CRAIDでブリッジエンジニアをしているYoshimuraです。
普段ともに仕事しているセブ在住エンジニアのJamesさんが投稿したテック記事を翻訳・加筆しましたので、当記事で紹介いたします。
英語を勉強されている方は、ぜひ当記事で日本語で理解した上で、英語記事を読んで頂くと分かり易いと思います。ご一緒にどうぞ。
翻訳元記事(オフショア子会社Full Speed Technologiesの技術ブログ)
なお、当記事内で扱うデータやコードは章末にリンクがございます。目次からご確認下さい。
ロジスティック回帰分析とは
ロジスティック回帰分析は、最も一般的な教師あり学習(機械学習)の 1 つです。「はい」か「いいえ」、「真」か「偽」など、発生するバイナリ(2進数)の事象を予測するために使用します。
但し、当記事では2つ以上の分類を扱います。モデルに入力するデータセットは、数値データとテキストデータの組み合わせとなります。分析の結果、各分類を反映した確率を表す数値が出力されます。

加筆:上の図のように、年齢、性別、給与からYes/Noの確率を予想する分析です。専門的な用語で説明すると、教師あり学習では、データセットの要因(説明変数)からバイナリの結果(目的変数)が起こる確立を予測する統計手法で、多変量解析手法の1つです。人間が予めデータセットを分析し、バイナリのラベルを定めた上で、機械に学習させ、データセットに対するバイナリの予測を行うモデルを構築します。おしゃれさ、かっこよさ、優しさなどを数値化して、とある誰かさんが彼女と付き合えるか確率を予想するイメージです。ほんまかいなw
診断に扱うデータセット
背景として、教師あり機械学習は、モデルに与えるデータセットに入力と出力の両方がある種類の機械学習です。今回使用するサンプル データには、入力と出力の両方が含まれています。ロジスティック回帰分析は、ターゲット変数 (説明変数)がカテゴリ分けされていたり、分類されている場合に使用する事ができます。仕様例としては、電子メールがスパムであるかどうかの検出であったり、出力が分類 A、 B、 C などのパターンに分かれるような問題の検出などです。
当記事では、列数の少ないデータに基づいて、Python を使用し単純なロジスティック回帰モデルを実装・作成します。現実の分析では、通常、更に多くの列数のデータを利用します。

今回使用する上記データには 7 つの列があります。加筆:左から体温、体の痛み、鼻水、自宅の同居人数、在宅勤務、コロナワクチン摂取済み、診察結果(インフルエンザ、新型コロナ感染、風邪)の列となっております。
機械学習において、最初の 6 列は入力として使用し、最後の列 (予測) は出力として使用します。当データは単なる模擬データであり、医療施設提供のものではありません。当データのCSVには75 行分のデータがあり、このデモンストレーションには十分ですが、現実世界の分析設定や研究には恐らく不十分です。
Pythonによるロジスティック回帰分析
入力データ準備とデータ傾向の理解
ライブラリインポート
ロジスティック回帰モデルに当データを入力する為に、まず必要なライブラリをインポートします。
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegressionpandasは、CSVデータの読み込みに使用します。加筆:pandasはPythonのデータ解析用ライブラリ。
pyplotは、データ傾向の理解目的で一部のデータを視覚化するためにのみ使用されます。加筆:matplotlibはPythonのグラフ描画用ライブラリ。
sklearn の LogisticRegressionは、ロジスティック回帰モデルの作成に使用するライブラリです。加筆:scikit-learn (sklearn)はPythonの機械学習ライブラリ。
CSVの読み込み
dataset = pd.read_csv('flu_covid_colds_activity.csv')flu_covid_colds_activity.csvというCSVからデータ全体をdataset変数に取り込みます。dataset変数には、6 つの全入力列と 1 つの出力列が含まれるようになりました。
データ傾向の理解
plt.ylabel('Prognosis')
plt.xlabel('Temperature')
plt.scatter(dataset.temperature, dataset.prognosis)
plt.show()
plt.ylabel('Prognosis')
plt.xlabel('Num People at Home')
plt.scatter(dataset.num_people_at_home, dataset.prognosis)
plt.show()このデモでは、2 つのグラフを表示します。1 つのグラフは診察結果(Y列)と体温(X列)の関係を示し、もう 1 つのグラフは診察結果(Y列)と患者の自宅の同居人数(X列)の関係を示します。
加筆:ylabelやxlabelは表のラベル設定を行います。scatter関数にdataset変数の体温と診察結果を渡して、show関数でグラフが表示されます。2つ目のグラフも同様で、簡単にグラフが表示できますね!

2 つのグラフから、インフルエンザ、風邪、新型コロナ感染の 3 つの出力分類間にクラスターがあることがはっきりとわかります。他の入力と予測出力列でもグラフ化できますが、今のところはこれで十分に傾向が見て取れます。
テキストデータの数値化
# Convert strings to numeric
dataset.body_aches = dataset.body_aches.replace(to_replace=['no', 'yes'], value=[0, 1])
dataset.runny_nose = dataset.runny_nose.replace(to_replace=['no', 'yes'], value=[0, 1])
dataset.working_at_home = dataset.working_at_home.replace(to_replace=['no', 'yes'], value=[0, 1])
dataset.covid_vaccinated = dataset.covid_vaccinated.replace(to_replace=['no', 'yes'], value=[0, 1])
dataset.prognosis = dataset.prognosis.replace(to_replace=['flu', 'covid', 'colds'], value=[0, 1, 2])LogisticRegression関数では機械学習中に文字列値 (yes/no) が許可されない為、数値形式 (いいえ→ 0、はい→ 1など)に変換します。上記コードによりyes/no 値を持つすべての入力列が数値に変換されました。また、出力の診察結果列も数値に変換されました。(インフルエンザ→ 0、新型コロナ感染→ 1、風邪→2)
加筆:replace関数に変換前と変換後の配列を渡す事で、dataset変数のbody_achesを変換し、元のbody_achesを上書いてますね。

上図は変換後のdataset変数の内容です。すべての文字の列が数値に変換されました。
また、後ほど分析対象のデータに対しても入力データの文字列を数値に変換します。
ロジスティック回帰モデル作成
# Create the Logistic Regression Model
model = LogisticRegression(max_iter=500)
model.fit(dataset[[
'temperature',
'body_aches',
'runny_nose',
'num_people_at_home',
'working_at_home',
'covid_vaccinated'
]], dataset.prognosis)LogisticRegression関数を使用してモデルを作成します。max_iter パラメーターは、モデルが機械学習する反復回数を定義します。データ行が数行しかない為、このパラメーターに値 500 を指定し、反復して学習するようにしました。
model.fit関数(加筆:ロジスティック回帰モデルの重みを学習)には2つのパラメータがあります。最初のパラメータは 6 列のデータを含む入力用で、2つ目のパラメータは診察結果の出力用です。
テスト用データ準備
# Test the model
test_temperature = 39
test_body_aches = 'yes'
test_runny_nose = 'yes'
test_num_people_at_home = 3
test_working_at_home = 'no'
test_covid_vaccinated = 'no'ロジスティック回帰モデルの作成と機械学習が完了したので、テストしましょう。CSV の 3 行目の値を使用してモデルをテストします。この行の診察結果はサンプルデータ同様の新型コロナ感染であれば正解ですね。
# Convert the test values to numeric
test_body_aches = 1 if test_body_aches == 'yes' else 0
test_runny_nose = 1 if test_runny_nose == 'yes' else 0
test_working_at_home = 1 if test_working_at_home == 'yes' else 0
test_covid_vaccinated = 1 if test_covid_vaccinated == 'yes' else 0この変換コードは、モデルの機械学習の書き方と少し異なりますね。大切なのは、モデル構築時と同じようにno→0、yes→1 はとなるように変換することです。
ロジスティック回帰分析の実行
output = model.predict_proba([[
test_temperature,
test_body_aches,
test_runny_nose,
test_num_people_at_home,
test_working_at_home,
test_covid_vaccinated
]])modelのpredict_proba関数 を使用して、各出力分類の確率を計算します。出力には 3 つの分類があるため、出力には 3 つの値が含まれている必要があります。インフルエンザ→ 0、新型コロナ感染→ 1、風邪→2のように、出力列の変換を割り当てたので、それぞれの確率を出力する必要があります。これらの 3 つの出力値はテスト用データの確率を表すため、加算すると 1 になるはずです。
print("FLU\t", "{:.4f}".format(output[0][0]))
print("COVID\t", "{:.4f}".format(output[0][1]))
print("COLDS\t", "{:.4f}".format(output[0][2]))このコードで出力をフォーマット化します。出力数値は小数点以下 4 桁に四捨五入されます。テストに使用するデータはCSV の 3 行目であり、最も高い確率で新型コロナ感染になるはずでしたね。

予想通り、最も確率が高いクラスは COVID 分類です。その為、この検査対象者が新型コロナに感染している確率は 0.96、つまり 96% です。インフルエンザと風邪の確率は十分に低いです。
ソースコード
当記事で使用したコードとCSVは当リポジトリに格納しております。
https://github.com/jamesnogra/SimpleLogisticRegressionPython
インストール手順を記載しております。Python 3.6 以降を搭載したPC/Macでの実行を想定しております。
加筆:レポジトリからソースコードとローカルに落として頂き、pip/Pythonの実行環境を整えた上で、以下を実行コマンドを頂くと、当記事内で説明したpandas/matplotlib/scikit-learnのライブラリがインストールされます。
pip install -r requirements.txt;python logistic.py;


