各種ライブラリのインポート
今回必要のないものも含んでいるので必要がなければ削除して使ってください。
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import sklearn.preprocessing as sp
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import StandardScaler
import pydotplus
from IPython.display import Image
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn import tree
# Scikit-learn(評価算出)
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import StratifiedKFold, cross_val_score
from sklearn import metrics
# graphvizのdotファイルを生成する
from sklearn import datasets
from sklearn.cluster import MiniBatchKMeans
from sklearn import tree
ファイルの読み込み
train=pd.read_table('./train.tsv')
test=pd.read_table('./test.tsv')
sub=pd.read_csv('./sample_submit.csv')
欠損値の確認
欠損値の有無は必ず確認するようにしています。
学習データとテストデータ両方とも確認しましょう。
train.isnull().sum()
テストデータも同様に実行(表示しませんが、欠損値はありませんでした)
pandasでカテゴリ変数をダミー変数に変換
文字列が入っている項目を符号化することは「エンコーディング」と呼び、機械学習では精度に関わる重要な作業となります。
機械学習では文字列を数値化しなければ計算することができません。
そこで例えば「赤、青、白」と言う文字列を「1,2,3」と単純に数値化してしまうと1~3は連続値と認識されてしまい、学習に悪影響が出てしまいます。
そこで、今回はget_dummiesを使います。
get_dummiesはカテゴリ変数の項目毎に、カテゴリ変数の値がその項目なら「1」、そうでないなら「0」になる新たな列を作成してくれます。
X_train=pd.get_dummies(train[['gill-color','gill-attachment','odor','cap-color']])
X_train['Y']=train['Y']
X_train.head()
結果、このようにgill-colorには「b,e,g・・・」などの文字として入力されていたものがそれぞれ項目として出力され「0」「1」で入力されます。
-
その他のエンコーディング手法
★列数を増やすエンコーディング
・OheHot Encoding
・Hash Encoding
★列数を増やさないエンコーディング
・Ordinal Encoding
・Target Encoding
ダミー変数としたデータの割合を知る
データセットの中身を知る上で説明変数内に何がどの割合存在するかを知っておくと何かと便利です。
まずは目的変数のYについてp(毒)の場合は「1」をそれ以外には「0」を入力します。
X_train['classes']=X_train['Y'].map(lambda x:1 if x=='p' else 0)
X_train['classes']
<bound method Series.sum of 0 1 1 1 2 0 3 1 4 1 .. 4057 1 4058 1 4059 1 4060 1 4061 1 Name: classes, Length: 4062, dtype: int64>
それでは、説明変数とするcap-color_cやbにそれぞれいくつの対象が存在しているかを確認します。
この時、groupbyを使って要素をグループ化して処理すると見やすいです。
X_train.groupby(['cap-color_c','Y'])['Y'].count().unstack()
目的変数のYはどうでしょう。
ここでは試しにunstack()を抜いて出力してみます。
X_train.groupby('Y')['Y'].count()
Y e 2103 p 1959 Name: Y, dtype: int64
無事にダミー変数を使ったエンコーディングができていることが確認できました。
ここまででデータの前処理は終わりです。
決定木を使ったコード例
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import sklearn.preprocessing as sp
from sklearn.preprocessing import OneHotEncoder
from sklearn.preprocessing import StandardScaler
import pydotplus
from IPython.display import Image
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier
from sklearn import tree
# Scikit-learn(評価算出)
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
from sklearn.model_selection import StratifiedKFold
from sklearn.model_selection import StratifiedKFold, cross_val_score
from sklearn import metrics
# graphvizのdotファイルを生成する
from sklearn import datasets
from sklearn.cluster import MiniBatchKMeans
from sklearn import tree
train=pd.read_table('./train.tsv')
test=pd.read_table('./test.tsv')
sub=pd.read_csv('./sample_submit.csv')
X_train=pd.get_dummies(train[['gill-color','gill-attachment','odor','cap-color']])
XX_test=pd.get_dummies(test[['gill-color','gill-attachment','odor','cap-color']])
X_train['Y']=train['Y']
X_train['classes']=X_train['Y'].map(lambda x:1 if x=='p' else 0)
X_train=X_train.drop('Y', axis=1)
Y=X_train['classes']
X=X_train.drop('classes', axis=1)
X_train, X_test, y_train, y_test = train_test_split(X, Y, test_size=0.05, random_state=1)
clf=tree.DecisionTreeRegressor(max_depth=10, random_state=1)
# clf = RandomForestClassifier(n_estimators=200, max_depth=20, random_state=1)
clf.fit(X_train, y_train)
y_pred = clf.predict(XX_test)
print ('Score: ',clf.score(X_test, y_test))#正解率の表示
#K分割交差検証
stratifiedkfold = StratifiedKFold(n_splits=10) #K=10分割
scores = cross_val_score(clf, X_train, y_train, cv=stratifiedkfold)
print('Cross-Validation scores: {}'.format(scores)) # 各分割におけるスコア
print('Average score: {}'.format(np.mean(scores))) # スコアの平均値
kmeans = MiniBatchKMeans(n_clusters=7, max_iter=300)
kmeans_result = kmeans.fit_predict(X_train)
features = X_train.columns
with open("tree.dot", 'w') as f:
tree.export_graphviz(
clf,
out_file=f,
feature_names=features,
filled=True,
rounded=True,
special_characters=True,
impurity=False,
proportion=False,
class_names=list(map(str, range(0, np.max(kmeans_result)+1)))
)
Score: 0.9851672614983253 Cross-Validation scores: [0.9700363 0.97976176 0.96777507 0.99717024 0.96404757 0.97596045 0.98062093 0.96526717 0.97392876 0.98776665] Average score: 0.9762334905066364
決定木の出力(max_depth=5の場合)
import pydotplus
from IPython.display import Image
graph = pydotplus.graphviz.graph_from_dot_file('tree.dot')
graph.write_png('tree.png')
Image(graph.create_png())
提出データへの変換
予測が0.5以上を1、それ以外を0としたのちに「p」と「e」に項目名を変換して提出とします。
提出時はラベルがない状態での提出なので削除して提出します。
for i in range(4062):
if y_pred[i]>=0.5:
y_pred[i]=1
else:
y_pred[i]=0
sub['id'] = test['id']
sub['Y'] = list(map(int, y_pred))
sub['Y']=sub['Y'].replace([1, 0], ["p", "e"])
sub.to_csv('submission.csv', index=False)
以上です。