2020年6月7日ビニングなるものに出会いました。ビニングはbinningで、特徴量をいくつかのビンに分けるんだね。機械学習で、データ自体を色々いじって新しい特徴量を作り出したりすることを、特徴量エンジニアリングというらしです。今回は、ビニングという手法を勉強しました。見、理解に苦しむ内容なのですが、プログラムを作成してみたら意外となるほど、と感じました。ボストンの住宅価格データの部屋数「RM」を利用して視覚化しながら勉強しました。目次ビニングのイメージ線形回帰は、特徴量が1つだけだとただの直線になってしまいます。たくさんの特徴がある場合には、線形回帰はどんどんと強力になっていきますが、データによってはそうでない時もあります。ビニングは、一つの特徴量を一定間隔のビンに分割して、それぞれの区間を違う特徴量とみなして重回帰をすることで、一つの特徴量に複雑な線を引くことができます。ビニング図の左は、線形回帰の単回帰になります。リッジやLassoで傾き具合をデータに適合しすぎないようにしていました。右の図が、今回やろうとしているビニングのイメージです。ビニングは、離散化とも呼ばれるようだね。確かに、アナログな連続的な線から、階段状のデジタルな線になっています。単回帰のプログラムを思い出すボストンの住宅価格データのRMのみを利用して、単回帰を行うプログラムです。以前の記事もご参考ください。部屋数の特徴量のデータに対する住宅価格のモデルを作成する、単回帰をやってみました。言葉が学者風になってきたね。random_state=0)train_test_splitのパラメータ、「random_state」を設定することで、乱数の種の数値を固定することで、毎回同じ分割ができるようにしました。(前回からの変更点)以前のプログラムでは、train_test_splitを実行するたびに違うデータ分割となってしまったのが、何回実行しても、同じ結果になりました。reg.predict(X_train))」とすることで、回帰の線を描くことができるように変更しています。オレンジの線が、線形回帰での予測線になるね。ビニングを行うビニングを行う流れとして、1.データのどこをビンとするかを決める2.データを所属するビンの番号に変更する3.特徴量として配列化する(ワンホットエンコーディングと呼ぶらしい)というデータ変換を行うことで、ビニングされたデータとします。データのどこをビンとするかを決めるnumpyのlinspaceで行います。今回のRMデータは、3〜9までの範囲になるため、linspaceの範囲を3と9としました。今回はシンプルに見やすくするため、分割数を6としています。3〜9までの6個の分割点を得ることができます。]この分割境界の6個の数字は、ビンの範囲と対応してきます。ビン1:「3~4.2」ビン2:「4.2~5.4」ビン3:「5.4~6.6」ビン4:「6.6~7.8」ビン5:「7.8~9」のような範囲となります。データを所属するビンの番号に変更するnumpyのdigitalizeで行います。これも、動作させて、どのようにデータが変化するのかを確認するとわかります。bins=bins)print(sel_bins.shape)print(X_train[0])print(sel_bins[0])X_trainの一個目のデータ(X_train[0])が5.605なので、5.4〜6.6の間に所属します。sel_binsの1個目データ(sel_bins[0])にはビン3を示す、3という数値が入ります。1)[5.605][3]全てのデータ(379個)に対してこのようにビンの番号へ変換する処理が行われます。ちなみに、この時点で、グラフ化すると、データがビン番号に変化したので、離散的なグラフになります。ここからも、離散化の意味が伝わってきます。特徴量として配列化するワンホットエンコーディングというらしいのですが、ここも、scikit-learnのOneHotEncoderという機能で変換することができます。ワンホットエンコーディングは、下の図のようにデータを変換します。encoder.transform(sel_bins)#ワンホットエンコーディングの3行目まで確認してみるbin_data[:3]sklearnのpreprocessingから、OneHotEncoderをimportします。エンコーダ作成後、エンコーダーに先ほどのビン番号に変換したデータ「sel_bins」を入れて訓練(fit)させます。最後に、訓練させたencorderに、「sel_bins」を入れて「transform」させることで、「bin_data」という変数に、先ほどのようなワンホットエンコーディングの形式の配列が得られます。0.]])線形モデルを学習させる最後の訓練は、このビン毎に分割したデータを学習させます。これは、ビン数分のカテゴリ変数の(0または1で決定する特徴量)特徴量を訓練させるのに似ていると思います。y_train)lineという変数に、X軸方向の数値、3〜9を1000分割した数値の配列を作成しておきます。reshapeで二次元配列の形に変換しておきます。line_binnedには、ワンホットエンコーディングに変換したline変数を入れておきます。color="green")#Xに3~9の1000分割した数値、Yに訓練させたモデルにXを3~9の1000分の1づつ増加した時の値を計算させる。“solid”)」のところです。predictでy軸をプロットするのですが、lineデータをビン化したものを入れます。することで、lineの配列(正確には2次元配列)の全ての数値に対してYの値が出せます。スコアを比較してみるまずは、普通の線形回帰です。y_train)print("通常データの精度")print(normal_reg.score(X_test,y_test))通常データの精度0.4679000543136782次に、ビニングしたものの精度です。テストデータも訓練データ同様、ワンホットエンコーディング形式にしないと、モデルがデータを受け付けません。encoder.transform(sel_bins_test)#テストデータをビンにしたもので精度を評価print(reg.score(bin_data_test,y_test))5分割したビニングの精度0.4778030179010067若干精度が上昇しているようです。ビンの数を増やせば、このRMの特徴量に対しては、もっと複雑なモデルを作成することができそうです。ビニングの分割数を増やすとどうなるか試してみようかな。ビニングの処理をひとまとめに関数化できないかな?いつかやってみよう。ビニングの続きの記事はこちらもご参考ください。ビニングのプログラムを色々といじっていました。pythonよかったらシェアしてね!URLをコピーしました!URLをコピーしました!パンダの中のパンダサウンドクリエータ、プログラマひたすら脳内の思考と雑念を記事にしている気が・・・ご容赦ください!音楽、プログラム、自分の作品となる何かが作れる日を目指して邁進中です。