In [1]:
from IPython.core.display import display
import pandas as pd
from io import StringIO
csv_data = '''A,B,C,D
1.0,2.0,3.0,4.0
5.0,6.0,,8.0
10.0,11.0,12.0,'''
df = pd.read_csv(StringIO(csv_data))
df
Out[1]:
In [2]:
# 各特徴量の欠測値をカウント
df.isnull().sum()
Out[2]:
In [3]:
df.values
Out[3]:
In [4]:
# 欠測値を含む行を削除
df.dropna()
Out[4]:
In [5]:
# 欠測値を含む列を削除
df.dropna(axis=1)
Out[5]:
In [6]:
# すべての列がNaNである行だけを削除
df.dropna(how='all')
# 非NaN値が4つ未満の行を削除
df.dropna(thresh=4)
# 特定の列にNaNが含まれている行だけを削除
df.dropna(subset=['C'])
Out[6]:
In [7]:
from sklearn.preprocessing import Imputer
# 欠測値補完のインスタンスを生成(平均値補完)
# median: 中央値、most_frequent: 最頻値
imr = Imputer(missing_values='NaN', strategy='mean', axis=0)
# データを適合
imr = imr.fit(df)
# 補完を実行
imputed_data = imr.transform(df.values)
imputed_data
Out[7]:
In [8]:
import pandas as pd
# サンプルデータを生成
df = pd.DataFrame([
['green', 'M', 10.1, 'class1'],
['red', 'L', 13.5, 'class2'],
['blue', 'XL', 15.3, 'class1'],
])
# 列名を設定
df.columns = ['color', 'size', 'price', 'classlabel']
df
Out[8]:
In [9]:
# Tシャツのサイズと整数を対応させるディクショナリを生成
size_mapping = {'XL': 3, 'L': 2, 'M': 1}
# Tシャツのサイズを整数に変換
df['size'] = df['size'].map(size_mapping)
df
Out[9]:
In [10]:
# Tシャツのサイズを文字列に戻す辞書
inv_size_mapping = {v: k for k, v in size_mapping.items()}
inv_size_mapping
Out[10]:
In [11]:
import numpy as np
# クラスラベルと整数を対応させる辞書
class_mapping = {label: i for i, label in enumerate(np.unique(df['classlabel']))}
class_mapping
Out[11]:
In [12]:
# クラスラベルを整数に変換
df['classlabel'] = df['classlabel'].map(class_mapping)
df
Out[12]:
In [13]:
inv_class_mapping = {v: k for k, v in class_mapping.items()}
# 整数からクラスラベルに変換
df['classlabel'] = df['classlabel'].map(inv_class_mapping)
df
Out[13]:
In [14]:
from sklearn.preprocessing import LabelEncoder
class_le = LabelEncoder()
y = class_le.fit_transform(df['classlabel'].values)
y
Out[14]:
In [15]:
class_le.inverse_transform(y)
Out[15]:
In [16]:
# Tシャツの色、サイズ、価格を抽出
X = df[['color', 'size', 'price']].values
color_le = LabelEncoder()
X[:, 0] = color_le.fit_transform(X[:, 0])
X
Out[16]:
In [17]:
from sklearn.preprocessing import OneHotEncoder
# one-hot エンコーダの生成
ohe = OneHotEncoder(categorical_features=[0])
# one-hot エンコーディングを実行
ohe.fit_transform(X).toarray()
Out[17]:
In [18]:
# one-hot エンコーディングを実行
pd.get_dummies(df[['price', 'color', 'size']])
Out[18]:
In [19]:
# http://archive.ics.uci.edu/ml/datasets/Wine
df_wine = pd.read_csv('http://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data', header=None)
display(df_wine.head())
# 列名を設定
df_wine.columns = ['Class label', 'Alcohol', 'Malic acid', 'Ash', 'Alcalinity of ash', 'Magnesium', 'Total phenols',
'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins', 'Color intensity', 'Hue',
'OD280/OD315 of diluted wines', 'Proline']
display(df_wine.head())
print('Class labels', np.unique(df_wine['Class label']))
In [20]:
from sklearn.cross_validation import train_test_split
# 特徴量とクラスラベルを別々に抽出
X, y = df_wine.iloc[:, 1:].values, df_wine.iloc[:, 0].values
# 全体の30%をテストデータにする
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
In [21]:
from sklearn.preprocessing import MinMaxScaler
# min-max スケーリングのインスタンスを生成
mms = MinMaxScaler()
# トレーニングデータをスケーリング
X_train_norm = mms.fit_transform(X_train)
# テストデータをスケーリング
X_test_norm = mms.transform(X_test)
X_train, X_train_norm
Out[21]:
In [22]:
from sklearn.preprocessing import StandardScaler
# 標準化のインスタンスを生成
stdsc = StandardScaler()
X_train_std = stdsc.fit_transform(X_train)
X_test_std = stdsc.transform(X_test)
X_train_std
Out[22]:
In [23]:
from sklearn.linear_model import LogisticRegression
# L1正則化ロジスティック回帰のインスタンスを生成
LogisticRegression(penalty='l1')
# L1正則化ロジスティック回帰のインスタンスを生成(逆正則化パラメータ C=0.1)
lr = LogisticRegression(penalty='l1', C=0.1)
lr.fit(X_train_std, y_train)
print('Training accuracy:', lr.score(X_train_std, y_train))
print('Test accuracy:', lr.score(X_test_std, y_test))
In [24]:
# 切片の表示
lr.intercept_
Out[24]:
In [25]:
# 重み係数の表示
lr.coef_
Out[25]:
In [26]:
import matplotlib.pyplot as plt
fig = plt.figure()
ax = plt.subplot(111)
colors = ['blue', 'green', 'red', 'cyan', 'magenta', 'yellow', 'black',
'pink', 'lightgreen', 'lightblue', 'gray', 'indigo', 'orange']
# 空のリストを生成(重み係数、逆正則化パラメータ
weights, params = [], []
# 逆正則化パラメータの値ごとに処理
for c in np.arange(-4, 6):
# print(c) # -4~5
lr = LogisticRegression(penalty='l1', C=10 ** c, random_state=0)
lr.fit(X_train_std, y_train)
weights.append(lr.coef_[1])
params.append(10 ** c)
# 重み係数をNumPy配列に変換
weights = np.array(weights)
# 各重み係数をプロット
# print(weights.shape[1]) # -> 13
for column, color in zip(range(weights.shape[1]), colors):
plt.plot(params, weights[:, column], label=df_wine.columns[column + 1], color=color)
# y=0 に黒い破線を引く
plt.axhline(0, color='black', linestyle='--', linewidth=3)
plt.xlim([10 ** (-5), 10 ** 5])
# 軸のラベルの設定
plt.ylabel('weight coefficient')
plt.xlabel('C')
# 横軸を対数スケールに設定
plt.xscale('log')
plt.legend(loc='upper left')
ax.legend(loc='upper center', bbox_to_anchor=(1.38, 1.03), ncol=1, fancybox=True)
plt.show()
In [41]:
from sklearn.base import clone
from itertools import combinations
import numpy as np
from sklearn.cross_validation import train_test_split
from sklearn.metrics import accuracy_score
class SBS():
"""
逐次後退選択(sequencial backward selection)を実行するクラス
"""
def __init__(self, estimator, k_features, scoring=accuracy_score,
test_size=0.25, random_state=1):
self.scoring = scoring # 特徴量を評価する指標
self.estimator = clone(estimator) # 推定器
self.k_features = k_features # 選択する特徴量の個数
self.test_size = test_size # テストデータの悪愛
self.random_state = random_state # 乱数種を固定する random_state
def fit(self, X, y):
# トレーニングデータとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=self.test_size,
random_state=self.random_state)
#print(len(X_train), len(X_test), len(y_train), len(y_test))
# 全ての特徴量の個数、列インデックス
dim = X_train.shape[1]
self.indices_ = tuple(range(dim))
self.subsets_ = [self.indices_]
#print(self.indices_)
# 全ての特徴量を用いてスコアを算出
score = self._calc_score(X_train, y_train, X_test, y_test, self.indices_)
# スコアを格納
self.scores_ = [score]
# 指定した特徴量の個数になるまで処理を反復
while dim > self.k_features:
# 空のリストの生成(スコア、列インデックス)
scores = []
subsets = []
# 特徴量の部分集合を表す列インデックスの組み合わせ毎に処理を反復
for p in combinations(self.indices_, r=dim - 1):
# スコアを算出して格納
score = self._calc_score(X_train, y_train, X_test, y_test, p)
scores.append(score)
# 特徴量の部分集合を表す列インデックスのリストを格納
subsets.append(p)
# 最良のスコアのインデックスを抽出
best = np.argmax(scores)
# 最良のスコアとなる列インデックスを抽出して格納
self.indices_ = subsets[best]
self.subsets_.append(self.indices_)
# 特徴量の個数を1つだけ減らして次のステップへ
dim -= 1
# スコアを格納
self.scores_.append(scores[best])
# 最後に格納したスコア
self.k_score_ = self.scores_[-1]
return self
def transform(self, X):
# 抽出した特徴量を返す
return X[:, self.indices_]
def _calc_score(self, X_train, y_train, X_test, y_test, indices):
# 指定された列番号 indices の特徴量を抽出してモデルに適合
self.estimator.fit(X_train[:, indices], y_train)
# テストデータを用いてクラスラベルを予測
y_pred = self.estimator.predict(X_test[:, indices])
# 真のクラスラベルと予測値を用いてスコアを算出
score = self.scoring(y_test, y_pred)
return score
In [46]:
from sklearn.neighbors import KNeighborsClassifier
import matplotlib.pyplot as plt
knn = KNeighborsClassifier(n_neighbors=2)
sbs = SBS(knn, k_features=1)
sbs.fit(X_train_std, y_train)
Out[46]:
In [47]:
# 近傍点の個数のリスト
k_feat = [len(k) for k in sbs.subsets_]
display(k_feat)
# 横軸を近傍店の個数、縦軸をスコアとした折れ線グラフのプロット
plt.plot(k_feat, sbs.scores_, marker='o')
plt.ylim([0.7, 1.1])
plt.ylabel('Accuracy')
plt.xlabel('Number of features')
plt.grid()
plt.show()
In [49]:
k5 = list(sbs.subsets_[8])
print(k5)
print(df_wine.columns[1:][k5])
In [53]:
# 13個全ての特徴量を用いてモデルに適合
knn.fit(X_train_std, y_train)
# トレーニングの正解率を出力
print('Training accuracy:', knn.score(X_train_std, y_train))
# テストの正解率を出力
print('Test accuracy:', knn.score(X_test_std, y_test))
In [55]:
# 5個の特徴量を用いてモデルに適合
knn.fit(X_train_std[:, k5], y_train)
# トレーニングの正解率を出力
print('Training accuracy:', knn.score(X_train_std[:, k5], y_train))
# テストの正解率を出力
print('Test accuracy:', knn.score(X_test_std[:, k5], y_test))
In [62]:
from sklearn.ensemble import RandomForestClassifier
# Wine データセットの特徴量の名所
feat_labels = df_wine.columns[1:]
# ランダムフォレストオブジェクトの生成
# (木の個数=10,000、すべての怖を用いて並列計算を実行
forest = RandomForestClassifier(n_estimators=10000, random_state=0, n_jobs=-1)
# モデルに適合
forest.fit(X_train, y_train)
# 特徴量の重要度を抽出
importances = forest.feature_importances_
# 重要度の降順で特徴量のインデックスを抽出
indices = np.argsort(importances)[::-1]
# 重要度の降順で特徴量の名称、重要度を表示
for f in range(X_train.shape[1]):
print("{:2d}) {:<30} {:f}".format(f + 1, feat_labels[indices[f]], importances[indices[f]]))
plt.title('Feature Importances')
plt.bar(range(X_train.shape[1]), importances[indices], color='lightblue', align='center')
plt.xticks(range(X_train.shape[1]), feat_labels[indices], rotation=90)
plt.xlim([-1, X_train.shape[1]])
plt.tight_layout()
plt.show()
In [65]:
from sklearn.feature_selection import SelectFromModel
# 特徴選択オブジェクトの生成(重要度のしきい値を0.15に設定)
sfm = SelectFromModel(forest, prefit=True, threshold=0.15)
# 特徴量を抽出
X_selected = sfm.transform(X_train)
X_selected.shape
Out[65]:
In [66]:
for f in range(X_selected.shape[1]):
print("{:2d}) {:<30} {:f}".format(f + 1, feat_labels[indices[f]], importances[indices[f]]))