目次
概要
作成したもの
- 高収入者分類データセットを前処理
使用した技術・ライブラリ
- Pandas
- Scikit-learn
- seaborn
動機
Deep Learning関連の案件でデータの前処理をする機会が多かったので、一度整理してみました。
なぜデータの前処理が必要なのか
まず、何らかの手段で欲しいデータが手に入ったとして、そのデータが完璧である可能性はほぼありません。
大抵データ内には欠損、ノイズ、エラー値などがあります。これらは無視してもよい場合もありますが、データの欠けに対しては適切な値で埋めたり、好ましくないデータ値は除いたりする必要があります。
高収入者分類データ
データの概要
学歴や出身などの経歴データをもとに年収が50Kドル以上かどうかが分類されたデータセット(adult Dataset)です。
アメリカの国税局のデータベースをもとに作成されたデータセットになります。Adult Datasetと表記されていますが怪しくはないです。
ターゲットとなる情報は、
age: continuous.
workclass: Private, Self-emp-not-inc, Self-emp-inc, Federal-gov, Local-gov, State-gov, Without-pay, Never-worked.
fnlwgt: continuous.
education: Bachelors, Some-college, 11th, HS-grad, Prof-school, Assoc-acdm, Assoc-voc, 9th, 7th-8th, 12th, Masters, 1st-4th, 10th, Doctorate, 5th-6th, Preschool.
education-num: continuous.
marital-status: Married-civ-spouse, Divorced, Never-married, Separated, Widowed, Married-spouse-absent, Married-AF-spouse.
occupation: Tech-support, Craft-repair, Other-service, Sales, Exec-managerial, Prof-specialty, Handlers-cleaners, Machine-op-inspct, Adm-clerical, Farming-fishing, Transport-moving, Priv-house-serv, Protective-serv, Armed-Forces.
relationship: Wife, Own-child, Husband, Not-in-family, Other-relative, Unmarried.
race: White, Asian-Pac-Islander, Amer-Indian-Eskimo, Other, Black.
sex: Female, Male.
capital-gain: continuous.
capital-loss: continuous.
hours-per-week: continuous.
native-country: United-States, Cambodia, England, Puerto-Rico, Canada, Germany, Outlying-US(Guam-USVI-etc), India, Japan, Greece, South, China, Cuba, Iran, Honduras, Philippines, Italy, Poland, Jamaica, Vietnam, Mexico, Portugal, Ireland, France, Dominican-Republic, Laos, Ecuador, Taiwan, Haiti, Columbia, Hungary, Guatemala, Nicaragua, Scotland, Thailand, Yugoslavia, El-Salvador, Trinadad&Tobago, Peru, Hong, Holand-Netherlands.
で、
クラスは、
50K, <=50K.
に分類されます。
ダウンロード
UCI(様々なデータセットが登録なしで無料で公開されているサイト)
https://archive.ics.uci.edu/ml/datasets/Adult
から高収入判別データ(adult.data)をダウンロードします。
インストール
前処理をするうえで必要なライブラリをインストールしていきます。Python3.xxでの環境になります。
pip seaborn
pip install pandas
pip install scikit-learn
データ整形
jupyter-notebook上で実行結果を確認しながら、データを整形していきます。
データの読み込み
ダウンロードしたデータセットを読み込みます。
必要なライブラリをインポートしてから、
データフレームでヘッダーを指定しCSV形式で読み込み、読み込んだ結果を確認します。
csv_path = './adult.csv' header = ["x__0:age", "x__1:workplace", "x__2:fnlwgt", "x__3:education", "x__4:education_num", "x__5:marital-status", "x__6:occupation", "x__7:relationship", "x__8:race", "x__9:sex", "x__10:capital-gain", "x__11:capital-loss", "x__12:hours-per-week", "x__13:native-country", "y:class"] df=pd.read_csv(csv_path, sep=',',names = header) print(len(df)) df.head()
ヘッダー付きでCSVデータが読み込めていることが確認できます。
x__0:age x__1:workplace x__2:fnlwgt x__3:education x__4:education_num x__5:marital-status x__6:occupation x__7:relationship x__8:race x__9:sex x__10:capital-gain x__11:capital-loss x__12:hours-per-week x__13:native-country y:class 0 39 State-gov 77516 Bachelors 13 Never-married Adm-clerical Not-in-family White Male 2174 0 40 United-States <=50K 1 50 Self-emp-not-inc 83311 Bachelors 13 Married-civ-spouse Exec-managerial Husband White Male 0 0 13 United-States <=50K 2 38 Private 215646 HS-grad 9 Divorced Handlers-cleaners Not-in-family White Male 0 0 40 United-States <=50K 3 53 Private 234721 11th 7 Married-civ-spouse Handlers-cleaners Husband Black Male 0 0 40 United-States <=50K 4 28 Private 338409 Bachelors 13 Married-civ-spouse Prof-specialty Wife Black Female 0 0 40 Cuba <=50K
欠損値の処理
今回のデータセットには欠損値[?]が含まれています。
欠損値が1つでも含まれている行はすべて削除するように前処理をします。
欠損値をNaNに置き換え、pandasの関数を使って欠損値が含まれる行を削除します。
# 欠損が含まれる行を全て削除 df.replace(' ?', np.nan, inplace=True) df.dropna(how="any", inplace=True) print(len(df))
ラベルの置き換え
DeepLearningに突っ込むためにデータをすべて数値に変換します。
置き換え作業をするカラムを指定し、ラベルにユニークな数値を振っています。
また、capital-gainとcapital-lossの値を0,1(有り無し)に変換します。
for column in df.columns: if column in ["x__1:workplace","x__3:education","x__5:marital-status","x__6:occupation","x__7:relationship","x__8:race","x__9:sex","x__13:native-country","y:class"]: labels, uniques = pd.factorize(df[column]) df[column] = labels # x__10:capital-gainとx__11:capital-lossを0,1に変換 df.loc[df["x__10:capital-gain"] > 0, "x__10:capital-gain"] = 1 df.loc[df["x__11:capital-loss"] > 0, "x__11:capital-loss"] = 1 df["x__2:fnlwgt"] = 0 df.head()
ラベルがすべて数値化されていることが確認できます。
x__0:age x__1:workplace x__2:fnlwgt x__3:education x__4:education_num x__5:marital-status x__6:occupation x__7:relationship x__8:race x__9:sex x__10:capital-gain x__11:capital-loss x__12:hours-per-week x__13:native-country y:class 0 39 0 0 0 13 0 0 0 0 0 1 0 40 0 0 1 50 1 0 0 13 1 1 1 0 0 0 0 13 0 0 2 38 2 0 1 9 2 2 0 0 0 0 0 40 0 0 3 53 2 0 2 7 1 2 1 1 0 0 0 40 0 0 4 28 2 0 0 13 1 3 2 1 1 0 0 40 1 0
クラス分布の確認
各クラスごとの数をseabornの棒グラフで表示します。
sns.countplot(data=df, x='y:class') plt.title('0:>50K 1:<=50K')
分布に偏りがあることが確認できます。
クラス数の調整
クラス数が一様になるように調整します。
データをシャッフルし、一番少ないクラスの数に合わせます。
# ダウンサンプリング df_shuffle = df.sample(frac=1) # シャッフル mim_count = df_shuffle['y:class'].value_counts().iat[-1] # 一番少ないクラス数 gdf = df.groupby('y:class') gdf = gdf.head(mim_count) sns.countplot(data=gdf, x='y:class')
データ数が減ってしまいましたが、クラス数を一様にすることができました。
学習データの分割
データセットを学習データと検証データに分割します。
scikit-learnを使って、8:2にデータセットを分割し、それぞれCSVファイルに出力しています。
from sklearn.model_selection import train_test_split x=np.array(gdf.iloc[:,:-1]) y=np.array(gdf.iloc[:,-1]) # データセットの分割 x_train, x_test, y_train, y_test = train_test_split(x, y, train_size=0.8, random_state=0, stratify=y)# csvに保存 # 学習データ train_data = np.concatenate([x_train, y_train[:, np.newaxis]], 1) train_df = pd.DataFrame(data=train_data, columns=df.columns.values) train_df['y:class'].astype(np.int64) # 検証データ test_data = np.concatenate([x_test, y_test[:, np.newaxis]], 1) test_df = pd.DataFrame(data=test_data, columns=df.columns.values) test_df['y:class'].astype(np.int64) # CSV出力 train_df.to_csv('adult_train.csv', index=False) test_df.to_csv('adult_test.csv', index=False)
結論・感想
講習収入者データの整形をしました。データの整形は機械学習をする上で面倒ですが、避けられない作業です。
この作業によってモデルの結果の良し悪しに大きく左右されます。
今回欠損は削除する処理をしましたが、次回は補完をやっていきたいと思います。