3
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【備忘録】機械学習プロセス(教師あり学習・教師なし学習)

Last updated at Posted at 2021-02-22

#1.機械学習の処理の手順

大まかな処理の流れは以下の8つのステップに分かれる

# ステップ 処理 使用ツール・ライブラリ
1 データ入手 スクレイピング、データの読み込み Requests、BeautifulSoup、NumPy、Pandas
2 データ加工 前処理(欠損値の対応、データの整形、データの連結処理) NumPy、Pandas
3 データ可視化 データの可視化 Matplotlib、Seaborn、Pandas
4 アルゴリズム選択 教師あり学習(分類・回帰)、教師なし学習(クラスタリング) scikit-learn(train_test_split, SVM, DecisionTreeClassifier, RandomForestClassifier, LinearRegression, LogisticRegression, PCA, KMeans, AgglomerativeClustering)
5 学習プロセス ハイパーパラメータの最適化 scikit-learn(train_test_split, GridSearchCV)
6 精度評価 ROC曲線、AUCの導出 scikit-learn(roc_curve, roc_auc_score, classification_report)
7 試験運用 (割愛) -
8 結果利用 (割愛) -

各ステップで使用するライブラリとその使い方を解説

##1-1.データ入手

###1-1-1.スクレイピング

####1-1-1-1.HTMLのtable要素の内容を取得(Pandas)

[In]
import pandas as pd

url = "https://example.com"
tables = pd.read_html(url)
df = tables[1] #サイト内の2つ目の表を抽出
df.head(20) #上位20項目を表示

####1-1-1-2.HTMLの任意の要素の内容を取得(Requests)

[In]
import requests

r = requests.get("https://example.com")

text =r.text #要素のInnerTextを取得
for line in text.split('\n'): #要素を改行して分割表示
    if '</th>' in line or '</td>' in line:
        print(line.strip()) #ブランク、空白文字を削除して出力

####1-1-1-3.HTMLを構文解析し、要素を取得する(BeautifulSoup)

[In]
import requests
from bs4 import BeautifulSoup

r = requests.get('')
soup = BeautifulSoup(r.text, 'html.parser')

###1-1-2.データの読み込み

[In]
import pandas as pd

#data変数に格納されているDataFrame化
df = pd.DataFrame(data)
#CSVファイルの読み込み
df = pd.read_csv("pokemon_galar.csv") #書き込みの場合はpd.to_csvを使用
#Excelファイルの読み込み
df = pd.read_excel("pokemon_galar.xlsx") #書き込みの場合はpd.to_excelを使用
#DataFrameファイルの読み込み 
df = pd.read_pickle("pokemon_galar.pickle") #書き込みの場合はpd.to_pickleを使用

##1-2.データ加工

###1-2-1.前処理

####1-2-1-1.欠損値の対応

#####各要素が欠損値かどうかをBool値で返す(isnull)

isnull
df.isnull()

#####欠損値の行を削除(dropna)

dropna
df.dropna()

#####欠損値を別の値で補完する(fillna)

[In]
#1つ手前の値で補完する
df.fillna(method='ffill')
#平均値で補完する
df.fillna(df.mean()) #中央値の場合はdf.median()、最頻値の場合はdf.mode().iloc[0, :]

#####欠損値を別の値で補完する(SimpleImputer)

[In]
from sklearn.impute import SimpleImputer #バージョン0.20以降

#平均値で補完する
imp = SimpleIimputer(strategy='mean') #中央値の場合は'median'、最頻値の場合は'most_frequent'
imp.fit(df)

####1-2-1-2.データの整形

#####条件で抽出

pandas
df["hp"] >= 100
df.loc[:, "hp"] >= 100
df.query('hp >= 100 and sp <= 90')

#####データ型の変換

pandas
#データ型を確認する
df.dtypes
#int型をfloat型に変換する
import numpy as np
df.loc[:, "hp"] = df.loc[:, "hp"].astype(np.float32)

#####並べ替え

pandas
df.sort_values(by="hp", ascending=False) #デフォルトはTrue(昇順)

#####不要なカラムの削除

pandas
df = df.drop("hp", axis=1) #axis=1で列方向、axis=0で行方向

#####カラム名の変更

pandas
df = df.rename(column={'HP': 'hp'}) #{'変更前': '変更後'}

#####組み合わせデータの挿入

pandas
df.loc[:, "hp/total"] = df.loc[:, "hp"] / df.loc[:, "total"]

#####ダミー関数

pandas
import pandas as pd
df_mod = pd.get_dummies(df.loc[:, "hp_index"], prefix="hp")

#####データ連結

pandas
import pandas as pd
#行方向のデータ連結
df_merged = pd.concat([df_1, df_2], axis=0)
#列方向のデータ連結
df_merged = pd.concat([df, df_new_column], axis=1)

#####時系列データの扱い

pandas
import pandas as pd
#1か月分のデータ
dates = pd.date_range(start="2020-01-01", end="2020-01-31")
#1年分365日のデータ
dates = pd.date_range(start="2020-01-01". periods=365)
#任意の曜日のデータ
sunday = pd.date_range(start="2020-01-01", end="2020-01-31", freq='W-SUN') #日曜日のみのデータ

#月平均のデータ
df.groupby(pd.Grouper(freq='M')).mean()

##1-3.データ可視化

###1-3-1.基本統計量

statistics
#最大値
df.loc[:, "hp"].max()
#最小値
df.loc[:, "hp"].min()
#最頻値
df.loc[:, "hp"].mode()
#平均値
df.loc[:, "hp"].mean()
#中央値
df.loc[:, "hp"].median()
#標準偏差
df.loc[:, "hp"].std(ddof=0) #デフォルトはddof=1

#件数のカウント
df[df.loc[:, "hp"]>=100].count()
#要約
df.describe()
#相関係数
df.corr()
#DataFrame(Pandas)→ndarray(Numpy)変換 
df.loc[:, ["hp", "sp"]].values

###1-3-2.グラフ描画

####1-3-2-1.散布図行列

pandas
from pandas.plotting import scatter_matrix
_ = scatter_matrix(df)

####1-3-2-2.Matplotlib

#####描画オブジェクト(fig)とサブプロット(ax)

matplotlib
import matplotlib.pyplot as plt
#2つのサブプロットを配置
fig, axes = plt.subplots(2)
plt.show() 

#2行2列(4つ)のサブプロットを配置
fig, axes = plt.subplots(2, 2)
fig, axes = plt.subplots(nrows=2, ncols=2)
plt.show()

#####タイトル

matplotlib
import matplotlib.pyplot as plt

fig, axes = plt.subplots(ncols=2)

#描画オブジェクトにタイトル設定
fig.subtitle('figure title')
#サブプロットにタイトル設定
axes[0].set_title('subplot title 0')
axes[1].set_title('subplot title 1')

plt.show()

#####軸ラベル

matplotlib
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

ax.set_xlabel('x label') #X軸にラベルを設定
ax.set_ylabel('y label') #Y軸にラベルを設定

plt.show()

#####凡例

matplotlib
import matplotlib.pyplot as plt

ax.plot(x, y, label='legend label')
ax.legend(loc='best') #データとの重なりが最小の場所に凡例を表示
plt.show()

#####ファイル出力

matplotlib
import matplotlib.pyplot as plt

fig.savefig('figure.png') #ファイル形式はpng, pdf, eps, svgが選択可能

####1-3-3-3.各種グラフの描画

#####折れ線グラフ

matplotlib
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

x = df["hp"]
y = df["total"]

ax.plot(x, y)

plt.show()

#####棒グラフ

(i)複数の棒グラフを並べて描画する場合

matplotlib
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

x1 = df["No."]
y1 = df["hp"]
y2 = df["speed"]

width = 0.4
ax.bar(x1, y1, width=width) #棒グラフの幅を0.4に設定

x2 = [num + width for num in x] #幅分ずらして棒グラフ2を描画
ax.bar(x2, y2, width=width)

plt.show()

(ii)積み上げ棒グラフを描画する場合

matplotlib
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

x = df["No."]
y1 = df["at"]
y2 = df["sp_attack"]

y_total = [num1 + num2 for num1, num2 in zip(y1, y2)]

ax.bar(x, y_total)
ax.bar(x, y2)

plt.show()

#####散布図

matplotlib
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

ax.scatter(df["hp"], df["total"], marker='v', label="hp-total") #下向き三角形
ax.scatter(df["attack"], df["total"], marker='^', label="attack-total") #上向き三角形
ax.scatter(df["defense"], df["total"], marker='s', label="defense-total") #正方形
ax.scatter(df["sp_attack"], df["total"], marker='*', label="sp_attack-total") #星形
ax.scatter(df["sp_defense"], df["total"], marker='x', label="sp_defense-total") #X

ax.legend()
plt.show()

#####ヒストグラム

matplotlib
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

x = df["total"]

n, bins, patches = ax.hist(x, orientation='vertical')#デフォルトはvertical、横向きに描画したい場合はhorizontal
#n:各ビンの度数
#bins:ビンの境界値
#patches:ビンを描画するための情報

plt.show()

#####箱ひげ図

matplotlib
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

x0 = df["hp"]
x1 = df["attack"]
x2 = df["defense"]

ax.boxplot(x0, x1, x2)

plt.show()

#####円グラフ

matplotlib
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

x0 = df.loc[0, "hp"] / df[0, "total"]
x1 = df.loc[0, "attack"] / df[0, "total"]
x2 = df.loc[0, "defense"] / df[0, "total"]

status = [x0, x1, x2]

ax.pie(status, startangle=90, counterclock=False) #上から時計回り
ax.axis('equal') #アスペクト比維持

plt.show()

##1-4.アルゴリズム選択

###1-4-1.分類(教師あり学習)

####1-4-1-1.テストデータと学習データの分割

scikit-learn
from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3) #テストデータ:学習データ = 3:7に分割

####1-4-1-2.サポートベクタマシン

#####学習

scikit-learn
from sklearn.svm import SVC

svc = SVC(kernel='linear', C=1e6) #線形分離、マージンの狭さ10^6

svc.fit(df["attack"], df["sp_attack"])

#####可視化

####1-4-1-3.決定木

#####学習

scikit-learn
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3)

tree = DecisionTreeClassifier(max_depth=3) #木の最大の深さを"3"に指定
tree.fit(x_train, y_train)

#####可視化

scikit-learn
from pydotplus import graph_from_dot_data
from sklearn.tree import export_graphviz

dot_data = export_graphviz(tree, 
                           filled=True, #多く分類されたノードに着色する
                           rounded=True, #ノードの角を丸くする
                           class_names=['ordinary', 'semi-legendary', 'legendary'])
                           feature_names=['hp', 'attack', 'defense', 'sp_attack', 'sp_defense', 'speed']
                           out_file=None) #ファイルを介さずにデータを渡す

graph = graph_from_dot_data(dot_data)
graph.write_png('tree.png')

####1-4-1-4.ランダムフォレスト

scikit-learn
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3)

forest = RandomForestClassifier(n_estimators=100) #決定木の個数

forest.fit(x_train, y_train)
y_pred = forest.predict(x_test)
y_pred

###1-4-2.回帰(教師あり学習)
データの読み込み・学習

scikit-learn
import pandas as pd
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split

df = pd.DataFrame(data)

x = df.loc[:, 0]
y = df.loc[:, 1]

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3)

lr = LinearRegression() 
lr.fit(x_train, y_train) 

y_pred = lr.predict(x_test)

可視化

scikit-learn
import matplotlib.pyplot as plt

fig, ax = plt.subplots()

ax.scatter(y_pred, y_test) #x軸を予測値、y軸を実績値として予測の精度を散布図で可視化する
ax.plot((0, 50), (0, 50), linestyle='dashed', color='red') #45度線の描画

ax.set_xlabel('predicted value')
ax.set_ylabel('actual value')

plt.show()

###1-4-2-1.次元削減

###1-4-2-2.主成分分析

scikit-learn
from sklearn.decomposition import PCA

pca = PCA(n_components=2) #新たな2変数に変換
x_pca = pca.fit_transform(df[:, "hp"], df[:, "total"])

fig, ax = plt.subplots()
ax.scatter(x_pca[:, 0], x_pca[:, 1])
plt.show()

###1-4-5.クラスタリング(教師なし学習)

####1-4-5-1.k-means
データの読み込み・学習

scikit-learn
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

df = pd.read_csv("data.csv")

fig, ax = plt.subplots()
ax.scatter(df.loc[:, 0], df.loc[:, 1])

km = KMeans(n_cluster=2, init=ramdom, n_init=10)
#クラスタ数:2
#初期値:ランダムに乱数で生成
#k-means実行回数:10

y_km = km.fit_predict(df)

可視化

scikit-learn
import numpy as np
fig, ax = plt.subplots()

#クラスタ1散布図
ax.scatter(df[y_km == 0, 0], df[y_km == 0, 1], s=50, edgecolor='black', marker='s', label='cluster1')

#クラスタ1中心
ax.scatter(np.mean(df[y_km == 0, 0]), np.mean(df[y_km == 0, 1]))

#クラスタ2散布図
ax.scatter(df[y_km == 1, 0], df[y_km == 1, 1], s=50, edgecolor='black', marker='o', label='cluster2')

#クラスタ2中心
ax.scatter(np.mean(df[y_km == 1, 0]), np.mean(df[y_km == 1, 1]))

ax.legend()
plt.show()

####1-4-5-2.階層的クラスタリング(凝集型)
データの読み込み

scikit-learn
import pandas as pd
from sklearn.cluster import AgglomerativeClustering

df = pd.read_csv("data.csv")

ac = AgglomerativeClustering(n_cluster=3, affinity='euclidean', linkage='complete')
#最大クラスタ数:3
#リンケージ手法:complete

labels = ac.fit_predict(df)
labels

可視化

scikit-learn
import numpy as np
from scipy.cluster.hierarchy import dendrogram #樹形図を描画するライブラリ

#子クラスタとの関係を抽出
children = ac.children_

#クラスタ間の距離を抽出
distance = np.arrange(children.shape[0])

#各データの観測番号
number_of_observations = np.arange(2, children.shape[0]+2)

#子クラスタ、クラスタ間の距離、観測番号を列方向に結合
linkage_matrix = np.hstack((children,
                            distance[:, np.newaxis],
                            number_of_observations[:, np.newaxis])).astype(float)

fig, ax = plt.subplots(figsize=(15, 3), dpi=300)
dendrogram(linkage_matrix, labels=np.arange(100), leaf_front_size=8, color_threshold=np.inf)
plt.show()

##1-5.学習プロセス

###1-5-1.ハイパーパラメータの最適化

####1-5-1-1.グリッドサーチ

##1-6.精度評価

###1-6-1.カテゴリの分類精度

指標 説明 計算式
適合率(precision) 正例と予測したデータのうち、実際に正例の割合 真陽性/(真陽性+偽陽性) 偽陽性をなくしたい際に求める
再現率(recall) 実際の正例のうち、正例と予測したものの割合 真陽性/(真陽性+偽陰性) 偽陰性をなくしたい際に求める
F値(F-Value) 適合率と再現率の調和平均 2適合率再現率/(適合率+再現率)
正解率(accuracy) 正例、負例にかかわらず、予測が的中した割合 真陽性+真陰性/全データ

###1-6-2.分類精度の出力

scikit-learn
from sklearn.metrics import classification_report

print(classification_report(y_test, y_pred))

###1-6-3.交差検証

scikit-learn
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score

svc = SVC()

x = df.loc[;, "hp"]
y = df.loc[:, "total"]

cross_val_score(svc, x, y, cv=10, scoring='precision')
#分割数:10
#評価指標:適合率(precision)

###1-6-4.ROC曲線の可視化

matplotlib
import numpy as np
import matplotlib.pyplot as plt

fpr = df.loc[:, "false_positive_rate"].values()/ n1 #n1:偽陽性のデータの個数
tpr = df.loc[:, "true_positive_rate"].values()/ n2 #n2:真陽性のデータの個数

fig, ax = plt.subplots()
ax.step(fpr, tpr) #ROC曲線を描画
ax.set_xlabel('false positive rate')
ax.set_ylabel('true positive rate')
plt.show()

###1-6-5.AUC

AUCとは...ROC曲線の下側の面積の合計。1に近づくほど正例と負例の区別がつきやすくなり、0に近づくほど区別がつかなくなる。

3
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?