2020 年には、すでに多くの楽しい機械学習チュートリアルが見つかります。この記事では、最も人気のあるランダム フォレストから始めて、モデルの構築方法とその完全なプロセスを段階的に説明します。 データ サイエンティストとして、分類モデルを作成する方法は数多くあります。最も人気のある方法の 1 つはランダム フォレストです。ランダム フォレストのハイパーパラメータを調整して、モデルのパフォーマンスを最適化できます。 モデルを適合する前に主成分分析 (PCA) を試すことも一般的な方法です。しかし、なぜこのステップを追加するのでしょうか?ランダムフォレストの目的は、特徴の重要性をより簡単に理解できるようにすることではないでしょうか? ランダムフォレストモデルの「特徴の重要度」を分析する場合、PCA によって各「特徴」の解釈がより困難になります。ただし、PCA は次元削減を実行し、ランダム フォレストが処理する必要がある機能の数を削減できるため、PCA はランダム フォレスト モデルのトレーニングを高速化するのに役立ちます。 計算コストが高いことがランダム フォレストの最大の欠点の 1 つであることに注意してください (モデルの実行には長い時間がかかる場合があります)。特に、数百、あるいは数千もの予測機能を使用する場合、PCA は非常に重要になります。したがって、単に最高のパフォーマンスを発揮するモデルが必要で、特徴の重要性の解釈を犠牲にできる場合は、PCA が役立つ可能性があります。 では、例を見てみましょう。 Scikit-learn の乳がんデータセットを使用して 3 つのモデルを作成し、そのパフォーマンスを比較します。 1. ランダムフォレスト 2. PCA次元削減によるランダムフォレスト 3. PCA次元削減とハイパーパラメータ調整によるランダムフォレスト データのインポートまず、データを読み込んで DataFrame を作成します。これは、Scikit-learn によって事前にクリーンアップされた「おもちゃ」データセットであり、すぐにモデリングを進めることができます。ただし、ベストプラクティスとして、次のことを行う必要があります。 - df.head() を使用して新しい DataFrame を確認し、期待どおりであることを確認します。
- df.info() を使用して、各列のデータの種類と量を確認します。必要に応じてデータ型を変換する必要がある場合があります。
- NaN 値がないことを確認するには、df.isna() を使用します。必要に応じて欠損値を処理したり、行を削除したりする必要があるかもしれません。
- df.describe() を使用して、各列の最小値、最大値、平均値、中央値、標準偏差、四分位範囲を調べます。
「cancer」という名前の列は、モデルを使用して予測するターゲット変数です。 「0」は「がんなし」を意味し、「1」は「がんあり」を意味します。 - pandasをpdとしてインポートする
- sklearn.datasetsからload_breast_cancer列= [ '平均半径' 、 「平均テクスチャ」 、 「平均境界」 、 「平均滑らかさ」 、 「平均コンパクト」 、 「凹面」 、 「平均凹面」 、 「平均対称」 、 「平均寸法」 、 「滑らかな寸法」 、 「エラー」 、 「エラー」 、 「エラー」 、 'compure erser' 、 'comper '、' 、 'concavity error ' 、 'concave points error' 、 '対称性エラー' 、 「フラクタル寸法エラー ' 、 「最悪の半径」、「最悪のテクスチャー」 、 「最悪の境界」 、 「最悪の領域」 、 「最悪の滑らかさ」 、最悪「コンパクトさ」 、 「最悪の凹み」 、 「最悪の凹点」 、 「最悪の対称性」 、 「最悪のフラクタル次元」 ] dataset = load_breast_cancer()
- データ = pd.DataFrame(データセット[ 'データ' ], 列 = 列)
- data[ 'cancer' ] = dataset[ 'target' ]display(data.head())
- 表示(データ情報())
- 表示(data.isna().sum())
- 表示(データ.記述())
上記の画像は乳がんデータフレームの一部です。各行は 1 人の患者の観察結果です。 「cancer」という名前の最後の列は、予測したいターゲット変数です。 0 は「がんなし」、1 は「がんあり」を意味します。 トレーニング/テストの分割ここで、Scikit-learn の「train_test_split」関数を使用してデータを分割します。できるだけ多くのデータでモデルをトレーニングしたいと考えています。ただし、モデルをテストするのに十分なデータがあることも確認する必要があります。通常、データセット内の行数が多いほど、トレーニング セットに提供できるデータが多くなります。 たとえば、数百万行ある場合、そのうちの 90% をトレーニングとして使用し、10% をテストとして使用できます。ただし、データセットには 569 行しかなく、データ量は多くありません。したがって、この小さなデータセットに合わせて、データを 50% のトレーニングと 50% のテストに分割します。トレーニング セットとテスト セットの 0 と 1 の比率が元のデータセットと同じになるように、stratify = y を設定します。 - sklearn.model_selection からtrain_test_splitXをインポートします。data.drop( 'cancer' , axis= 1 )
- y = データ[ '癌' ]
- X_train、X_test、y_train、y_test = train_test_split(X、y、test_size= 0.50 、random_state = 2020 、stratify=y)
データを正規化するモデル化する前に、データを「中心化」および「標準化」し、さまざまな変数を同じスケールで測定する必要があります。予測子を決定する機能が互いに「公平に戦う」ことができるようにスケーリングを実行します。また、モデルが後でトレーニング データを受信できるように、 y_train を Pandas Series オブジェクトから NumPy 配列に変換します。 - numpyをnpとしてインポートする
- sklearn.preprocessing から StandardScalerをインポートしますrss = StandardScaler()
- X_train_scaled = ss.fit_transform(X_train)
- X_test_scaled = ss.transform(X_test)
- y_train = np.array(y_train)
「ベースライン」ランダムフォレストモデルの適合それでは、「ベースライン」ランダム フォレスト モデルを作成しましょう。このモデルは、Scikit-learn Random Forest Classifier ドキュメントで定義されているすべての予測機能とデフォルト設定を使用します。まず、モデルをインスタンス化し、正規化されたデータを使用してモデルを適合させます。トレーニング データを使用してモデルの精度を測定できます。 - sklearn.ensemble からRandomForestClassifierをインポートします
- sklearn.metrics から、recall_scorerfc = RandomForestClassifier()をインポートします。
- rfc.fit(X_train_scaled、y_train) を使います。
- 表示(rfc.score(X_train_scaled, y_train))# 1.0
ランダム フォレスト モデルが乳がんを予測するのに最も重要な特徴を知りたい場合は、feature_importances _ メソッドを呼び出して、これらの重要な特徴を視覚化し、定量化できます。 - 偉業 = {}
- 機能の場合、zip(data.columns、rfc_1.feature_importances_) 内の重要度:
- feats[feature] = importanceimportances = pd.DataFrame.from_dict(feats, orient= 'index' ).rename(columns={ 0 : 'Gini-Importance' })
- 重要度 = importances.sort_values(by= 'Gini-Importance' 、 ascending=False)
- 重要度 = 重要度.reset_index()
- importances = importances.rename(columns={ 'index' : 'Features' })sns.set(font_scale = 5 )
- sns.set(スタイル= "whitegrid" 、カラーコード=True、フォントスケール= 1.7 )
- 図、ax = plt.subplots()
- 図.set_size_inches( 30 , 15 )
- sns.barplot(x=importances[ 'ジニ係数' ], y=importances[ '特徴' ], データ=importances, 色= 'skyblue' )
- plt.xlabel( '重要度' 、フォントサイズ = 25 、太さ = '太字' )
- plt.ylabel( '機能' 、フォントサイズ = 25 、太さ = '太字' )
- plt.title( '機能の重要性' 、フォントサイズ = 25 、太字 = '太字' )display(plt.show())
- 表示(重要度)
主成分分析(PCA)さて、ベースラインモデルをどのように改善できるでしょうか?次元削減を使用すると、モデルを実行する計算コストを削減しながら、元のデータセットをより少ない変数で適合させることができます。 PCA を使用すると、これらの特徴の累積分散比を調べて、どの特徴がデータ内で最も大きな分散を表しているかを理解できます。 PCA 関数をインスタンス化し、考慮するコンポーネント (機能) の数を設定します。ここでは、生成されたすべてのコンポーネントの分散を確認し、どこをカットするかを決定するために、これを 30 に設定します。次に、スケーリングされた X_train データを PCA 関数に「適合」させます。 - matplotlib.pyplot を plt としてインポートします。
- Seaborn を SNS としてインポートする
- sklearn.decomposition から PCAをインポートします。pca_test = PCA(n_components= 30 )
- pca_test.fit(X_train_scaled)sns.set(スタイル= 'whitegrid' )
- plt.plot(np.cumsum(pca_test.explained_variance_ratio_))
- plt.xlabel( 'コンポーネントの数' )
- plt.ylabel( '累積説明分散' )
- plt.axvline(線幅= 4 、色= 'r' 、線のスタイル= '--' 、x= 10 、ymin= 0 、ymax= 1 )
- 表示(plt.show())evr = pca_test.explained_variance_ratio_
- cvr = np.cumsum(pca_test.explained_variance_ratio_) pca_df = pd.DataFrame()
- pca_df[ '累積分散比' ] = cvr
- pca_df[ '説明分散比率' ] = evr
- 表示(pca_df.head( 10 ))
プロットは、10 個を超える特徴では、説明される変動があまりないことを示しています。この DataFrame は、累積分散比 (データの合計分散が説明されている) と説明分散比 (データの合計分散のうち、各 PCA コンポーネントによって説明されている割合) を示します。 上記の DataFrame から、PCA を使用して 30 個の予測変数を 10 個のコンポーネントに減らしても、分散の 95% 以上を説明できることがわかります。他の 20 個のコンポーネントは分散の 5% 未満を説明するため、それらの重みを減らすことができます。このロジックに従って、PCA を使用して、X_train と X_test のコンポーネント数を 30 から 10 に減らします。再作成された「次元削減」データセットを「X_train_scaled_pca」と「X_test_scaled_pca」に割り当てます。 - pca = PCA(n_components= 10 )です。
- pca.fit(X_train_scaled)X_train_scaled_pca = pca.transform(X_train_scaled)
- X_test_scaled_pca = pca.transform(X_test_scaled)
各コンポーネントは、元の変数と対応する「重み」の線形結合です。 DataFrame を作成すると、各 PCA コンポーネントの「重み」を確認できます。 - pca_dims = []
- x が範囲( 0 、len(pca_df))内である場合:
- pca_dims.append( 'PCA コンポーネント {}' .format(x))pca_test_df = pd.DataFrame(pca_test.components_, columns=columns, index=pca_dims)
- pca_test_df.head( 10 ).T
PCA後の「ベースライン」ランダムフォレストモデルのフィッティングこれで、X_train_scaled_pca と y_train のデータを別の「ベースライン」ランダム フォレスト モデルに適合させ、そのモデルよりも予測が改善されたかどうかをテストできます。 - rfc = ランダムフォレスト分類子()
- rfc.fit(X_train_scaled_pca, y_train) 表示(rfc.score(X_train_scaled_pca, y_train)) # 1.0
ハイパーパラメータチューニングラウンド 1: RandomSearchCV PCA を実装した後、ハイパーパラメータを調整してランダム フォレストを調整し、より良い予測を得ることもできます。ハイパーパラメータは、モデルの「設定」と考えることができます。 2 つの異なるデータセットの理想的な設定は同じではないため、モデルを「調整」する必要があります。 まず、RandomSearchCV から始めて、より多くのハイパーパラメータ値を検討することができます。すべてのランダム フォレスト ハイパーパラメータについては、Scikit-learn Random Forest Classifier のドキュメントを参照してください。 各ハイパーパラメータの値の範囲を含む param_dist を生成します。 RandomSearchCV をインスタンス化し、最初にランダム フォレスト モデルを渡し、次に「param_dist」、テスト反復回数、およびクロス検証回数を渡します。 ハイパーパラメータ「n_jobs」は、モデルの実行に使用するプロセッサ コアの数を決定します。 n_jobs = -1 に設定すると、コンピューターのすべてのコアが使用されるため、モデルの実行速度が最も速くなります。 以下のハイパーパラメータを調整します。 - n_estimators: ランダムフォレスト内の「ツリー」の数。
- max_features: 各分割における特徴の数。
- max_depth: 各ツリーが持つことができる「分割」の最大数。
- min_samples_split: ツリー内のノードが分割される前に必要な観測値の最小数。
- min_samples_leaf: 各ツリーの末尾のリーフ ノードに必要な観測値の最小数。
- bootstrap: ランダムフォレスト内の各ツリーにデータを提供するためにブートストラップを使用するかどうか。 (ブートストラップとは、データセットからランダムに抽出して置き換えることです。)
- sklearn.model_selection からRandomizedSearchCV をインポートします。n_estimators = [ int (x) for x in np.linspace(start = 100 , stop = 1000 , num = 10 )] max_features = [ 'log2' , 'sqrt' ] max_depth = [ int (x) for x in np.linspace(start = 1 , stop = 15 , num = 15 )] min_samples_split = [ int (x) for x in np.linspace(start = 2 , stop = 50 , num = 10 )] min_samples_leaf = [ int (x) for x in np.linspace(start = 2 , stop = 50 , num = 10 )] bootstrap = [True, False] param_dist = { 'n_estimators' : n_推定値、
- '最大機能' : 最大機能、
- 'max_depth' : 最大深度、
- 'min_samples_split' : min_samples_split、
- 'min_samples_leaf' : min_samples_leaf、
- 'ブートストラップ' : ブートストラップ}rs = RandomizedSearchCV(rfc_2,
- パラメータ距離、
- n_iter = 100 、
- CV = 3 、
- 詳細 = 1 、
- n_jobs=- 1 ,
- ランダム状態 = 0 )rs.fit(X_train_scaled_pca、y_train)
- rs.ベストパラメータ
-
- ————————————————————————————————————————————
- # { 'n_estimators' : 700 ,
- # 'min_samples_split' : 2 ,
- # 'min_samples_leaf' : 2 ,
- # 'max_features' : 'log2' ,
- # '最大深度' : 11 ,
- # 'ブートストラップ' : True}
n_iter = 100、cv = 3 で、上記で入力したハイパーパラメータの組み合わせをランダムにサンプリングして、300 個のランダム フォレスト モデルを作成しました。 best_params を呼び出すと、最もパフォーマンスの高いモデル パラメータを取得できます (上記のコード ボックスの下部に表示)。 ただし、現在の「best_params」では、次のハイパーパラメータ調整を実行するための一連のパラメータを取得するための最も効果的な情報が提供されない可能性があります。これをより大規模に試すには、RandomSearchCV の結果の DataFrame を簡単に取得できます。 - rs_df = pd.DataFrame(rs.cv_results_).sort_values( 'rank_test_score' ).reset_index(drop=True)
- rs_df = rs_df.drop([
- '平均適合時間' 、
- 'std_fit_time' 、
- '平均スコア時間' 、
- '標準スコア時間' 、
- 'パラメータ' 、
- 'split0_test_score' 、
- 'split1_test_score' 、
- 'split2_test_score' 、
- 'std_test_score' ],
- 軸 = 1 )
- rs_df.head( 10 )
ここで、各ハイパーパラメータのヒストグラムを x 軸に作成し、各値に対するモデルの平均スコアをプロットして、平均的にどの値が最適であるかを確認してみましょう。 - 図、axs = plt.subplots(ncols= 3 、nrows= 2 )
- sns.set(スタイル = "whitegrid" 、カラーコード = True、フォントスケール = 2 )
- fig.set_size_inches( 30 , 25 )sns.barplot(x= 'param_n_estimators' 、y= 'mean_test_score' 、データ=rs_df、ax=axs[ 0 , 0 ]、色= 'lightgrey' )
- axs[ 0 , 0 ].set_ylim([. 83 ,. 93 ])axs[ 0 , 0 ].set_title(label = 'n_estimators' 、size = 30 、weight = 'bold' )sns.barplot(x = 'param_min_samples_split' 、y = 'mean_test_score' 、data = rs_df、ax = axs[ 0 , 1 ]、color = 'coral' )
- axs[ 0 , 1 ].set_ylim([. 85 ,. 93 ]) axs[ 0 , 1 ].set_title(label = 'min_samples_split' 、size= 30 、weight= 'bold' ) sns.barplot(x= 'param_min_samples_leaf' 、y= 'mean_test_score' 、data=rs_df、ax=axs[ 0 , 2 ]、color= 'lightgreen' )
- axs[ 0 , 2 ].set_ylim([. 80 ,. 93 ]) axs[ 0 , 2 ].set_title(label = 'min_samples_leaf' 、size= 30 、weight= 'bold' ) sns.barplot(x= 'param_max_features' 、y= 'mean_test_score' 、data=rs_df、ax=axs[ 1 , 0 ]、color= 'wheat' )
- axs[ 1 , 0 ].set_ylim([. 88 ,. 92 ]) axs[ 1 , 0 ].set_title(label = 'max_features' 、size = 30 、weight = 'bold' ) sns.barplot(x = 'param_max_depth' 、y = 'mean_test_score' 、data = rs_df、ax = axs[ 1 , 1 ]、color = 'lightpink' )
- axs[ 1 , 1 ].set_ylim([. 80 ,. 93 ])axs[ 1 , 1 ].set_title(label = 'max_depth' 、size = 30 、weight = 'bold' )sns.barplot(x = 'param_bootstrap' 、y = 'mean_test_score' 、data = rs_df、ax = axs[ 1 , 2 ]、color = 'skyblue' )
- axs[ 1 , 2 ].set_ylim([. 88 ,. 92 ])
上記のグラフから、各ハイパーパラメータ値の平均パフォーマンスがわかります。 n_estimators: 300、500、700 はほぼ最高の平均スコアを持ちます。 min_samples_split: 2 や 7 などの値が小さいほど、スコアが高くなります。 23も高得点です。 2 より大きい値や 23 付近の値を試すことができます。 min_samples_leaf: 値が小さいほどスコアが高くなる可能性があります。2〜7 の値を使用してみてください。 max_features: 「sqrt」は平均スコアが最も高くなります。 max_depth: 明確な結果はありませんが、2、3、7、11、15 がうまく機能します。 bootstrap: 「False」の平均スコアが最も高くなります。 これらの調査結果を使用して、ハイパーパラメータの調整の 2 回目のラウンドに移行し、選択肢をさらに絞り込むことができます。 ハイパーパラメータチューニング第2ラウンド: GridSearchCV RandomSearchCV を使用した後、GridSearchCV を使用して、これまでで最高のハイパーパラメータをより細かく検索できます。ハイパーパラメータは同じですが、GridSearchCV を使用して、より「徹底的な」検索を実行します。 GridSearchCV では、ハイパーパラメータの個々の組み合わせを試行します。これには、試行する反復回数を直接制御できる RandomSearchCV よりもはるかに多くの計算能力が必要です。たとえば、3 倍の交差検証を使用して、わずか 6 つのパラメータに対して 10 個の異なるパラメータ値を検索するには、モデルを 3,000,000 回フィッティングする必要があります。そのため、最初に検索を絞り込むのに役立つ RandomSearchCV を使用した後に GridSearchCV を実行します。 そこで、RandomizedSearchCV から学んだことを活用して、各ハイパーパラメータの平均的な最高パフォーマンス範囲を入力します。 - sklearn.model_selectionからGridSearchCVn_estimatorsをインポートします。 = [ 300 , 500 , 700 ]
- 最大特徴 = [ '平方根' ]
- 最大深度 = [ 2 , 3 , 7 , 11 , 15 ]
- 最小サンプル分割 = [ 2 、 3 、 4 、 22 、 23 、 24 ]
- 最小サンプル数 = [ 2 , 3 , 4 , 5 , 6 , 7 ]
- bootstrap = [False] param_grid = { 'n_estimators' : n_estimators,
- '最大機能' : 最大機能、
- 'max_depth' : 最大深度、
- 'min_samples_split' : min_samples_split、
- 'min_samples_leaf' : min_samples_leaf、
- 'ブートストラップ' : ブートストラップ}gs = GridSearchCV(rfc_2、param_grid、cv = 3 、verbose = 1 、n_jobs=- 1 )
- gs.fit(X_train_scaled_pca、y_train) 関数
- rfc_3 = gs.ベストエスティメーター_
- gs.ベストパラメータ
-
- ————————————————————————————————————————————
- # { 'bootstrap' : False、
- # 'max_depth' : 7 ,
- # 'max_features' : 'sqrt' ,
- # 'min_samples_leaf' : 3 ,
- # 'min_samples_split' : 2 ,
- # 'n_estimators' : 500 }
ここでは、3 x 1 x 5 x 6 x 6 x 1 = 540 モデル、合計 1,620 モデルに対して 3 倍のクロス検証を実行します。ここで、RandomizedSearchCV と GridSearchCV を実行した後、best_params_ を呼び出して、データを予測するための最適なモデルを取得できます (上記のコード ボックスの下部に示すように)。 テストデータでモデルのパフォーマンスを評価するこれで、テスト データでモデルを評価できます。 3つのモデルをテストします: - ベースラインランダムフォレスト
- PCA 次元削減によるベースライン ランダム フォレスト
- PCA 次元削減とハイパーパラメータ調整によるベースライン ランダム フォレスト
各モデルの予測を生成してみましょう。 - y_pred = rfc.predict(X_test_scaled)
- y_pred_pca = rfc.predict(X_test_scaled_pca)
- y_pred_gs = gs.best_estimator_.predict(X_test_scaled_pca)
次に、各モデルが乳がんをどの程度正確に予測できるかを確認するために、各モデルの混同行列を作成しました。 - sklearn.metrics からconfusion_matrixをインポートしますconf_matrix_baseline = pd.DataFrame(confusion_matrix(y_test, y_pred), index = [ '実際 0' , '実際 1' ], columns = [ '予測 0' , '予測 1' ])conf_matrix_baseline_pca = pd.DataFrame(confusion_matrix(y_test, y_pred_pca), index = [ '実際 0' , '実際 1' ], columns = [ '予測 0' , '予測 1' ])conf_matrix_tuned_pca = pd.DataFrame(confusion_matrix(y_test, y_pred_gs), index = [ '実際 0' , '実際 1' ], columns = [ '予測 0' , '予測1' ])display(conf_matrix_baseline)
- display( 'ベースラインランダムフォレストリコールスコア' , Recall_score(y_test, y_pred))
- 表示(conf_matrix_baseline_pca)
- display( 'PCA リコールスコア付きベースラインランダムフォレスト' , Recall_score(y_test, y_pred_pca))
- 表示(conf_matrix_tuned_pca)
- display( 'ハイパーパラメータ調整ランダムフォレスト、PCA 次元削減リコールスコア' 、recall_score(y_test、y_pred_gs))
予測は次のとおりです。 私たちは癌の診断を扱っており、モデルにおける偽陰性の予測誤差を最小限に抑えることに最も関心があるため、再現率をパフォーマンス指標として使用します。 これを考慮すると、ベースラインのランダム フォレスト モデルは、リコール スコアが 94.97% で最適なパフォーマンスを発揮するようです。私たちのテストデータセットでは、ベースラインモデルは 179 人の癌患者のうち 170 人を正確に予測できます。 このケーススタディでは、重要な注意点が浮かび上がります。PCA の後、または大規模なハイパーパラメータ調整の後でも、調整されたモデルが通常の「生の」モデルほどうまく機能しない場合があります。しかし、試してみることは重要です。試してみなければ、どのモデルが最適かはわかりません。がんを予測するモデルの精度が高ければ高いほど、より多くの命を救うことができます。 |