“A column-vector y was passed when a 1d array was expected.” が出たとき 【scikit-learn】

Python

Python の scikit-learn で機械学習をしようとした際、“A column-vector y was passed when a 1d array was expected.” というワーニング/エラーが出た場合の対処方法についてまとめておきます。
以下の環境で確認をしています。

環境: Windows 10, Anaconda, Python 3.x

状況: sklearn で fit() を実行すると “1d array array was expected” の警告が出る

スクリプトの概要は以下の通りです。要部のみ抜粋します。

import sklearn 
import pandas as pd1
(略)
df_train = pd1.read_csv( file1 )
x1 = df_train.loc[:, ["col1","col2"]]
y1 = df_train.loc[:, ["col3"]]
x_train, x_test, y_train, y_test = train_test_split( x1, y1, random_state=0 )

model1 = RandomForestClassifier()          # random forest 
model1.fit( x_train, y_train )             # learning 

※ やろうとしたこと
① 機械学習に使う csv ファイルを pandas で読み出す。
列 col1, col2 を入力データとし、列 col3 を、正解データとする。(詳細略)
② train_test_split() で、学習用データセットと、テスト用データセットに分割する(split する)。
③ 学習モデルはランダムフォレスト(どのモデルでもよい)で定義し、機械学習 fit() を実行する。

ワーニングの表示:次元が合わないので ravel で変換

上記のスクリプトを実行すると、以下のような警告が出る。(最後の行はスクリプトの書き方により変わる。)

DataConversionWarning: A column-vector y was passed when a 1d array was expected. 
Please change the shape of y to (n_samples,), for example using ravel().
model1.fit( x_train, y_train )   # learning

scikit-learn の .fit() メソッドの y の入力は1次元配列が期待されており、ravel() が使えるといっています。

対処方法 ~ 次元が合わないので 1d array に修正する

そこで、エラーメッセージに従って、train_test_split() 関数の直後に、下記の2行(#1、#2)を追加します。
(警告が出ているスクリプトにコピー&ペーストし、スクリプトに合うよう修正してください。)

(略)
x_train, x_test, y_train, y_test = train_test_split( x1, y1, random_state=0 )
y_train = y_train.values.ravel()   # 1    2d array -> 1d array 
y_test  = y_test.values.ravel()    # 2    2d array -> 1d array 

model1 = RandomForestClassifier()          # random forest 
model1.fit( x_train, y_train )             # learning 

解説 ~ 納得したい人向け

・ 確認のため、以下の # for debug とした2行を追加してみてください。
さらに、# 1, # 2 の2行を入れた場合と、# 1, # 2 の 2行をコメントアウトした場合とで次元(出力)を比較してみてください。(y_train の配列が何行何列となっているか確認する。)
・ fit() メソッドは、y の次元(shape)が、( n_samples, ) となることを想定していると出ています。そこで、print() 関数で、いわれるがまま、y_train.shape を出力してみます。
・ また、修正するには ravel() メソッドを使ってみたらどうか?となっているので、# 1, # 2 の2行では、ravel() を追加して変換しています。
なお、values を入れないと、今度は、’DataFrame’ object has no attribute ‘ravel’ と言われて別のエラーとなるため、ravel() の実行前にオブジェクトを変換しています。
また、….ndim とした print() 関数を入れたのは、念のため、次元の数を確認するためです。
・ ravel() を入れることで、次元が 1d array に変換できていることがわかります。

(略)
x_train, x_test, y_train, y_test = train_test_split( x1, y1, random_state=0 )
y_train = y_train.values.ravel()   # 1    2d array -> 1d array 
y_test  = y_test.values.ravel()    # 2    2d array -> 1d array 

print( y_train.shape )             # for debug 
print( y_train.ndim )              # for debug 

model1 = RandomForestClassifier()          # random forest 
model1.fit( x_train, y_train )             # learning 

まとめ: fit する前に ravel で 1d array に変換する

sklearn を使っていて、ワーニング “DataConversionWarning: A column-vector y was passed when a 1d array was expected.” が出た場合の対処方法についてポイントをまとめました。
ravel() で変換すればよいということでした。
このワーニングって昔から出ていました? 単に学習データを csv ファイルにしただけなんですけれどもね。

関連リンク
・ 【scikit-learn】 LinearRegression の予測結果を整数で出力する方法
・ “cannot import name ‘joblib’ from ‘sklearn.externals’ “の表示が出たとき 【scikit-learn】

タイトルとURLをコピーしました