机器学习为压力检测揭示了洞见

介绍

压力是身体和心理对具有挑战性或要求的情况的自然反应。它是身体对外部压力或内部思维和感觉反应的方式。压力可能由多种因素触发,如工作压力、财务困难、关系问题、健康问题或重大生活事件。由数据科学和机器学习驱动的压力检测洞见旨在预测个体或人群的压力水平。通过分析多种数据源,如生理测量、行为数据和环境因素,预测模型可以识别与压力相关的模式和风险因素。

这种积极主动的方法使得及时干预和定制支持成为可能。压力预测在医疗保健方面具有早期发现和个性化干预的潜力,也可以用于优化工作环境。它还可以为公共卫生倡议和政策决策提供信息。通过预测压力,这些模型提供了有价值的洞见,以改善个体和社区的福祉和增强其韧性。

本文作为数据科学博客马拉松的一部分发表。

使用机器学习进行压力检测的概述

使用机器学习进行压力检测涉及收集、清洗和预处理数据。应用特征工程技术以提取有意义的信息或创建新特征,以捕获与压力相关的模式。这可能涉及提取统计量、频域分析或时间序列分析,以捕获压力的生理或行为指标。提取或工程化相关特征以提高性能。

研究人员利用标记数据训练机器学习模型,如逻辑回归、支持向量机、决策树、随机森林或神经网络,以分类压力水平。他们使用准确性、精确度、召回率和F1分数等度量来评估模型的性能。将训练好的模型集成到实际应用程序中,实现实时压力监测。持续监测、更新和用户反馈对于提高准确性至关重要。

在处理与压力相关的敏感个人数据时,考虑到伦理问题和隐私问题是至关重要的。应遵循适当的知情同意、数据匿名化和安全数据存储程序,以保护个人的隐私和权利。在整个过程中,伦理考虑、隐私和数据安全都很重要。基于机器学习的压力检测使早期干预、个性化压力管理和提高福祉成为可能。

数据描述

“压力”数据集包含与压力水平相关的信息。没有特定结构和列的数据集,可以提供有关百分位数数据描述的一般概述。

数据集可能包含代表定量测量的数值变量,如年龄、血压、心率或按比例测量的压力水平。它还可以包括代表定性特征的分类变量,如性别、职业类别或将压力水平分类为不同类别(低、中、高)。

# 数组
import numpy as np

# 数据框
import pandas as pd

#可视化
import matplotlib.pyplot as plt
import seaborn as sns

# 警告
import warnings
warnings.filterwarnings('ignore')

# 数据读取
stress_c= pd.read_csv('/human-stress-prediction/Stress.csv')

# 拷贝
stress=stress_c.copy()

# 数据
stress.head()

下面的函数允许您快速评估数据类型并查找缺失或空值。当处理大型数据集或执行数据清理和预处理任务时,此摘要很有用。

# 信息
stress.info()

使用代码stress.isnull().sum()检查“压力”数据集中是否存在空值,并计算每列中空值的总和。

# 检查空值
stress.isnull().sum()

生成关于“压力”数据集的统计信息。编译此代码,您将获得数据集中每个数值列的描述性统计摘要。

# 统计信息
stress.describe()

探索性数据分析(EDA)

探索性数据分析(EDA)是了解和分析数据集的关键步骤。它涉及对数据进行视觉探索和总结其主要特征、模式和关系。

lst=['subreddit','label']
plt.figure(figsize=(15,12))
for i in range(len(lst)):
    plt.subplot(1,2,i+1)
    a=stress[lst[i]].value_counts()
    lbl=a.index
    plt.title(lst[i]+'_分布')
    plt.pie(x=a,labels=lbl,autopct="%.1f %%")
    plt.show()

Matplotlib和Seaborn库为“压力”数据集创建了一个计数图。它可视化了不同子论坛中“压力”实例的计数,压力标签通过不同的颜色进行区分。

plt.figure(figsize=(20,12))
plt.title('子论坛压力计数')
plt.xlabel('子论坛')
sns.countplot(data=stress,x='subreddit',hue='label',palette='gist_heat')
plt.show()

文本预处理

文本预处理是将原始文本数据转换为更干净和结构化的格式,适合于分析或建模任务。它特别涉及一系列步骤,以消除噪音、规范化文本和提取相关特征。这里我添加了所有相关的文本处理库。

# 正则表达式
import re 

# 处理字符串
import string

# NLP 工具
import spacy

nlp=spacy.load('en_core_web_sm')
from spacy.lang.en.stop_words import STOP_WORDS

# 导入自然语言工具包进行 NLP 操作
import nltk
nltk.download('stopwords')
nltk.download('wordnet')
nltk.download('punkt')
nltk.download('omw-1.4')                                
from nltk.stem import WordNetLemmatizer

from wordcloud import WordCloud, STOPWORDS
from nltk.corpus import stopwords
from collections import Counter

文本预处理中常用的一些技术包括:

文本清洗

  • 删除特殊字符: 删除标点符号、符号或不包含在文本含义中的非字母数字字符。
  • 删除数字: 如果数字与分析无关,则删除数字。
  • 小写: 将所有文本转换为小写,以确保文本匹配和分析的一致性。
  • 删除停用词: 删除不包含太多信息的常用词,例如“a”、“the”、“is”等。

分词

  • 将文本分割成单词或标记: 将文本分割成单个单词或标记,以便进行进一步的分析。研究人员可以通过使用空格或更高级的分词技术,例如利用NLTK或spaCy等库来实现这一点。

标准化

  • 词形还原:将单词缩减为其基本或词典形式(词形)。例如,将“running”和“ran”转换为“run”。
  • 词干提取:通过删除前缀或后缀将单词缩减为其基本形式。例如,将“running”和“ran”转换为“run”。
  • 去除变音符号:从字符中去除重音符号或其他变音符号。
#定义预处理函数
def preprocess(text,remove_digits=True):
    text = re.sub('\W+',' ', text)                                       
    text = re.sub('\s+',' ', text)                                       
    text = re.sub("(?<!\w)\d+", "", text)                                
    text = re.sub("-(?!\w)|(?<!\w)-", "", text)                          
    text=text.lower()
    nopunc=[char for char in text if char not in string.punctuation]    
    nopunc=''.join(nopunc)
    nopunc=' '.join([word for word in nopunc.split()
               if word.lower() not in stopwords.words('english')])  
    
    
    return nopunc
# 定义词形还原函数
def lemmatize(words):
   
    words=nlp(words)
    lemmas = []
    for word in words:
        
        lemmas.append(word.lemma_)
    return lemmas



#将它们转换为字符串
def listtostring(s):
    str1=' '
    return (str1.join(s))

def clean_text(input):
    word=preprocess(input)
    lemmas=lemmatize(word)
    return listtostring(lemmas)

# 创建一个特征来存储干净的文本
stress['clean_text']=stress['text'].apply(clean_text)
stress.head()

机器学习模型构建

机器学习模型构建是创建数学表示或模型的过程,该模型可以学习模式并从数据中进行预测或决策。它涉及使用带标签的数据集训练模型,然后使用该模型对新的未见过的数据进行预测。

从可用数据中选择或创建相关特征。特征工程旨在从原始数据中提取有意义的信息,以帮助模型有效地学习模式。

#向量化
from sklearn.feature_extraction.text import TfidfVectorizer

# 模型构建
from sklearn.model_selection import GridSearchCV,StratifiedKFold,
          KFold,train_test_split,cross_val_score,cross_val_predict
from sklearn.linear_model import LogisticRegression,SGDClassifier
from sklearn import preprocessing
from sklearn.naive_bayes import MultinomialNB
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import StackingClassifier,RandomForestClassifier,
                        AdaBoostClassifier
from sklearn.neighbors import KNeighborsClassifier

#模型评估
from sklearn.metrics import confusion_matrix,classification_report,
                              accuracy_score,f1_score,precision_score
from sklearn.pipeline import Pipeline

# 时间
from time import time

# 定义ML模型构建的目标和特征
x=stress['clean_text']
y=stress['label']
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3,random_state=1)

根据问题的性质和数据的特征选择或创建合适的机器学习算法或模型架构。不同的模型,例如决策树、支持向量机或神经网络,具有不同的优点和缺点。

使用标记的数据训练所选模型。该步骤涉及将训练数据馈送到模型中,并允许其学习特征和目标变量之间的模式和关系。

#自定义函数,通过tf idf vectorizer将数据转换为向量形式
#并使用逻辑回归分类器对其进行分类和创建模型

def model_lr_tf(x_train, x_test, y_train, y_test):
    global acc_lr_tf,f1_lr_tf
    # 文本向量转换
    vector = TfidfVectorizer()
    x_train = vector.fit_transform(x_train)
    x_test = vector.transform(x_test)
 
    ovr = LogisticRegression()
    
    #将训练数据拟合到模型中并进行预测
    t0 = time()

    ovr.fit(x_train, y_train)
    
    y_pred = ovr.predict(x_test)
    
    # 模型评估
    
    conf=confusion_matrix(y_test,y_pred)
    acc_lr_tf=accuracy_score(y_test,y_pred)
    f1_lr_tf=f1_score(y_test,y_pred,average='weighted')
    print('时间 :',time()-t0)
    print('准确率: ',acc_lr_tf)
    print(10*'===========')
    print('混淆矩阵: \n',conf)
    print(10*'===========')
    print('分类报告: \n',classification_report(y_test,y_pred))
    
    
    return y_test,y_pred,acc_lr_tf

# 自定义函数,通过tf idf vectorizer将数据转换为向量形式
#并使用MultinomialNB分类器对其进行分类和创建模型

def model_nb_tf(x_train, x_test, y_train, y_test):
    global acc_nb_tf,f1_nb_tf
    # 文本向量转换 
    vector = TfidfVectorizer()
    x_train = vector.fit_transform(x_train)
    x_test = vector.transform(x_test)

    ovr = MultinomialNB()
    
    #将训练数据拟合到模型中并进行预测
    t0 = time()
    
    ovr.fit(x_train, y_train)
    
    y_pred = ovr.predict(x_test)
    
    # 模型评估
    
    conf=confusion_matrix(y_test,y_pred)
    acc_nb_tf=accuracy_score(y_test,y_pred)
    f1_nb_tf=f1_score(y_test,y_pred,average='weighted')
    print('时间 : ',time()-t0)
    print('准确率: ',acc_nb_tf)
    print(10*'===========')
    print('混淆矩阵: \n',conf)
    print(10*'===========')
    print('分类报告: \n',classification_report(y_test,y_pred

模型评估

模型评估是机器学习中的关键步骤,用于评估训练模型的性能和有效性。它涉及测量多个模型如何推广到未见过的数据以及它是否满足所需的目标。评估训练模型在测试数据上的性能。计算评估指标,如准确度、精确度、召回率和 F1 分数,以评估模型在应力检测方面的有效性。模型评估提供有关模型的优势、劣势以及其适用性的见解。

# 评估模型

print('********************逻辑回归*********************')
print('\n')
model_lr_tf(x_train, x_test, y_train, y_test)
print('\n')
print(30*'==========')
print('\n')
print('********************多项式朴素贝叶斯*********************')
print('\n')
model_nb_tf(x_train, x_test, y_train, y_test)
print('\n')
print(30*'==========')
print('\n')
print('********************决策树*********************')
print('\n')
model_dt_tf(x_train, x_test, y_train, y_test)
print('\n')
print(30*'==========')
print('\n')
print('********************KNN*********************')
print('\n')
model_knn_tf(x_train, x_test, y_train, y_test)
print('\n')
print(30*'==========')
print('\n')
print('********************随机森林*********************')
print('\n')
model_rf_tf(x_train, x_test, y_train, y_test)
print('\n')
print(30*'==========')
print('\n')
print('********************自适应提升*********************')
print('\n')
model_ab_tf(x_train, x_test, y_train, y_test)
print('\n')
print(30*'==========')
print('\n')

模型性能比较

这是机器学习中的关键步骤,用于确定给定任务的最佳性能模型。比较模型时,重要的是要有明确的目标。无论是最大化准确性、优化速度还是优先考虑可解释性,评估指标和技术都应与具体目标相一致。

在模型性能比较中,一致性是关键。在所有模型中使用一致的评估指标可以确保公正且有意义的比较。同样重要的是要将数据分成训练、验证和测试集,并在所有模型中保持一致。通过确保模型在相同的数据子集上进行评估,研究人员可以公平比较它们的性能。

考虑到这些因素,研究人员可以进行全面且公正的模型性能比较,这将导致对特定问题的模型选择做出明智决策。

# 创建表格格式以进行更好的比较
tbl=pd.DataFrame()
tbl['Model']=pd.Series(['逻辑回归','多项式朴素贝叶斯',
            '决策树','KNN','随机森林','自适应提升'])
tbl['Accuracy']=pd.Series([acc_lr_tf,acc_nb_tf,acc_dt_tf,acc_knn_tf,
                  acc_rf_tf,acc_ab_tf])
tbl['F1_Score']=pd.Series([f1_lr_tf,f1_nb_tf,f1_dt_tf,f1_knn_tf,
                  f1_rf_tf,f1_ab_tf])
tbl.set_index('Model')
# 基于 F1 分数的最佳模型
tbl.sort_values('F1_Score',ascending=False)

交叉验证以避免过拟合

当训练机器学习模型时,交叉验证确实是一种有价值的技术,可以帮助避免过拟合。通过使用多个数据子集进行训练和测试,它提供了模型性能的稳健评估。通过估计模型在未见数据上的性能,有助于评估模型的泛化能力。

# 使用交叉验证方法避免过拟合
import statistics as st
vector = TfidfVectorizer()

x_train_v = vector.fit_transform(x_train)
x_test_v  = vector.transform(x_test)

# 模型构建
lr =LogisticRegression()
mnb=MultinomialNB()
dct=DecisionTreeClassifier(random_state=1)
knn=KNeighborsClassifier()
rf=RandomForestClassifier(random_state=1)
ab=AdaBoostClassifier(random_state=1)
m  =[lr,mnb,dct,knn,rf,ab]
model_name=['Logistic R','MultiNB','DecTRee','KNN','R forest','Ada Boost']

results, mean_results, p, f1_test=list(),list(),list(),list()

#模型拟合、交叉验证和性能评估
def algor(model):
    print('\n',i)
    pipe=Pipeline([('model',model)])
    pipe.fit(x_train_v,y_train)
    cv=StratifiedKFold(n_splits=5)
    n_scores=cross_val_score(pipe,x_train_v,y_train,scoring='f1_weighted',
                  cv=cv,n_jobs=-1,error_score='raise') 
    results.append(n_scores)
    mean_results.append(st.mean(n_scores))
    print('f1-Score(train): mean= (%.3f), min=(%.3f)) ,max= (%.3f), 
                    stdev= (%.3f)'%(st.mean(n_scores), min(n_scores),
                       max(n_scores),np.std(n_scores)))
    y_pred=cross_val_predict(model,x_train_v,y_train,cv=cv)
    p.append(y_pred)
    f1=f1_score(y_train,y_pred, average = 'weighted')
    f1_test.append(f1)
    print('f1-Score(test): %.4f'%(f1))

for i in m:
    algor(i)

#通过可视化进行模型比较
fig=plt.subplots(figsize=(20,15))
plt.title('MODEL EVALUATION BY CROSS VALIDATION METHOD')
plt.xlabel('MODELS')
plt.ylabel('F1 Score')
plt.boxplot(results,labels=model_name,showmeans=True)
plt.show()
     

由于模型的F1分数在两种方法中都非常相似。因此,现在我们正在应用留一法来构建最佳表现模型。

x=stress['clean_text']
y=stress['label']
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3,random_state=1)

vector = TfidfVectorizer()
x_train = vector.fit_transform(x_train)
x_test = vector.transform(x_test)
model_lr_tf=LogisticRegression()

model_lr_tf.fit(x_train,y_train)
y_pred=model_lr_tf.predict(x_test)

#模型评估
conf=confusion_matrix(y_test,y_pred)
acc_lr=accuracy_score(y_test,y_pred)
f1_lr=f1_score(y_test,y_pred,average='weighted')

print('Accuracy: ',acc_lr)
print('F1 Score: ',f1_lr)
print(10*'===========')
print('Confusion Matrix: \n',conf)
print(10*'===========')
print('Classification Report: \n',classification_report(y_test,y_pred))

压力词和非压力词的词云

该数据集包含被标记为压力和非压力的文本消息或文档。该代码通过循环遍历这两个标签来创建每个标签的词云,使用WordCloud库并显示词云可视化。每个词云代表各自类别中最常用的单词,较大的单词表示较高的频率。颜色图的选择("winter"、"autumn"、"magma"、"viridis"、"plasma")决定了词云的颜色方案。生成的可视化提供了与压力和非压力消息或文档相关的最频繁单词的简洁表示。

以下是代表与压力检测常见相关的压力和非压力词的词云:

for label, cmap in zip([0,1],
                       ['winter', 'autumn', 'magma', 'viridis', 'plasma']):
    text = stress.query('label == @label')['text'].str.cat(sep=' ')
    plt.figure(figsize=(12, 9))
    wc = WordCloud(width=1000, height=600, background_color="#f8f8f8", colormap=cmap)
    wc.generate_from_text(text)
    plt.imshow(wc)
    plt.axis("off")
    plt.title(f"Words Commonly Used in ${label}$ Messages", size=20)
    plt.show()

预测

新的输入数据被预处理并提取特征以匹配模型的期望。然后,使用predict函数基于提取的特征生成预测。最后,根据需要打印或利用预测进行进一步的分析或决策。

data=["""我已经没有能力再应对它了。我正在努力,
      但很多事情都在触发我,我在工作中关掉了,
      只找到我感到最安全的地方,呆在那里一两个小时,
      直到我感觉自己可以再做些事情。我厌倦了看着
      我的背,厌倦了去我觉得不安全的地方旅行,厌倦了
      重新经历那个时刻,厌倦了被触发,厌倦了压力,
      厌倦了胃里的焦虑和结,厌倦了被触发时的非理性思想,
      厌倦了非理性的偏执狂。我筋疲力尽,需要
      休息,但知道这不够,直到我经过漫长的道路
      通过治疗。我一点也不想自杀,只是希望这种痛苦和
      苦难会结束,重新拥有我的生活。"""]
      
data=vector.transform(data)
model_lr_tf.predict(data)

data=["""如果这是你第一次阅读这篇文章......
    我们正在寻找愿意完成一些在线问卷调查的人,
    这些问卷调查涉及就业和福祉,我们希望这些问卷调查能够帮助我们
    改善为患有心理健康问题的人提供就业援助服务的质量。
    我们正在为患有人格障碍的人开发就业问卷调查;
    然而,我们正在寻找来自各个背景的人来完成它。
    这意味着您不需要被诊断为人格障碍 - 您只需要有兴趣
    完成在线问卷调查。问卷调查只需要大约10分钟的时间。
    为了感谢您的参与,我们将代表您向心理健康慈善机构(Young Minds:儿童和青少年心理健康,心理健康基金会或Rethink)捐赠1英镑"""]

data=vector.transform(data)
model_lr_tf.predict(data)

结论

机器学习技术在预测压力水平方面的应用为心理健康提供了个性化的见解。通过分析各种因素,如数值测量(血压、心率)和分类特征(例如性别、职业),机器学习模型可以学习模式并对个人的压力水平进行预测。通过准确检测和监测压力水平的能力,机器学习有助于开发积极的策略和干预措施,以管理和增强心理健康。

我们探讨了使用机器学习进行压力预测的见解以及其革命性改变我们解决这一关键问题的方法的潜力。

  • 准确的预测:机器学习算法分析大量的历史数据,准确预测压力发生情况,提供有价值的见解和预测。
  • 早期检测:机器学习可以早期检测预警信号,允许在易受攻击的领域采取积极的措施和及时的支持。
  • 增强规划和资源分配:机器学习使得压力高发区和强度的预测成为可能,优化资源的分配,如紧急服务和医疗设施的分配。
  • 提高公共安全性:通过机器学习预测发出及时的警报和警告,使个人能够采取必要的预防措施,减少压力的影响,提高公共安全性。

总之,这种压力预测分析为压力水平及其使用机器学习的预测提供了有价值的见解。利用这些发现开发应对压力的工具和干预措施,促进整体健康和提高生活质量。

常见问题

本文中显示的媒体不归Analytics Vidhya所有,作者自行决定使用。