【sklearn】ロジステック回帰モデルの実装コード

python
  • 【python×sklearn】によるロジステック回帰モデルの実装方法
  • 分類境界線のプロットと境界式の出力
  • 学習済みモデルを使った新規データの推論結果確認

この記事では、ロジスティック回帰による2クラス分類を行い、その結果をわかりやすく出力します。

ロジステック回帰

学習データ

以下のようなデータが含まれる’train_data.csv’に対して、ロジステック回帰による2クラスの分類モデルを作成します。

# CSVファイル名
input_csv_filename = 'train_data.csv'

# データフレームを作成
df = pd.read_csv(input_csv_filename, names=['label', 'Intensity', 'Area'])

モデルの学習と分類境界表示

まずはロジステック回帰モデルの学習と結果を見てみます。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
import pandas as pd

# CSVファイル名
input_csv_filename = 'train_data.csv'

# データフレームを作成
df = pd.read_csv(input_csv_filename, names=['label', 'Intensity', 'Area'])

# データを取得
y = df['label']
X = df[['Intensity', 'Area']]

# ロジスティック回帰モデルを設定
model = LogisticRegression()

# モデルをトレーニング
model.fit(X, y)

# 分類境界をプロット
x_min, x_max = X['Intensity'].min() - 1, X['Intensity'].max() + 2
y_min, y_max = X['Area'].min() - 1000, X['Area'].max() + 1000
xx, yy = np.meshgrid(np.arange(x_min, x_max, 1), np.arange(y_min, y_max, 1))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

plt.contourf(xx, yy, Z, alpha=0.2, cmap=plt.cm.coolwarm)
plt.scatter(X['Intensity'], X['Area'], c=y, cmap=plt.cm.coolwarm)

# 軸ラベルとタイトル
plt.xlabel('Intensity')
plt.ylabel('Area')
plt.title('Logistic Regression Decision Boundary')

# グラフをファイルとして保存
plt.savefig('logistic_regression_results.png', dpi=300)
plt.show()

グラフの軸はデータセットに合わせて下の部分を調整してください。

# 分類境界をプロット
x_min, x_max = X['Intensity'].min() - 1, X['Intensity'].max() + 2
y_min, y_max = X['Area'].min() - 1000, X['Area'].max() + 1000

誤分類の少ないところに直線の境界線を引くことができています。

境界線の式を表示

次に決定境界の式を出力してみます。

# ロジスティック回帰モデルから重みベクトルとバイアスを取得
w = model.coef_[0]
b = model.intercept_[0]

# 境界線の式を表示
digits = 4 #表示する有効数字
print(f'境界線の式: {w[0]:.{digits}g}*Intensity + {w[1]:.{digits}g}*Area + {b:.{digits}g} = 0')

境界線の式: -0.3481*Intensity + -0.001779*Area + 18.95 = 0

この式が0を超えるときにクラス=0、0未満のときにクラス=1となります。

学習したモデルでテストデータの推論

続いて、学習したモデルに以下のような新たなデータ’test_data.csv’を与えて結果を出力してみます。

 <推論するコードと結果>

# 新たなCSVファイル名
input_new_csv_filename = 'test_data.csv'
output_csv_filename = 'prediction_results.csv'

# 新たなデータフレームを作成
new_df = pd.read_csv(input_new_csv_filename, names=['Intensity', 'Area'])

# 新たなデータから推論を行う
predictions = model.predict(new_df)

# 結果を新たなデータフレームに追加
new_df['Predicted_Label'] = predictions

# 結果をCSVファイルに出力
new_df.to_csv(output_csv_filename, index=False)
print(new_df)

# xx, yyの範囲を全データの範囲に基づいて更新
combined_df = pd.concat([df[['Intensity', 'Area']], new_df[['Intensity', 'Area']]])
x_min, x_max = combined_df['Intensity'].min() - 1, combined_df['Intensity'].max() + 2
y_min, y_max = combined_df['Area'].min() - 1000, combined_df['Area'].max() + 1000
xx, yy = np.meshgrid(np.arange(x_min, x_max, 1), np.arange(y_min, y_max, 1))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

# 推論結果をプロット
plt.contourf(xx, yy, Z, alpha=0.2, cmap=plt.cm.coolwarm)
plt.scatter(new_df['Intensity'], new_df['Area'], c=new_df['Predicted_Label'], cmap=plt.cm.coolwarm, edgecolors='k')

# 軸ラベルとタイトル
plt.xlabel('Intensity')
plt.ylabel('Area')
plt.title('Logistic Regression Prediction Results')

# グラフをファイルとして保存
plt.savefig('logistic_regression_prediction_results.png', dpi=300)
plt.show()

未知のデータに対してしっかり分類できていることが確認できました。

最後に全体のコードを載せておきます。

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LogisticRegression
import pandas as pd

# CSVファイル名
input_csv_filename = 'train_data.csv'

# データフレームを作成
df = pd.read_csv(input_csv_filename, names=['label', 'Intensity', 'Area'])

# データを取得
y = df['label']
X = df[['Intensity', 'Area']]

# ロジスティック回帰モデルを設定
model = LogisticRegression()

# モデルをトレーニング
model.fit(X, y)

# 分類境界をプロット
x_min, x_max = X['Intensity'].min() - 1, X['Intensity'].max() + 2
y_min, y_max = X['Area'].min() - 1000, X['Area'].max() + 1000
xx, yy = np.meshgrid(np.arange(x_min, x_max, 1), np.arange(y_min, y_max, 1))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

plt.contourf(xx, yy, Z, alpha=0.2, cmap=plt.cm.coolwarm)
plt.scatter(X['Intensity'], X['Area'], c=y, cmap=plt.cm.coolwarm)

# 軸ラベルとタイトル
plt.xlabel('Intensity')
plt.ylabel('Area')
plt.title('Logistic Regression Decision Boundary')

# グラフをファイルとして保存
plt.savefig('logistic_regression_results.png', dpi=300)
plt.show()

# ================= 決定境界の表示 ===================
# ロジスティック回帰モデルから重みベクトルとバイアスを取得
w = model.coef_[0]
b = model.intercept_[0]

# 境界線の式を表示
digits = 4 #表示する有効数字
print(f'境界線の式: {w[0]:.{digits}g}*Intensity + {w[1]:.{digits}g}*Area + {b:.{digits}g} = 0')

# ================= 推論と結果出力===================
# 新たなCSVファイル名
input_new_csv_filename = 'test_data.csv'
output_csv_filename = 'prediction_results.csv'

# 新たなデータフレームを作成
new_df = pd.read_csv(input_new_csv_filename, names=['Intensity', 'Area'])

# 新たなデータから推論を行う
predictions = model.predict(new_df)

# 結果を新たなデータフレームに追加
new_df['Predicted_Label'] = predictions

# 結果をCSVファイルに出力
new_df.to_csv(output_csv_filename, index=False)
print(new_df)

# xx, yyの範囲を全データの範囲に基づいて更新
combined_df = pd.concat([df[['Intensity', 'Area']], new_df[['Intensity', 'Area']]])
x_min, x_max = combined_df['Intensity'].min() - 1, combined_df['Intensity'].max() + 2
y_min, y_max = combined_df['Area'].min() - 1000, combined_df['Area'].max() + 1000
xx, yy = np.meshgrid(np.arange(x_min, x_max, 1), np.arange(y_min, y_max, 1))
Z = model.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

# 推論結果をプロット
plt.contourf(xx, yy, Z, alpha=0.2, cmap=plt.cm.coolwarm)
plt.scatter(new_df['Intensity'], new_df['Area'], c=new_df['Predicted_Label'], cmap=plt.cm.coolwarm, edgecolors='k')

# 軸ラベルとタイトル
plt.xlabel('Intensity')
plt.ylabel('Area')
plt.title('Logistic Regression Prediction Results')

# グラフをファイルとして保存
plt.savefig('logistic_regression_prediction_results.png', dpi=300)
plt.show()
タイトルとURLをコピーしました