実現したいこと
機械学習のフェーズに入って約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)

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2023/05/27 11:02