質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.42%
Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Q&A

解決済

1回答

227閲覧

機械学習にて、データの前処理の順番について

Omihiro

総合スコア6

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

0グッド

0クリップ

投稿2023/05/23 12:56

編集2023/05/27 11:09

実現したいこと

機械学習のフェーズに入って約1か月程ですが、ふと疑問に思い質問いたしました。

とあるサイトや参考書を見ていて、機械学習における手順として、NaN値をまずは除去なり補完なりを行った後に、外れ値がある場合はそれを除去の手順と記載されておりました。

つまり
①番目:NaNの除去、補完
②番目:外れ値の除去
の手順で記載されておりました。

・しかし、データの散布図にプロットされている外れ値を見てふと思ったのですが、先に外れ値を除去してから、NaNを補完なり削除なりした方が性能が高いモデルになるのでは?
・そもそも外れ値があると仮定して、NaN値を外れ値を含む平均で補完した場合に、正しく補完が行えていないことになり、最初っから外れ値を削除した方がどのみち効率がいいのでは?

この2点から自分なりに二通り試し、線形回帰モデルの決定係数で比較を行ってみました。

1)外れ値を削除してから、NaNを中央値で補完
2)NaNを中央値で補完してから外れ値を削除
(コードはその二通りに分けて記述しております。)

結論から言いますと、1)の方が決定係数が、わずかに高くなっておりました。

そこで質問なのですが、NaNを処理後に外れ値を処理した方がいいケースもあるのでしょうか?
あるとすればどのようなデータの場合なのかも含めて教えて頂ければ幸いです。
宜しくお願いいたします。

試したこと

python3

1#1)外れ値を削除してから、NaNを中央値で補完 2 3df = pd.read_csv("./sukkiri-ml-codes/datafiles/ex3.csv") 4print(df.head()) 5df.isna().sum() 6 7df.plot(kind="scatter", x = "x0", y = "target" ) 8df.plot(kind="scatter", x = "x1", y = "target" ) 9df.plot(kind="scatter", x = "x2", y = "target" ) 10df.plot(kind="scatter", x = "x3", y = "target" ) 11 12 #外れ値をまずは除去 13df.query("x2 < -2 and target >= 100") 14 15df = df.drop(23,axis=0) 16#再度確認、除去されている。 17df.plot(kind="scatter", x = "x2", y = "target" ) 18 19print(df.isna().sum()) 20#各列毎にNaNを調べる 21df[df["x0"].isna() == True] 22 23#各列毎にNaNを中央値で補完し、新たなdfとする。 24df = df.fillna(df.median()) 25df.head() 26#各列のNaNの個数を再度調べる。各列0個であることが分かる。 27print(df.isna().sum()) 28 29#dfを学習用データセットとテスト用データセットに分ける。 30X = df[["x0","x1","x2","x3"]] 31y = df["target"] 32X_train , X_test , y_train , y_test = train_test_split(X,y,test_size=0.2,random_state=1) 33 34#線形回帰分析により、回帰モデルを構築 35model3 = LinearRegression() 36model3.fit(X_train,y_train) 37model3.score(X_test,y_test) 38print(model3.predict(X_test)) 39print(model3.score(X_test,y_test)) 40 41#1)の実行結果 42 43 x0 x1 x2 x3 target 440 1.000943 2.114344 -1.148213 -0.051415 77.147293 451 1.505901 -0.626081 3.041686 -0.587336 278.595852 462 -0.390320 0.283607 -0.940359 -2.154124 -71.039904 473 -0.167273 1.413624 -0.632571 -1.016131 42.193870 484 -0.728801 1.370530 0.168298 -1.203904 89.167955 49x0 2 50x1 0 51x2 2 52x3 0 53target 0 54dtype: int64 55x0 0 56x1 0 57x2 0 58x3 0 59target 0 60dtype: int64 61[ 15.05327112 8.99105672 -41.74725543 5.22387964 -51.76948953 62 -288.76886524 -62.7708211 36.75697671 -84.71395592 -143.57675651 63 178.18554795 -21.35650517 167.10941813 -0.35875119 140.84561288 64 75.55167828 -218.03813847 -226.25515662 -118.55738726 -85.0386107 ] 650.9821246117105957

python3

1#2)NaNを中央値で補完してから外れ値を削除した場合 2 3df = pd.read_csv("./sukkiri-ml-codes/datafiles/ex3.csv") 4print(df.head()) 5df.isna().sum() 6 7df.plot(kind="scatter", x = "x0", y = "target" ) 8df.plot(kind="scatter", x = "x1", y = "target" ) 9df.plot(kind="scatter", x = "x2", y = "target" ) 10df.plot(kind="scatter", x = "x3", y = "target" ) 11 12print(df.isna().sum()) 13#各列毎にNaNを調べる 14df[df["x0"].isna() == True] 15 16#各列毎にNaNを中央値で補完し、新たなdfとする。 17df = df.fillna(df.median()) 18df.head() 19#各列のNaNの個数を再度調べる。各列0個であることが分かる。 20print(df.isna().sum()) 21 22 #外れ値を除去 23df.query("x2 < -2 and target >= 100") 24 25df = df.drop(23,axis=0) 26#再度確認、除去されている。 27df.plot(kind="scatter", x = "x2", y = "target" ) 28 29 30 31#dfを学習用データセットとテスト用データセットに分ける。 32X = df[["x0","x1","x2","x3"]] 33y = df["target"] 34X_train , X_test , y_train , y_test = train_test_split(X,y,test_size=0.2,random_state=1) 35 36#線形回帰分析により、回帰モデルを構築 37model3 = LinearRegression() 38model3.fit(X_train,y_train) 39model3.score(X_test,y_test) 40print(model3.predict(X_test)) 41print(model3.score(X_test,y_test)) 42 43#2)の実行結果 44 45 x0 x1 x2 x3 target 460 1.000943 2.114344 -1.148213 -0.051415 77.147293 471 1.505901 -0.626081 3.041686 -0.587336 278.595852 482 -0.390320 0.283607 -0.940359 -2.154124 -71.039904 493 -0.167273 1.413624 -0.632571 -1.016131 42.193870 504 -0.728801 1.370530 0.168298 -1.203904 89.167955 51x0 2 52x1 0 53x2 2 54x3 0 55target 0 56dtype: int64 57x0 0 58x1 0 59x2 0 60x3 0 61target 0 62dtype: int64 63[ 15.05250147 8.99533035 -41.74601422 5.22944331 -51.78084303 64 -288.77085908 -62.77155255 36.75136397 -84.71145755 -143.56518812 65 178.19197248 -21.35527622 167.1121523 -0.3600463 140.84684223 66 75.54840326 -218.04441227 -226.2734193 -118.55965813 -85.22980242] 670.9820345074421969

ここに問題に対して試したことを記載してください。

NaNを補完する際に平均でも補完してみましたが、決定係数が下がった為、こちらは割愛。
また、データ分割の際のシード値はどちらも1としております。

補足情報(FW/ツールのバージョンなど)

Python3.8.8
vscodeバージョン: 1.78.2 (user setup)

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

理論的な裏付けなどはない回答となりますが
「どのような値が外れ値か?は実際のデータを見てみないと分からない」
つまり「実データから外れ値を決定する」ケースだと、最初にNaN値を除外したり埋めるのが自然だと思います。

  • NaN値を除いたデータで外れ値を決定
  • 外れ値を除外
  • NaN値を除外or平均や中央値で埋め

という手順でももちろんよいですが、複雑ですしそれほど違いは出ないかもしれません。

投稿2023/05/24 02:00

can110

総合スコア38332

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Omihiro

2023/05/27 11:02

質問の趣旨をちゃんと整理したうえで質問すべきでした。申し訳ありません。(編集で修正しておきます) 要は仮に外れ値があると仮定して、NaN値を外れ値を含んだ平均で補完した場合に、その補完が正しく行えないケケースがあるんだったら、最初から外れ値を削除してからNaN値を補完なり、削除なりした方が自然の流れでは?という質問でした。 ただ、can110さんが言っているように、何が外れ値なのか全体を見てみないと、そもそも外れ値なのかが分からない。だから、まずは全体を把握するために、NaN値を補完なり、削除なりして全体を把握した上でどれが外れ値に該当するのかという流れが自然ということですね。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.42%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問