機械学習によるストレス検出の洞察を開示

Insights into stress detection using machine learning.

イントロダクション

ストレスとは、身体や心が要求や挑戦的な状況に対して自然に反応することです。外部の圧力や内部の思考や感情に対する身体の反応です。仕事に関するプレッシャーや財政的な困難、人間関係の問題、健康上の問題、または重要な人生の出来事など、様々な要因によってストレスが引き起こされることがあります。データサイエンスと機械学習によるストレス検知インサイトは、個人や集団のストレスレベルを予測することを目的としています。生理学的な測定、行動データ、環境要因などの様々なデータソースを分析することで、予測モデルはストレスに関連するパターンやリスク要因を特定することができます。

この予防的アプローチにより、タイムリーな介入と適切なサポートが可能になります。ストレス予測は、健康管理において早期発見と個別化介入、職場環境の最適化に役立ちます。また、公衆衛生プログラムや政策決定にも貢献します。ストレスを予測する能力により、これらのモデルは個人やコミュニティの健康増進と回復力の向上に貢献する貴重な情報を提供します。

この記事は、データサイエンスブログマラソンの一部として公開されました。

機械学習を用いたストレス検知の概要

機械学習を用いたストレス検知は、データの収集、クリーニング、前処理を含みます。特徴量エンジニアリング技術を適用して、ストレスに関連するパターンを捉えることができる意味のある情報を抽出したり、新しい特徴を作成したりすることができます。これには、統計的な測定、周波数領域解析、または時間系列解析などが含まれ、ストレスの生理学的または行動的指標を捉えることができます。関連する特徴量を抽出またはエンジニアリングすることで、パフォーマンスを向上させることができます。

研究者は、ロジスティック回帰、SVM、決定木、ランダムフォレスト、またはニューラルネットワークなどの機械学習モデルを、ストレスレベルを分類するためのラベル付きデータを使用してトレーニングします。彼らは、正解率、適合率、再現率、F1スコアなどの指標を使用してモデルのパフォーマンスを評価します。トレーニングされたモデルを実世界のアプリケーションに統合することで、リアルタイムのストレス監視が可能になります。継続的なモニタリング、更新、およびユーザーフィードバックは、精度向上に重要です。

ストレスに関連する個人情報の扱いには、倫理的な問題やプライバシーの懸念を考慮することが重要です。個人のプライバシーや権利を保護するために、適切なインフォームドコンセント、データの匿名化、セキュアなデータストレージ手順に従う必要があります。倫理的な考慮事項、プライバシー、およびデータセキュリティは、全体のプロセスにおいて重要です。機械学習に基づくストレス検知は、早期介入、個別化ストレス管理、および健康増進に役立ちます。

データの説明

「ストレス」データセットには、ストレスレベルに関する情報が含まれています。データセットの特定の構造や列を持たない場合でも、パーセンタイルのためのデータ説明の一般的な概要を提供できます。

データセットには、年齢、血圧、心拍数、またはスケールで測定されたストレスレベルなど、数量的な測定を表す数値変数が含まれる場合があります。また、性別、職業カテゴリ、または異なるカテゴリ(低、VoAGI、高)に分類されたストレスレベルなど、定性的な特徴を表すカテゴリカル変数も含まれる場合があります。

# Array
import numpy as np

# Dataframe
import pandas as pd

#Visualization
import matplotlib.pyplot as plt
import seaborn as sns

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

#Data Reading
stress_c= pd.read_csv('/human-stress-prediction/Stress.csv')

# Copy
stress=stress_c.copy()

# Data
stress.head()

下記の関数を使用すると、データタイプをすばやく評価し、欠落またはnull値を検出することができます。大規模なデータセットを扱ったり、データのクリーニングや前処理タスクを実行する場合に有用です。

# Info
stress.info()

コードstress.isnull().sum()を使用して、「ストレス」データセット内のnull値をチェックし、各列のnull値の合計を計算してください。

# Checking null values
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]+'_Distribution')
    plt.pie(x=a,labels=lbl,autopct="%.1f %%")
    plt.show()

MatplotlibとSeabornライブラリは、「ストレス」データセットのカウントプロットを作成します。それは、異なるサブレディット間のストレスインスタンス数を、異なる色で区別されたストレスラベルとともに視覚化します。

plt.figure(figsize=(20,12))
plt.title('Subreddit wise stress count')
plt.xlabel('Subreddit')
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操作のためのNatural Language Tool Kitをインポート
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によるベクトル形式に変換するための自己定義関数
# ベクトル化器とロジスティック回帰によるモデルの作成

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 :',time()-t0)
    print('Accuracy: ',acc_lr_tf)
    print(10*'===========')
    print('Confusion Matrix: \n',conf)
    print(10*'

モデル評価

モデル評価は、トレーニングされたモデルのパフォーマンスと有効性を評価するための機械学習における重要なステップです。未知のデータに対する複数のモデルの一般化度合いや、目的を達成しているかどうかを測定することが含まれます。トレーニングされたモデルのパフォーマンスをテストデータ上で評価し、正確性、適合率、再現率、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')

モデルパフォーマンス比較

与えられたタスクに対して最も優れたパフォーマンスを発揮するモデルを特定するために、このステップは機械学習において重要です。モデルを比較する際には、明確な目的を持つことが重要です。正確性を最大化するか、速度を最適化するか、解釈可能性を優先するかにかかわらず、評価指標と技術は特定の目的と一致する必要があります。

モデルパフォーマンス比較においては、一貫性が重要です。すべてのモデルで一貫した評価指標を使用することで、公正かつ意味のある比較が可能となります。また、データをトレーニング、検証、テストの3つのセットに一貫して分割することも重要です。研究者がモデルを同じデータのサブセットで評価することで、モデルのパフォーマンスを公正に比較することができます。

これらの要素を考慮することにより、研究者は包括的かつ公正なモデルパフォーマンス比較を実施し、特定の問題に対するモデル選択に関する情報に基づいた意思決定を行うことができます。

# 比較のための表形式の作成
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('モデル評価の交差検証法による評価')
plt.xlabel('モデル')
plt.ylabel('F1スコア')
plt.boxplot(results,labels=model_name,showmeans=True)
plt.show()
     

F1スコアが両方の方法でかなり似ているため、今度は1つのデータを除外する方法を適用して、最も優れたパフォーマンスのモデルを構築します。

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()

予測

新しい入力データは前処理され、モデルの期待に合わせて特徴量が抽出されます。そして、抽出された特徴量に基づいて予測関数が使用されて予測が生成されます。最後に、予測は必要に応じて印刷されるか、さらなる分析や意思決定に利用されます。

data=["""I don't have the ability to cope with it anymore. I'm trying, 
      but a lot of things are triggering me, and I'm shutting down at work,
      just finding the place I feel safest, and staying there for an hour
      or two until I feel like I can do something again. I'm tired of watching
      my back, tired of traveling to places I don't feel safe, tired of 
      reliving that moment, tired of being triggered, tired of the stress,
      tired of anxiety and knots in my stomach, tired of irrational thought 
      when triggered, tired of irrational paranoia. I'm exhausted and need
      a break, but know it won't be enough until I journey the long road 
      through therapy. I'm not suicidal at all, just wishing this pain and 
      misery would end, to have my life back again."""]
      
data=vector.transform(data)
model_lr_tf.predict(data)

data=["""In case this is the first time you're reading this post... 
    We are looking for people who are willing to complete some 
    online questionnaires about employment and well-being which
    we hope will help us to improve services for assisting people
    with mental health difficulties to obtain and retain employment. 
    We are developing an employment questionnaire for people with 
    personality disorders; however we are looking for people from all 
    backgrounds to complete it. That means you do not need to have a 
    diagnosis of personality disorder – you just need to have an 
    interest in completing the online questionnaires. The questionnaires
     will only take about 10 minutes to complete online. For your
     participation, we’ll donate £1 on your behalf to a mental health 
     charity (Young Minds: Child & Adolescent Mental Health, Mental
      Health Foundation, or Rethink)"""]

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

結論

機械学習技術をストレスレベルの予測に応用することで、メンタルウェルビーイングに対する個人的な洞察が提供されます。血圧、心拍数などの数値測定値や(例えば、性別、職業などの)カテゴリカルな特性など、様々な要因を分析することで、機械学習モデルはパターンを学習し、個々のストレスレベルについて予測を行うことができます。正確にストレスレベルを検出・監視する能力により、機械学習はメンタルウェルビーイングを管理・向上するための積極的な戦略や介入の開発に貢献しています。

私たちは、ストレス予測に機械学習を使用することで得られる洞察と、この重要な問題に対するアプローチを革新する可能性を探求しました。

  • 正確な予測:機械学習アルゴリズムは、豊富な歴史データを分析してストレス発生を正確に予測し、貴重な洞察と予測を提供します。
  • 早期発見:機械学習は、早期に警告サインを検出し、脆弱な領域に対する積極的な対策や適時の支援を可能にします。
  • 計画とリソースの最適化:機械学習により、ストレスのホットスポットと強度を予測することができ、緊急サービスや医療施設などのリソースの割り当てを最適化することができます。
  • 公共の安全性の向上:機械学習予測によって発行される適時の警告と注意喚起により、個人が必要な予防措置を取ることができ、ストレスの影響を軽減し、公共の安全性を向上させることができます。

結論として、このストレス予測分析は、機械学習を使用したストレスレベルとその予測に関する貴重な洞察を提供します。この知見を活用して、ストレス管理のためのツールや介入を開発し、全体的なウェルビーイングと生活の質を向上させましょう。

よくある質問

この記事で使用されているメディアはAnalytics Vidhyaが所有しておらず、著者の自由裁量により使用されています。

We will continue to update VoAGI; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more