Python PlatoBlockchain データ インテリジェンスにおけるロジスティック回帰の決定版ガイド。垂直検索。あい。

Python でのロジスティック回帰の決定版ガイド

概要

時々混同される 線形回帰 初心者による – 用語の共有による 回帰ロジスティック回帰 とは大きく異なります 線形回帰. 線形回帰では、2、2.45、6.77、または 連続値、それを 回帰 アルゴリズム、 ロジスティック回帰 0 または 1、1 または 2 または 3 などの値を予測します。 離散値、それを 分類 アルゴリズム。 はい、呼ばれています 回帰 しかし、 分類 アルゴリズム。 詳しくは後ほど。

したがって、データ サイエンスの問題に連続値が含まれる場合は、 回帰 アルゴリズム (線形回帰はその XNUMX つです)。 それ以外の場合、入力、離散値、またはクラスの分類が含まれる場合は、 分類 アルゴリズム (ロジスティック回帰はその XNUMX つです)。

このガイドでは、Scikit-Learn ライブラリを使用して Python でロジスティック回帰を実行します。 という言葉の理由についても説明します。 「回帰」 名前とロジスティック回帰の仕組みに含まれています。

そのために、まず、分類、視覚化、および前処理されるデータを読み込みます。 次に、そのデータを理解するロジスティック回帰モデルを構築します。 次に、このモデルが評価され、新しい入力に基づいて値を予測するために使用されます。

動機

あなたが働いている会社は、トルコの農業農場と提携していました。 このパートナーシップには、カボチャの種の販売が含まれます。 カボチャの種は、人間の栄養にとって非常に重要です。 炭水化物、脂肪、タンパク質、カルシウム、カリウム、リン、マグネシウム、鉄、亜鉛がかなりの割合で含まれています。

データ サイエンス チームでは、データを使用してカボチャの種の種類を区別することがあなたの仕事です。 分類 種子の種類別のデータ。

トルコの農場では、XNUMX 種類のカボチャの種を扱っています。 チェルチェヴェリク もう一方 ウルギュップ・シヴリーシ.

カボチャの種を分類するために、あなたのチームは 2021 年の論文に従いました 「カボチャの種 (Cucurbita pepo L.) の分類における機械学習手法の使用。 遺伝資源と作物の進化」 Koklu、Sarigil、および Ozbek から - この論文では、画像から種子の測定値を撮影して抽出するための方法論があります。

論文に記載されているプロセスを完了した後、次の測定値が抽出されました。

  • エリア – カボチャの種の境界内のピクセル数
  • 周囲 – カボチャの種のピクセル単位の円周
  • 主軸の長さ – カボチャの種のピクセル単位の円周
  • 短軸の長さ – カボチャの種の短軸距離
  • 偏心 – カボチャの種の偏心
  • 凸部 – カボチャの種によって形成された領域での最小の凸状シェルのピクセル数
  • エクステント – 境界ボックスのピクセルに対するカボチャの種の面積の比率
  • 等価直径 – カボチャの種の面積を XNUMX で割った値の平方根を pi で割った値
  • コンパクトさ – 同じ円周を持つ円の面積に対するカボチャの種の面積の割合
  • 固まり – かぼちゃの種の凸と凸の状態
  • 真円度 – エッジの歪みを考慮しないカボチャの種の楕円率
  • アスペクト比 – かぼちゃの種の縦横比

これらは、使用する必要がある測定値です。 測定以外にも、 CLASS XNUMX 種類のカボチャの種のラベル。

シードの分類を開始するには、データをインポートして見てみましょう。

データセットを理解する

注: カボチャのデータセットをダウンロードできます こちら.

データセットをダウンロードした後、次を使用してデータフレーム構造にロードできます。 pandas 図書館。 エクセルファイルなので、 read_excel() 方法:

import pandas as pd

fpath = 'dataset/pumpkin_seeds_dataset.xlsx' 
df = pd.read_excel(fpath)

データが読み込まれたら、次のコマンドを使用して最初の 5 行をすばやく確認できます。 head() 方法:

df.head() 

この結果:

	Area 	Perimeter 	Major_Axis_Length 	Minor_Axis_Length 	Convex_Area 	Equiv_Diameter 	Eccentricity 	Solidity 	Extent 	Roundness 	Aspect_Ration 	Compactness 	Class
0 	56276 	888.242 	326.1485 			220.2388 			56831 			267.6805 		0.7376 			0.9902 		0.7453 	0.8963 		1.4809 			0.8207 			Çerçevelik
1 	76631 	1068.146 	417.1932 			234.2289 			77280 			312.3614 		0.8275 			0.9916 		0.7151 	0.8440 		1.7811 			0.7487 			Çerçevelik
2 	71623 	1082.987 	435.8328 			211.0457 			72663 			301.9822 		0.8749 			0.9857 		0.7400 	0.7674 		2.0651 			0.6929 			Çerçevelik
3 	66458 	992.051 	381.5638 			222.5322 			67118 			290.8899 		0.8123 			0.9902 		0.7396 	0.8486 		1.7146 			0.7624 			Çerçevelik
4 	66107 	998.146 	383.8883 			220.4545 			67117 			290.1207 		0.8187 			0.9850 		0.6752 	0.8338 		1.7413 			0.7557 			Çerçevelik

ここでは、それぞれの列にすべての測定値があります。 機能を使用そしてまた CLASS コラム、私たちの ターゲット、これはデータフレームの最後のものです。 を使用して、測定値の数を確認できます。 shape 属性:

df.shape 

出力は次のとおりです。

(2500, 13)

形状の結果は、データセットに 2500 のエントリ (または行) と 13 の列があることを示しています。 ターゲット列が 12 つあることがわかっているので、これは XNUMX 個の特徴列があることを意味します。

これで、ターゲット変数であるカボチャの種を調べることができます Class. その変数を予測するので、各カボチャの種のサンプル数を確認するのは興味深いことです。 通常、クラス内のインスタンス数の差が小さいほど、サンプルのバランスが取れ、予測が向上します。

この検査は、各シード サンプルをカウントすることで実行できます。 value_counts() 方法:

df['Class'].value_counts() 

上記のコードは次を表示します。

Çerçevelik       1300
Ürgüp Sivrisi    1200
Name: Class, dtype: int64

1300 個のサンプルがあることがわかります。 チェルチェヴェリク シードと 1200 サンプル ウルギュップ・シヴリーシ シード。 それらの差は 100 サンプルであり、非常に小さい差であることに注意してください。これは私たちにとって良いことであり、サンプル数を再調整する必要がないことを示しています。

機能の記述統計量も見てみましょう。 describe() データがどの程度分散されているかを確認する方法。 また、結果のテーブルを次のように転置します T 統計全体の比較を容易にするため:

df.describe().T

結果のテーブルは次のとおりです。

					count 	mean 			std 			min 		25% 			50% 			75% 			max
Area 				2500.0 	80658.220800 	13664.510228 	47939.0000 	70765.000000 	79076.00000 	89757.500000 	136574.0000
Perimeter 			2500.0 	1130.279015 	109.256418 		868.4850 	1048.829750 	1123.67200 		1203.340500 	1559.4500
Major_Axis_Length 	2500.0 	456.601840 		56.235704 		320.8446 	414.957850 		449.49660 		492.737650 		661.9113
Minor_Axis_Length 	2500.0 	225.794921 		23.297245 		152.1718 	211.245925 		224.70310 		240.672875 		305.8180
Convex_Area 		2500.0 	81508.084400 	13764.092788 	48366.0000 	71512.000000 	79872.00000 	90797.750000 	138384.0000
Equiv_Diameter 		2500.0 	319.334230 		26.891920 		247.0584 	300.167975 		317.30535 		338.057375 		417.0029
Eccentricity 		2500.0 	0.860879 		0.045167 		0.4921 		0.831700 		0.86370 		0.897025 		0.9481
Solidity 			2500.0 	0.989492 		0.003494 		0.9186 		0.988300 		0.99030 		0.991500 		0.9944
Extent 				2500.0 	0.693205 		0.060914 		0.4680 		0.658900 		0.71305 		0.740225 		0.8296
Roundness 			2500.0 	0.791533 		0.055924 		0.5546 		0.751900 		0.79775 		0.834325 		0.9396
Aspect_Ration 		2500.0 	2.041702 		0.315997 		1.1487 		1.801050 		1.98420 		2.262075 		3.1444
Compactness 		2500.0 	0.704121 		0.053067 		0.5608 		0.663475 		0.70770 		0.743500 		0.9049

表を見比べてみると、 意味する および 標準偏差 (std) 列を見ると、ほとんどの特徴の平均が標準偏差からかけ離れていることがわかります。 これは、データ値が平均値の周りに集中しているのではなく、平均値の周りに散らばっていることを示しています。 変動性が高い.

また、 最小 (min)と (max) 列、次のようないくつかの機能 Area, Convex_Area、最小値と最大値の間に大きな違いがあります。 これは、これらの列に非常に小さなデータと非常に大きなデータ値があることを意味します。または より高い振幅 データ値の間。

変動性が高く、振幅が大きく、測定単位が異なるフィーチャがある場合、ほとんどのデータは、すべてのフィーチャに対して同じスケールを使用するか、 縮尺. データのスケーリングは、データを平均に集中させ、その分散を減らします。

このシナリオは、データに異常値と極端な値があることも示している可能性があります。 だから、いくつか持っているのが最善です 外れ値の処理 データのスケーリングに加えて。

いくつかの機械学習アルゴリズムがあります。たとえば、次のようなツリーベースのアルゴリズムです。 ランダム フォレスト分類、高いデータ分散、外れ値、極端な値の影響を受けません。 ロジスティック回帰 値を分類する関数に基づいており、その関数のパラメーターは、一般的なデータの傾向から外れて分散の大きい値の影響を受ける可能性があります。

ロジスティック回帰については、実装するときに少し理解します。 今のところ、データの探索を続けることができます。

注: コンピュータ サイエンスでは、次のような有名な格言があります。 「ガベージイン、ガベージアウト」(GIGO)、機械学習に適しています。 これは、ガベージ データ (現象自体を説明しない測定値) がある場合、理解されておらず、アルゴリズムやモデルの種類に従って適切に準備されていないデータは、機能しない誤った出力を生成する可能性が高いことを意味します。日々の基本。
これが、データの調査、理解、および選択したモデルの機能が非常に重要である理由の XNUMX つです。 そうすることで、モデルにごみを入れるのを避けることができます。代わりに価値を入れて、価値を引き出すことができます。

データの視覚化

これまでの記述統計では、データのいくつかの性質のやや抽象的なスナップショットが得られました。 もう XNUMX つの重要なステップは、それを視覚化し、分散、振幅、外れ値が高いという仮説を確認することです。 これまでに観察したことがデータに示されているかどうかを確認するために、いくつかのグラフをプロットできます。

特徴が予測される XNUMX つのクラスにどのように関連しているかを確認することも興味深いです。 そのために、インポートしましょう seaborn パッケージ化して使用する pairplot 各機能の分布と、機能ごとの各クラス分離を確認するためのグラフ:

import seaborn as sns


sns.pairplot(data=df, hue='Class')

注: 上記のコードは、ペアプロットがすべての機能の散布図を結合し (可能)、機能の分布も表示するため、実行に時間がかかる場合があります。

ペアプロットを見ると、ほとんどの場合、 Çerçevelik クラスは、のポイントから明確に分離されています Ürgüp Sivrisi クラス。 あるクラスのポイントが右にあり、他のポイントが左にある場合、または一部が上にあり、他のポイントが下にある場合があります。 ある種の曲線または線を使用してクラスを分離する場合、これはそれらを分離する方が簡単であることを示しています。それらが混在している場合、分類はより困難な作業になります。

Eccentricity, Compactness および Aspect_Ration 列、一般的なデータ傾向から「孤立」または逸脱しているいくつかのポイント (外れ値) も簡単に見つけられます。

チャートの左上から右下への対角線を見ると、データ分布もクラスに従って色分けされていることに注意してください。 分布の形状と両方の曲線間の距離は、それらがどの程度分離可能かを示す別の指標であり、互いに離れているほど良好です。 ほとんどの場合、それらは重ね合わされていないため、分離が容易であり、これも私たちのタスクに貢献しています。

順番に、すべての変数の箱ひげ図をプロットすることもできます sns.boxplot() 方法。 ほとんどの場合、箱ひげ図を水平方向に配置すると便利です。そのため、箱ひげ図の形状は分布の形状と同じになります。 orient 引数:


sns.boxplot(data=df, orient='h') 

Python PlatoBlockchain データ インテリジェンスにおけるロジスティック回帰の決定版ガイド。垂直検索。あい。

上記のプロットでは、次のことに注意してください。 Area および Convex_Area 他の列の大きさと比較すると、他の箱ひげ図を押しつぶすほどの大きさがあります。 すべての箱ひげ図を見ることができるようにするために、特徴をスケーリングして再度プロットすることができます。

それを行う前に、他の値と密接に関連している特徴の値がある場合、たとえば、他の特徴の値が大きくなると大きくなる値がある場合、 正相関; または、反対の値がある場合は、他の値が小さくなる間に小さくなり、 負の相関.

データに強い関係があるということは、一部の列が他の列から派生したか、モデルと同様の意味を持つことを意味する可能性があるため、これを確認することが重要です。 その場合、モデルの結果は過大評価される可能性があり、より現実に近い結果が必要になります。 強い相関関係がある場合は、特徴の数を減らし、使用する列を減らしてモデルをより多く作成できることも意味します。 倹約.

注: で計算されたデフォルトの相関 corr() メソッドは ピアソン相関係数. この係数は、データが定量的で、正規分布しており、外れ値がなく、線形関係がある場合に示されます。

別の選択肢は、計算することです スピアマンの相関係数. スピアマンの係数は、データが序数型で、非線形で、分布があり、外れ値がある場合に使用されます。 私たちのデータは、ピアソンやスピアマンの仮定に完全に適合するわけではないことに注意してください (ケンドールのような相関方法は他にもあります)。 私たちのデータは定量的であり、その線形関係を測定することが重要であるため、ピアソンの係数を使用します。

変数間の相関関係を見てみましょう。その後、データの前処理に移ることができます。 との相関を計算します。 corr() メソッドを作成し、Seaborn's でそれらを視覚化します heatmap(). ヒートマップの標準サイズは小さくなりがちなのでインポートします matplotlib (Seabornが上に構築されている一般的な視覚化エンジン/ライブラリ)とサイズを変更します figsize:

import matplotlib.pyplot as plt
plt.figure(figsize=(15, 10))

correlations = df.corr()
sns.heatmap(correlations, annot=True) 

Python PlatoBlockchain データ インテリジェンスにおけるロジスティック回帰の決定版ガイド。垂直検索。あい。

このヒートマップでは、1 または -1 に近い値が注意が必要な値です。 最初のケースは高い正の相関を示し、0.8 番目のケースは高い負の相関を示します。 どちらの値も、0.8 または -XNUMX を超えていない場合、ロジスティック回帰モデルにとって有益です。

のような高い相関がある場合 0.99 の間に Aspec_Ration および Compactness、これは、使用のみを選択できることを意味します Aspec_Ration またはのみ Compactness、両方の代わりに(ほぼ等しいため) 予測子 お互いの)。 同じことが当てはまります Eccentricity および Compactness また、 -0.98 相関、 Area および Perimeter また、 0.94 相関関係、およびその他の列。

データの前処理

しばらくデータを調査したので、前処理を開始できます。 とりあえず、クラス予測にすべての機能を使用しましょう。 最初のモデルであるベースラインを取得した後、相関性の高い列をいくつか削除して、それをベースラインと比較できます。

機能列は私たちのものになります X データとクラス列、私たちの y 対象データ:

y = df['Class']
X = df.drop(columns=['Class'], axis=1)

カテゴリ特徴を数値特徴に変換する

弊社について Class 列 – その値は数値ではありません。これは、それらも変換する必要があることを意味します。 この変換を行うには多くの方法があります。 ここでは、 replace() メソッドと置換 Çerçevelik 〜へ 0 および Ürgüp Sivrisi 〜へ 1.

y = y.replace('Çerçevelik', 0).replace('Ürgüp Sivrisi', 1)

マッピングを覚えておいてください! モデルから結果を読み取るとき、これらを少なくとも頭の中で変換するか、他のユーザーのクラス名に戻す必要があります。

データをトレーニング セットとテスト セットに分割する

私たちの調査では、機能にはスケーリングが必要であることに気付きました。 今スケーリングを行った場合、または自動的にスケーリングを行った場合、値は全体でスケーリングされます。 X および y. その場合は、ご紹介します データ漏洩、間もなくテスト セットの値がスケーリングに影響を与えるためです。 データ漏洩は、ML モデルの再現不可能な結果と幻想的な高性能の一般的な原因です。

スケーリングについて考えると、最初に分割する必要があることがわかります X および y データをトレーニング セットとテスト セットにさらに追加し、 フィット トレーニング セットのスケーラー、および 変換 トレーニング セットとテスト セットの両方 (これを行うスケーラーにテスト セットが影響を与えることはありません)。 このために、Scikit-Learn の train_test_split() 方法:

from sklearn.model_selection import train_test_split
SEED = 42 

X_train, X_test, y_train, y_test = train_test_split(X, y, 
                                                    test_size=.25, 
                                                    random_state=SEED)

設定 test_size=.25 データの 25% をテストに使用し、75% をトレーニングに使用するようにしています。 これは、デフォルトの分割であれば省略できますが、 パイソン的 コードの書き方は、「明示的であることは暗黙的よりも優れている」とアドバイスしています。

注: 「明示的は暗黙的よりも優れている」という文は、 Pythonの禅、またはPEP20。 Python コードを書くためのいくつかの提案を提示します。 これらの提案に従っている場合、コードは考慮されます パイソン的. あなたはそれについてもっと知ることができます こちら.

データをトレーニング セットとテスト セットに分割した後、各セットに含まれるレコードの数を確認することをお勧めします。 それはで行うことができます shape 属性:

X_train.shape, X_test.shape, y_train.shape, y_test.shape

これは以下を表示します:

((1875, 12), (625, 12), (1875,), (625,))

分割後、トレーニング用に 1875 のレコード、テスト用に 625 のレコードがあることがわかります。

データのスケーリング

トレーニング セットとテスト セットの準備ができたら、Scikit-Learn を使用してデータのスケーリングに進むことができます。 StandardScaler オブジェクト (またはライブラリによって提供される他のスケーラー)。 漏れを防ぐために、スケーラーは X_train 次に、データとトレーニング値を使用して、トレーニング データとテスト データの両方をスケーリング (または変換) します。

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)

通常は次のように呼び出します。

scaler.fit(X_train)
X_train = scaler.transform(X_train)
X_test = scaler.transform(X_test)

最初の XNUMX 行は単数形で折りたたむことができます fit_transform() セットのスケーラーに適合し、一度に変換します。 ボックスプロット グラフを再現して、データをスケーリングした後の違いを確認できるようになりました。

スケーリングによって列名が削除されることを考慮すると、プロットする前に、列名を使用してトレーニング データをデータフレームに整理し、視覚化を容易にすることができます。

column_names = df.columns[:12] 
X_train = pd.DataFrame(X_train, columns=column_names)

sns.boxplot(data=X_train, orient='h')

Python PlatoBlockchain データ インテリジェンスにおけるロジスティック回帰の決定版ガイド。垂直検索。あい。

ついにすべての箱ひげ図を見ることができます! それらのすべてに外れ値があり、正規分布から離れた分布を示す特徴 (左または右に歪んだ曲線を持つ特徴) があることに注意してください。 Solidity, Extent, Aspect_Ration, Compactedness、より高い相関があったものと同じです。

IQR 法による外れ値の除去

ロジスティック回帰が外れ値の影響を受ける可能性があることは既にわかっています。 それらを処理する方法の XNUMX つは、と呼ばれる方法を使用することです。 四分位範囲 or I.Q.R.. IQR メソッドの最初のステップは、トレーニング データを四分位数と呼ばれる XNUMX つの部分に分割することです。 最初の四分位、 Q1、データの 25% に相当します。 Q2、50%まで、XNUMX回目、 Q3、75%まで、そして最後のもの、 Q4、100% に。 boxplot のボックスは IQR メソッドによって定義され、それを視覚的に表したものです。

水平の箱ひげ図を考えると、左側の垂直線はデータの 25%、中央の垂直線はデータの 50% (または中央値)、右側の最後の垂直線はデータの 75% を示します。 . 垂直線で定義された両方の正方形のサイズが均一であるほど、または中央の垂直線が中央にあるほど、データが正規分布に近づいているか、歪みが少ないことを意味し、これは分析に役立ちます。

IQR ボックスのほかに、その両側に水平線もあります。 これらの線は、によって定義された最小および最大の分布値をマークします。

$$
最小 = Q1 – 1.5*IQR
$$

および

$$
最大 = Q3 + 1.5*IQR
$$

IQR はまさに Q3 と Q1 (または Q3 – Q1) の差であり、データの最も中心的なポイントです。 そのため、IQR を見つけるときに、データの端点、または最小点と最大点で外れ値をフィルタリングすることになります。 箱ひげ図は、IQR 法の結果がどうなるかを垣間見ることができます。

Python PlatoBlockchain データ インテリジェンスにおけるロジスティック回帰の決定版ガイド。垂直検索。あい。

パンダを使用できます quantile() 分位点を見つける方法、および iqr scipy.stats 各列の四分位データ範囲を取得するパッケージ:

from scipy.stats import iqr

Q1 = X_train.quantile(q=.25)
Q3 = X_train.quantile(q=.75)

IQR = X_train.apply(iqr)

Q1、Q3、IQR ができたので、中央値に近い値を除外できます。


minimum = X_train < (Q1-1.5*IQR)
maximum = X_train > (Q3+1.5*IQR)


filter = ~(minimum | maximum).any(axis=1)


X_train = X_train[filter]

トレーニング行をフィルタリングした後、データ内に残っている行の数を次のように確認できます。 shape:

X_train.shape

この結果:

(1714, 12)

フィルタリング後、行数が 1875 から 1714 になったことがわかります。 これは、161 行に外れ値またはデータの 8.5% が含まれていたことを意味します。

注: 外れ値のフィルタリング、NaN 値の削除、およびデータのフィルタリングとクレンジングを含むその他のアクションは、データの 10% 未満または最大 10% にとどめることをお勧めします。 フィルタリングまたは削除がデータの XNUMX% を超える場合は、他の解決策を考えてみてください。

外れ値を取り除いた後、モデルにデータを含める準備がほぼ整いました。 モデルのフィッティングには、トレーニング データを使用します。 X_train フィルタリングされていますが、どうですか y_train?

y_train.shape

これは出力します:

(1875,)

注意してください y_train まだ1875行あります。 の数を一致させる必要があります。 y_train 行数から X_train 恣意的ではありません。 削除したカボチャの種のインスタンスの y 値を削除する必要があります。 y_train 設定。 フィルタリングされた X_train stil には元のインデックスがあり、インデックスには外れ値を削除したギャップがあります! 次に、のインデックスを使用できます X_train 対応する値を検索する DataFrame y_train:

y_train = y_train.iloc[X_train.index]

それを行った後、私たちは見ることができます y_train 再び形状:

y_train.shape

どの出力:

(1714,)

ベストプラクティス、業界で認められた標準、および含まれているチートシートを含む、Gitを学習するための実践的で実用的なガイドを確認してください。 グーグルGitコマンドを停止し、実際に 学ぶ それ!

今、 y_train 1714行もあり、それらは X_train 行。 ようやくロジスティック回帰モデルを作成する準備が整いました!

ロジスティック回帰モデルの実装

難しい部分は完了です! Scikit-Learn などのライブラリを使用する場合、前処理は通常、モデル開発よりも困難です。これにより、ML モデルの適用がわずか数行に簡素化されます。

まず、インポートします LogisticRegression クラスを作成してインスタンス化し、 LogisticRegression オブジェクト:

from sklearn.linear_model import LogisticRegression
logreg = LogisticRegression(random_state=SEED)

次に、列車データを logreg とのモデル fit() メソッドを使用して、テスト データを予測します。 predict() メソッド、結果を次のように保存 y_pred:



logreg.fit(X_train.values, y_train)
y_pred = logreg.predict(X_test)

私たちはすでに私たちのモデルで予測を行っています! の最初の 3 行を見てみましょう X_train 使用したデータを確認するには:

X_train[:3]

上記のコードは次のように出力します。

       Area          Perimeter     Major_Axis_Length    Minor_Axis_Length    Convex_Area   Equiv_Diameter       Eccentricity  Solidity      Extent        Roundness     Aspect_Ration        Compactness
0      -1.098308     -0.936518     -0.607941            -1.132551            -1.082768     -1.122359            0.458911      -1.078259     0.562847      -0.176041     0.236617             -0.360134
1      -0.501526     -0.468936     -0.387303            -0.376176            -0.507652     -0.475015            0.125764      0.258195      0.211703      0.094213      -0.122270            0.019480
2      0.012372      -0.209168     -0.354107            0.465095              0.003871      0.054384            -0.453911     0.432515      0.794735      0.647084      -0.617427            0.571137

そして、最初の 3 つの予測で y_pred 結果を見るには:

y_pred[:3] 

この結果:

array([0, 0, 0])

これらの XNUMX つの行については、それらがファースト クラスのシードであるという予測がありました。 Çerçevelik.

ロジスティック回帰、次のような最終クラスを予測する代わりに 0、行が関連する確率を予測することもできます 0 クラス。 これは、ロジスティック回帰がデータを分類するときに実際に起こることです。 predict() メソッドは、この予測をしきい値に渡して「ハード」クラスを返します。 クラスに属する確率を予測するには、 predict_proba() 使用されている:

y_pred_proba = logreg.predict_proba(X_test)

y 確率予測の最初の 3 つの値も見てみましょう。

y_pred_proba[:3] 

どの出力:

        # class 0   class 1   
array([[0.54726628, 0.45273372],
       [0.56324527, 0.43675473],
       [0.86233349, 0.13766651]])

これで、XNUMX つのゼロの代わりに、各クラスに XNUMX つの列ができました。 左の列で、 0.54726628、クラスに関連するデータの確率です 0; 右側の列で、 0.45273372、クラスに関連する確率です 1.

注: この分類の違いは、としても知られています。 ハード および ソフト 予測。 ハード予測は予測をクラスにボックス化し、ソフト予測は 確率 クラスに属するインスタンスの。

予測された出力がどのように作成されたかについての詳細情報があります。 実はそうじゃなかった 0、しかしクラスの 55% の確率 0、およびクラスの 45% の確率 1. これにより、最初の XNUMX つの X_test クラスに関するデータポイント 0、86% の確率で XNUMX 番目のデータ ポイントに関してのみ明確であり、最初の XNUMX つのデータ ポイントについてはそれほど明確ではありません。

ML メソッドを使用して調査結果を伝える場合、通常はソフト クラスを返し、関連する確率を "自信" その分類の。

モデルをさらに深く掘り下げるときに、それがどのように計算されるかについて詳しく説明します。 この時点で、次のステップに進むことができます。

分類レポートによるモデルの評価

XNUMX 番目のステップは、モデルがテスト データに対してどのように機能するかを確認することです。 Scikit-Learn をインポートできます classification_report() そして私たちを渡します y_test および y_pred 引数として。 その後、その応答を印刷できます。

分類レポートには、次のような最もよく使用される分類指標が含まれています。 精度, リコール, f1スコア, 精度.

  1. 精度: 分類子によってどの正しい予測値が正しいと見なされたかを理解するため。 精度は、これらの真陽性の値を陽性と予測されたもので除算します。

$$
精度 = frac{text{真陽性}}{text{真陽性} + text{偽陽性}}
$$

  1. リコール: 分類器によって識別された真陽性の数を理解するため。 再現率は、真陽性を陽性と予測されたはずのもので割ることによって計算されます。

$$
リコール = frac{text{真陽性}}{text{真陽性} + text{偽陰性}}
$$

  1. F1スコア: バランスの取れたまたは 調和平均 精度と再現率。 最小値は 0 で、最大値は 1 です。 f1-score が 1 の場合、すべてのクラスが正しく予測されたことを意味します。これは、実際のデータで取得するのが非常に難しいスコアです。

$$
text{f1-score} = 2* frac{text{precision} * text{recall}}{text{precision} + text{recall}}
$$

  1. 正確さ: 分類子が何回予測を正しく行ったかを示します。 精度の最低値は 0 で、最高値は 1 です。通常、その値に 100 を掛けてパーセンテージを求めます。

$$
精度 = frac{text{正しい予測の数}}{text{予測の総数}}
$$

注: 実際のデータで 100% の精度を得ることは非常に困難です。そうなった場合は、何らかの漏れや何か問題が発生している可能性があることに注意してください。理想的な精度値についてのコンセンサスはなく、これも状況に依存します。 70% の値は、分類子がデータの 30% で間違いを犯すことを意味します。つまり、ほとんどのモデルでは 70% を超える値で十分です。

from sklearn.metrics import classification_report
cr = classification_report(y_test, y_pred)
print(cr)

次に、分類レポートの出力を確認できます。

				precision    recall  f1-score   support

           0       0.83      0.91      0.87       316
           1       0.90      0.81      0.85       309

    accuracy                           0.86       625
   macro avg       0.86      0.86      0.86       625
weighted avg       0.86      0.86      0.86       625

これが私たちの結果です。 注意してください precision, recall, f1-score, accuracy 指標はすべて非常に高く、80% を超えています。これは理想的ですが、これらの結果はおそらく高い相関関係の影響を受けており、長期的には維持されません。

モデルの精度は 86% で、14% の確率で分類が間違っていることを意味します。 全体的な情報はありますが、クラスの分類に関して 14% の誤りが発生するかどうかを知ることは興味深いでしょう。 0 またはクラス 1. どのクラスがどのクラスとしてどの頻度で誤認されているかを特定するために、 混同行列 私たちのモデルの予測の。

混同行列を使用したモデルの評価

混同行列を計算してプロットしましょう。 そうすれば、それぞれの部分が理解できるようになります。 混同行列をプロットするには、Scikit-Learn を使用します confusion_matrix()からインポートします metrics モジュールを開きます。

Seaborn を使用すると、混同行列を簡単に視覚化できます。 heatmap(). したがって、それを生成した後、混同行列をヒートマップの引数として渡します。

from sklearn.metrics import confusion_matrix

cm = confusion_matrix(y_test, y_pred)
sns.heatmap(cm, annot=True, fmt='d')

Python PlatoBlockchain データ インテリジェンスにおけるロジスティック回帰の決定版ガイド。垂直検索。あい。

  1. 混乱マトリックス: マトリックスは、モデルが各クラスで正解または不正解だったサンプルの数を示します。 正しく、正しく予測された値が呼び出されます 真陽性、陽性と予測されたが陽性ではなかったものが呼び出されます 偽陽性. の同じ命名法 真のネガティブ および 偽陰性 負の値に使用されます。

混同行列プロットを見ると、 287 だった値 0 そして次のように予測されました 0 - または 真陽性 授業のために 0 (Çerçevelik の種)。 私たちも持っています 250 クラスの真陽性 1 (ウルギュップ シヴリーシの種)。 真陽性は常に、左上から右下に向かう行列の対角線上にあります。

我々はまた、持っています 29 本来あるべき価値 0、しかし次のように予測されます 1 (偽陽性)と 59 だった値 1 そして次のように予測されました 0 (偽陰性)。 これらの数値を使用すると、モデルが最も大きくするエラーは、偽陰性を予測することであることがわかります。 そのため、ほとんどの場合、ウルギュップ シヴリーシ シードを Çerçevelik シードとして分類することになります。

この種のエラーは、クラスの 81% のリコールによっても説明されます。 1. メトリックが接続されていることに注意してください。 そして、再現率の違いは、ウルギュップ シヴリーシ クラスのサンプルが 100 少ないことに起因しています。 これは、サンプル数が他のクラスよりわずかに少ないことの影響の XNUMX つです。 再現率をさらに向上させるには、クラスの重みを試すか、より多くの Ürgüp Sivrisi サンプルを使用することができます。

これまで、データ サイエンスの従来の手順のほとんどを実行し、ロジスティック回帰モデルをブラック ボックスとして使用しました。

注: さらに進みたい場合は、 クロス検証 (CV) とグリッド検索 それぞれ、データに関して最も一般化するモデルと、トレーニング前に選択された最適なモデル パラメーターを探す、または ハイパーパラメータ.

理想的には、CV と Grid Search を使用して、データの前処理ステップ、データ分割、モデリング、および評価を実行するための連結された方法を実装することもできます。これは Scikit-Learn で簡単になります。 パイプライン.

ここで、ブラック ボックスを開いて内部を調べ、ロジスティック回帰がどのように機能するかをより深く理解します。

ロジスティック回帰が実際にどのように機能するかを深く掘り下げる

  回帰 ロジスティック回帰が何をするかを理解するために、その兄弟である線形回帰がデータに対して何をするかを思い出すことができます。 線形回帰式は次のとおりです。

$$
y = b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n
$$

どのbで0 は回帰切片、b1 係数と x1 データ。

その方程式は、新しい値を予測するために使用される直線になりました。 導入部を思い出すと、ここでの違いは、新しい値を予測するのではなく、クラスを予測することです。 そのため、その直線を変更する必要があります。 ロジスティック回帰では、非線形性が導入され、予測は線ではなく曲線を使用して行われるようになりました。

Python PlatoBlockchain データ インテリジェンスにおけるロジスティック回帰の決定版ガイド。垂直検索。あい。

線形回帰直線が継続し、連続する無限値で構成されているのに対し、ロジスティック回帰曲線は中央で分割され、0 と 1 の値に極値があることに注意してください。 その「S」形状が、データを分類する理由です。最も高い端に近いか落ちるポイントはクラス 1 に属し、下象限にあるポイントまたは 0 に近いポイントはクラス 0 に属します。 「S」は 0 と 1 の中間、0.5 です。これは、ロジスティック回帰ポイントのしきい値です。

Python PlatoBlockchain データ インテリジェンスにおけるロジスティック回帰の決定版ガイド。垂直検索。あい。

ロジスティック回帰と線形回帰の視覚的な違いはすでに理解していますが、式はどうでしょうか? ロジスティック回帰の式は次のとおりです。

$$
y = b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n
$$

次のように書くこともできます。

$$
y_{確率} = frac{1}{1 + e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}
$$

または次のように書くこともできます:

$$
y_{確率} = frac{e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}{1 + e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}
$$

上記の式では、値の代わりに入力の確率があります。 分子が 1 であるため、結果として 0 と 1 の間の値が得られ、1 に分母の値が加算されるため、その値は 1 などになります。これは、分数の結果全体が 1 より大きくならないことを意味します。 .

そして、分母にある値は何ですか? それは e、自然対数の底 (約 2.718282) を線形回帰で累乗します。

$$
e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}
$$

別の書き方は次のようになります。

$$
ln left( frac{p}{1-p} right) = {(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}
$$

その最後の式では、 ln は自然対数 (底 e) であり、 p は確率なので、結果の確率の対数は線形回帰の結果と同じです。

言い換えれば、線形回帰の結果と自然対数を使用して、入力が設計されたクラスに関連するかどうかの確率に到達できます。

ロジスティック回帰の導出プロセス全体は次のとおりです。

$$
p{X} = frac{e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}{1 + e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}
$$

$$
p(1 + e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}) = e^{(b_0 + b_1 * x_1 + b_2 *x_2 + b_3 * x_3 + ldots + b_n * x_n)}
$$

$$
p + p*e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)} = e^{(b_0 + b_1 * x_1 + b_2 *x_2 + b_3 * x_3 + ldots + b_n * x_n)}
$$

p
=

e

(

b
0

+

b
1

x
1

+

b
2

x
2

+

b
3

x
3

+
...
+

b
n

x
n

)

-
p

e

(

b
0

+

b
1

x
1

+

b
2

x
2

+

b
3

x
3

+
...
+

b
n

x
n

)

$$
frac{p}{1-p} = e^{(b_0 + b_1 * x_1 + b_2 *x_2 + b_3 * x_3 + ldots + b_n * x_n)}
$$

$$
ln left( frac{p}{1-p} right) = (b_0 + b_1 * x_1 + b_2 *x_2 + b_3 * x_3 + ldots + b_n * x_n)
$$

これは、ロジスティック回帰モデルにも係数と切片値があることを意味します。 線形回帰を使用し、自然対数を使用して非線形成分を追加するため (e).

線形回帰で行ったのと同じ方法で、モデルの係数と切片の値を確認できます。 coef_ および intercept_ プロパティ:

logreg.coef_

12 個の特徴のそれぞれの係数を表示します。

array([[ 1.43726172, -1.03136968,  0.24099522, -0.61180768,  1.36538261,
        -1.45321951, -1.22826034,  0.98766966,  0.0438686 , -0.78687889,
         1.9601197 , -1.77226097]])
logreg.intercept_

その結果、次のようになります。

array([0.08735782])

係数と切片の値を使用して、データの予測確率を計算できます。 最初に取得しましょう X_test 例として、値を再度示します。

X_test[:1]

これは、の最初の行を返します X_test NumPy 配列として:

array([[-1.09830823, -0.93651823, -0.60794138, -1.13255059, -1.0827684 ,
        -1.12235877,  0.45891056, -1.07825898,  0.56284738, -0.17604099,
         0.23661678, -0.36013424]])

初期方程式に従う:

$$
p{X} = frac{e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}{1 + e^{(b_0 + b_1 * x_1 + b_2 * x_2 + b_3 * x_3 + ldots + b_n * x_n)}}
$$

Pythonでは、次のものがあります。

import math

lin_reg = logreg.intercept_[0] + 
((logreg.coef_[0][0]* X_test[:1][0][0])+ 
(logreg.coef_[0][1]* X_test[:1][0][1])+ 
(logreg.coef_[0][2]* X_test[:1][0][2])+ 
(logreg.coef_[0][3]* X_test[:1][0][3])+ 
(logreg.coef_[0][4]* X_test[:1][0][4])+ 
(logreg.coef_[0][5]* X_test[:1][0][5])+ 
(logreg.coef_[0][6]* X_test[:1][0][6])+ 
(logreg.coef_[0][7]* X_test[:1][0][7])+ 
(logreg.coef_[0][8]* X_test[:1][0][8])+ 
(logreg.coef_[0][9]* X_test[:1][0][9])+ 
(logreg.coef_[0][10]* X_test[:1][0][10])+ 
(logreg.coef_[0][11]* X_test[:1][0][11]))

px = math.exp(lin_reg)/(1 +(math.exp(lin_reg)))
px

この結果:

0.45273372469369133

もう一度見てみると、 predict_proba 最初の結果 X_test 行、私たちは持っています:

logreg.predict_proba(X_test[:1])


これは、元のロジスティック回帰方程式がクラスに関する入力の確率を与えることを意味します 1、クラスの確率を調べる 0、簡単にできます:

1 - px


両方に注意してください px および 1-px と同じです predict_proba 結果。 これがロジスティック回帰の計算方法とその理由です 回帰 その名前の一部です。 しかし、用語はどうですか ロジスティック?

用語 ロジスティック から来た ロジット、これはすでに見た関数です:

$$
左 (frac{p}{1-p} 右)
$$

で計算したところです。 px および 1-px. これはロジットとも呼ばれます 対数オッズ オッズの対数に等しいので、 p 確率です。

まとめ

このガイドでは、最も基本的な機械学習分類アルゴリズムの XNUMX つ、すなわち ロジスティック回帰.

最初に、Scikit-Learn の機械学習ライブラリを使用してロジスティック回帰をブラック ボックスとして実装しました。その後、回帰とロジスティックという用語がなぜどこから来たのかを明確にするために、段階的に理解しました。

また、データ サイエンス分析の最も重要な部分の XNUMX つであることを理解して、データを調査および研究しました。

ここから、遊んでみることをお勧めします マルチクラス ロジスティック回帰、XNUMX つ以上のクラスのロジスティック回帰 – 複数のクラスを持つ他のデータセットに同じロジスティック回帰アルゴリズムを適用し、結果を解釈できます。

注: データセットの優れたコレクションが利用可能です こちら あなたが遊ぶために。

また、L1とL2を勉強することをお勧めします 正則化、それらは、アルゴリズムがより良い結果を得ることができるように、モデルの複雑さを抑えて、より高いデータを通常に近づけるために「ペナルティを課す」方法です。 私たちが使用した Scikit-Learn 実装には、デフォルトですでに L2 正則化が含まれています。 もうXNUMXつ注目すべき点は、 ソルバー、 といった lbgs、ロジスティック回帰アルゴリズムのパフォーマンスを最適化します。

に注目することも重要です。 統計的 ロジスティック回帰へのアプローチ。 それは持っています 前提条件 データの動作について、および満足のいく結果を保証するために保持する必要があるその他の統計について、次のようなものがあります。

  • 観測は独立しています。
  • 説明変数間に多重共線性はありません。
  • 極端な外れ値はありません。
  • 説明変数と応答変数のロジットの間には線形関係があります。
  • サンプルサイズは十分に大きいです。

これらの仮定の多くが、データの分析と処理ですでにカバーされていることに注意してください。

ロジスティック回帰がさまざまなアプローチで提供するものを探求し続けることを願っています!

タイムスタンプ:

より多くの スタックアバス