0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

機械学習初学習ノート! ~前編(Pythonと教師あり・なし学習)~

Last updated at Posted at 2026-01-21

初めに

こんにちは!L_Gravityです!機械学習の勉強が楽しそうだったので手を付けてみました!
gacco上のこちらの無料講座を受けながらとったノートを自分でもってくだけではもったいない気がしたので、他の初学者の方向けに公開したものです!

わかりやすく正しい情報であることを保証はしませんが、是非お使いください!

主要ライブラリの使い方

Numpy

だいたいこう使う

import numpy as np
from sklearn import datasets
Iris = datasets.load_iris()

#データの形式
print (Iris.feature_names)


#先頭5行目までのデータの取り出し
print (Iris.data[:5])
# n 行 m 列目のデータの取り出し
print (Iris.data[n, m])
#列の題名
print (Iris.target_names)
#2列目だけ切り抜く
print (Iris.data[:,2])
#2行目だけ切り抜く
print (Iris.data[2,:])


#最大値
print(np.max(Iris.data[:,2]))
#最小値
print(np.min(Iris.data[:,2]))
#中央値
print(np.median(Iris.data[:,2]))
#ソート
print("データ", np.sort(Iris.data[:,2]))
#平均値
print(np.mean(Iris.data[:,2]))
#分散
print(np.var(Iris.data[:,2]))
#標準偏差
print(np.std(Iris.data[:,2]))

#四分位数
Q1 = np.percentile(Iris.data[:,2], 25)
Q3 = np.percentile(Iris.data[:,2], 75)

#四分位範囲
IQR = Q3 - Q1
print(IQR)

# 相関係数
correlation_matrix = np.corrcoef(Iris.data[:,2], Iris.data[:,3])
print(correlation_matrix)
print("Correlation coefficient between petal length and petal width:", correlation_matrix[0, 1])

# 共分散
covariance_matrix = np.cov(Iris.data[:,2], Iris.data[:,3])
print(covariance_matrix)
print("Covariance between petal length and petal width:", covariance_matrix[0, 1])

# 標本偏差
std_dev = np.std(Iris.data[:,2], ddof=1)
print("Sample standard deviation of petal length:", std_dev)


#まとめ
print("データ", Iris.data[:,2])
print("ソート後データ", np.sort(Iris.data[:,2]))
print("中央値", np.median(Iris.data[:,2]))
print("平均値", np.mean(Iris.data[:,2]))
print("最大値", np.max(Iris.data[:,2]))
print("最小値", np.min(Iris.data[:,2]))
print("分散", np.var(Iris.data[:,2]))
print("標準偏差", np.std(Iris.data[:,2]))
print("四分位範囲", IQR)
print("相関係数", correlation_matrix[0, 1])
print("共分散", covariance_matrix[0, 1])
print("標本偏差", std_dev)

出力例

中央値 4.35
平均値 3.7580000000000005
最大値 6.9
最小値 1.0
分散 3.0955026666666665
標準偏差 1.759404065775303
四分位範囲 3.4999999999999996
相関係数 0.9628654314027963
共分散 1.2956093959731545
標本偏差 1.7652982332594662

Matplotlib

だいたいこう使う(上のものと合わせて)

#ヒストグラム
import matplotlib.pyplot as plt
plt.hist(Iris.data[:,2], bins=10, edgecolor='black')
plt.title('Histogram of Iris Petal Lengths')
plt.xlabel('Petal Length (cm)')
plt.ylabel('Frequency')
plt.show()

# 箱ひげ図
plt.boxplot(Iris.data[:,2], vert=True, patch_artist=True)
plt.title('Boxplot of Iris Petal Lengths')
plt.ylabel('Petal Length (cm)')
plt.show()

# 散布図
plt.scatter(Iris.data[:,2], Iris.data[:,3], c=Iris.target,
            cmap='viridis', edgecolor='k', s=100)
plt.title('Scatter Plot of Iris Petal Length vs Width') 
plt.xlabel('Petal Length (cm)')
plt.ylabel('Petal Width (cm)')
plt.show()

pandas

だいたいこう使う(上のものと合わせて)

import pandas as pd
#データフレームの作成
df = pd.DataFrame(data=Iris.data, columns=Iris.feature_names)
#基本統計量
print(df.describe())
#相関行列
print(df.corr())


#データ
print(df.iloc[:,2])
#最大値
print(df.iloc[:,2].max())
#最小値
print(df.iloc[:,2].min())
#中央値
print(df.iloc[:,2].median())
#ソート
print(df.iloc[:,2].sort_values())
#平均値
print(df.iloc[:,2].mean())
#分散
print(df.iloc[:,2].var())
#標準偏差
print(df.iloc[:,2].std())

#四分位数
Q1_df = df.iloc[:,2].quantile(0.25)
Q3_df = df.iloc[:,2].quantile(0.75)
IQR_df = Q3_df - Q1_df
print(IQR_df)

#相関係数
correlation_df = df.iloc[:,2].corr(df.iloc[:,3])
print(correlation_df)

#共分散
covariance_df = df.iloc[:,2].cov(df.iloc[:,3])
print(covariance_df)

#標本偏差
std_dev_df = df.iloc[:,2].std(ddof=1)

#出力
print(std_dev_df)
print("データ", df.iloc[:,2])
print("ソート後データ", df.iloc[:,2].sort_values())
print("中央値", df.iloc[:,2].median())
print("平均値", df.iloc[:,2].mean())
print("最大値", df.iloc[:,2].max())
print("最小値", df.iloc[:,2].min())
print("分散", df.iloc[:,2].var())
print("標準偏差", df.iloc[:,2].std())
print("四分位範囲", IQR_df)
print("相関係数", correlation_df)
print("共分散", covariance_df)
print("標本偏差", std_dev_df)


#グラフをかく(+plt)

#ヒストグラム
df.iloc[:,2].hist(bins=10, edgecolor='black')
plt.title('Histogram of Iris Petal Lengths (DataFrame)')
plt.xlabel('Petal Length (cm)')
plt.ylabel('Frequency')
plt.show()

#箱ひげ図
df.iloc[:,2].plot.box(vert=True, patch_artist=True)
plt.title('Boxplot of Iris Petal Lengths (DataFrame)')
plt.ylabel('Petal Length (cm)')
plt.show()

#散布図
plt.scatter(df.iloc[:,2], df.iloc[:,3], c=Iris.target,
            cmap='viridis', edgecolor='k', s=100)
plt.title('Scatter Plot of Iris Petal Length vs Width (DataFrame)')
plt.xlabel('Petal Length (cm)')
plt.ylabel('Petal Width (cm)')
plt.show()

出力例

基本統計量        sepal length (cm)  sepal width (cm)  petal length (cm)  petal width (cm)
count         150.000000        150.000000         150.000000        150.000000
mean            5.843333          3.057333           3.758000          1.199333
std             0.828066          0.435866           1.765298          0.762238
min             4.300000          2.000000           1.000000          0.100000
25%             5.100000          2.800000           1.600000          0.300000
50%             5.800000          3.000000           4.350000          1.300000
75%             6.400000          3.300000           5.100000          1.800000
max             7.900000          4.400000           6.900000          2.500000
相関行列                    sepal length (cm)  sepal width (cm)  petal length (cm)  petal width (cm)
sepal length (cm)           1.000000         -0.117570           0.871754          0.817941
sepal width (cm)           -0.117570          1.000000          -0.428440         -0.366126
petal length (cm)           0.871754         -0.428440           1.000000          0.962865
petal width (cm)            0.817941         -0.366126           0.962865          1.000000
データ 0      1.4
1      1.4
2      1.3
3      1.5
4      1.4
      ...
145    5.2
146    5.0
147    5.2
148    5.4
149    5.1
Name: petal length (cm), Length: 150, dtype: float64
ソート後データ 22     1.0
13     1.1
14     1.2
35     1.2
16     1.3
      ...
131    6.4
105    6.6
117    6.7
122    6.7
118    6.9
Name: petal length (cm), Length: 150, dtype: float64
中央値 4.35
平均値 3.7580000000000005
最大値 6.9
最小値 1.0
分散 3.116277852348993
標準偏差 1.7652982332594662
四分位範囲 3.4999999999999996
相関係数 0.9628654314027963
共分散 1.2956093959731545
標本偏差 1.7652982332594662

教師あり学習

k近傍法(例:アヤメの種類当て)

from sklearn.datasets import load_iris
iris = load_iris()

from sklearn.model_selection import train_test_split

#30%をテストデータにする(残りは訓練)
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.3, random_state=0) 

#KVNモデル作成
from sklearn.neighbors import KNeighborsClassifier
#一つだけ近傍をとってK-NM
model = KNeighborsClassifier(n_neighbors=1)

#学習
model.fit(X_train, y_train)

#予測
y_pred = model.predict(X_test)

#正解と精度の確認
print("予測結果:", y_pred)
print("正解    :", y_test)
import numpy as np

#一致していれば1, そうでなければ0での平均
print(np.mean(y_pred == y_test)) 

線形回帰

データの関係性を直線で表現する

参照:

ここではYが目的変数の予測値、βが回帰係数、xが説明変数、pが説明変数の次元数 (種類数)
$$ Y = \beta_0 + \beta_1 x_1 + \beta_2 x_2 + \cdots + \beta_p x_p \quad$$

まずまず

複雑さでいうと、

Lasso < Ridge < 二乗平均誤差

モデルが複雑なほど、$Variance$(出力のばらつき)が大きくなり、そうでないほど$Bias^2$(モデルのそもそもの値のズレ)が大きくなるので、ここをちょうど合わせる必要がある

最小二乗法

$n$個のデータがあるとき、目的変数の実測値$y$と、上式で算出される予測値$Y$との誤差の二乗和が最小となるような回帰係数$β$を求める

$$ \sum_{i=1}^{n} \left( y_i - \beta_0 - \sum_{j=1}^{p} \beta_j x_{ij} \right)^2 \quad \cdots (1) $$

下のやつを最小化する

Lasso

・予測するにあたって重要ではない説明変数の係数を 0 にして実質的に削除する
・正則化パラメータ$λ$を大きくするほど選択する変数を少なくする傾向になる
$$
\sum_{i=1}^{n}(y_i-\beta_0-\sum_{j=1}^{p}\beta_j x_{ij})^2+\lambda\sum_{j=1}^{p}|\beta_j|
$$

Ridge

$$
\sum_{i=1}^{n}(y_i-\beta_0-\sum_{j=1}^{p}\beta_j x_{ij})^2
+\lambda\sum_{j=1}^{p}\beta_j^2
$$


import sklearn.datasets as datasets
import matplotlib.pyplot as plt

#データセットの生成と可視化
X,y = datasets.make_regression (n_samples=50, n_features=1, noise=20, random_state=1)

#線形回帰モデルの学習と予測
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression

#データの分割
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=2)
#モデルの学習
model = LinearRegression()
#予測
model.fit(X_train, y_train)
#テストデータに対する予測
y_pred = model.predict(X_test)

#結果の可視化
import numpy as np
lx = np.linspace(-2, 2)
ly = model.coef_ * lx + model.intercept_
plt.plot(lx, ly, 'r-') #回帰直線を赤い線でプロット
plt.plot(X_train, y_train, 'o') #訓練データを小さい円でプロット
plt.plot(X_test, y_test, 'x', markersize=10) #テストデータをバツ印でプロット
plt.plot(X_test, y_pred, '*', markersize=10) #予測データを星印でプロット
plt.show()


#Ridge回帰モデルの学習と評価
from sklearn.linear_model import Ridge
model = Ridge(alpha =1.0)
model.fit(X_train, y_train)
print(model)
print(model.score(X_train, y_train))
print(model.score(X_test, y_test))

#Lasso回帰モデルの学習と評価
from sklearn.linear_model import Lasso
lr = Lasso(alpha=1.0)
lr.fit(X_train, y_train)
print(lr)
print(lr.score(X_train, y_train))
print(lr.score(X_test, y_test))

出力例

Ridge()
0.9698162723325009
0.9320310873180947
Lasso()
0.9703304366304393
0.9330286290026062

交差検証(CV: Cross Validation)

n交差検証

独立に$n$回テストデータ、訓練データに分割して学習させ精度を評価する
具体的には、
・データを$N$個に分割
・以下を$N$回繰り返す

・これまでテストデータにならなかったやつから1つを選択してテストデータにする
・残りを訓練データにする
・予測精度評価

・$N$個のテストデータに対する予測精度の平均値が向上するようにハイパーパラメータをいじる
・最終評価を$N$個のテストデータに対する予測精度の平均値で行う

# 必要なライブラリの import
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression

# データのロード
iris = load_iris()
logreg = LogisticRegression()

from sklearn.model_selection import cross_val_score

#交差検証の実行
#model: 評価対象のモデル
#iris.data, iris.target: データセット
#cv=10は10分割交差検証を意味する
#scoring='accuracy'は評価指標として正解率を使用することを意味する
scores = cross_val_score(logreg, iris.data, iris.target, cv=10, scoring='accuracy')

# 各分割におけるスコア
print('Cross-Validation scores: {}'.format(scores))

# スコアの平均値
import numpy as np
print('Average score: {}'.format(np.mean(scores)))

出力例

Cross-Validation scores: [1 0.93333333 1 1 0.93333333 0.93333333 0.93333333 1 1 1]
Average score: 0.9733333333333334

分割方法

K-Fold⇒ラベルにかかわらず分割
出力値のラベルが偏る可能性が高い⇒分類向け
もとのデータランダムシャッフルするとよき

StratifiedK-Fold⇒かなりランダムに分割してくれる⇒回帰向け

訓練データ・検証・テストデータに分ける

CVだとバカ時間かかる可能性があるのでこっちでもいい
検証でパラメータチューニングをする!

決定木

不純度

ラベルの数を$j$, あるノード$m$におけるラベル$j$であるデータ数の割合を$p_{m , j}$とする

・ジニ不純度
$$H_m = 1 - \sum_{j=1}^j ({p_{mj}}) ^ 2$$

↑同じような確率で出てくるものが多いほど、う純度が高い!(偏ってると低い)

・エントロピー
$$H_m = - \sum_{j=1}^j {p_{mj}} log ({p_{mj}})$$

決定木の実装

# 必要なライブラリの import
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split


# データのロード
iris = load_iris()
X = iris.data
y = iris.target
X_train, X_test,y_train, y_test = train_test_split(X, y, random_state=27)

# 決定木の実装
from sklearn.tree import DecisionTreeClassifier
model = DecisionTreeClassifier(random_state=27)
#不純度基準はデフォルトの'gini'か'entropy'に変更可能
model.fit(X_train, y_train)
# モデルの評価
print(model.score(X_train, y_train))
print(model.score(X_test, y_test))

#決定木をグラフ化

#訓練はいけるけど、テストデータでの精度が良くない

枝刈り

事前枝刈りと、事後枝刈りが存在する
枝刈りで決定木が複雑にならないように

#depth3の枝刈り
model = DecisionTreeClassifier(max_depth=3, random_state=27)

決定木の利点

・関係ない特徴量入っててもいい
・事前処理の手間が少ない
・比較的高速
・欠損値耐性がある
・チューニングが容易
・理解しやすい

決定木の欠点

・回帰で精度が上がりにくい
・データが細分化されてまう
・訓練データのわずかな変化に影響しやすい
・上層の分岐で不具合があると、下層が死ぬ可能性が高い

⇒アンサンブル学習を使おう!!

アンサンブル学習

複数の学習器を用いる

・統計的に独立的であればいい

ex)バギングで、3つに分割してやる

サポートベクタマシン

⇒最も近い訓練データ(サポートベクタ)との距離を最大にするように出力する

ラグランジュの未定乗数法を用いてやる

単純パーセプトロン

関数にぶち込んで、YesかNoかを判定する2分類問題

ソフトマージン

外れ値を許容して考える、
反対側に入り込んだやつのキョリを記録しておいて、反対に入ることを許す

$$\underset{{\bf \omega},;\gamma}{min};\frac{1}{2}||{\bf \omega}||^2+C\sum\xi^i\hspace{1cm} (Cはハイパーパラメータ)$$

マージンを最大化、誤差を最小化することを目指す
Cが大きいほど、ハードマージンに近づく(外れを許容しない)

# 必要なライブラリの import
import matplotlib.pyplot as plt
from sklearn import datasets

# データの生成&可視化
X, y = datasets.make_blobs(n_samples=100, centers=2, random_state=1)

#SVC
import numpy as np
from sklearn.svm import LinearSVC
model = LinearSVC(C = 1.0).fit(X, y)

#出力
coefs = model.coef_
intercept = model.intercept_
plt.scatter(X[y == 0, 0], X[y == 0, 1], c='red')
plt.scatter(X[y == 1, 0], X[y == 1, 1], c='blue')
line_x = np.linspace(-13,1)
line_y = -(coefs[0][0] * line_x + intercept) / coefs[0][1]
plt.plot(line_x, line_y, color='black')
plt.show()

線形分離が不可能なやつは、データ側を捻じ曲げればいいじゃない、という考え方をしてるのがSVC(カーネルトリック。高次元にデータを持っていく)

# 必要なライブラリの import
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn import svm
from mlxtend.plotting import plot_decision_regions

# データの生成&可視化
X, y = datasets.make_blobs(centers=3, random_state=1)

#SVC
model = svm.SVC(kernel = 'rbf', C = 1.0, gamma = 1.0).fit(X, y)

plot_decision_regions(X, y, clf=model)
plt.show()

# 教師なし学習

k均法

アルゴリズム

・適当に点(mean)をk個取る
・最も近い点(mean)に基づいて各データ点を分割
・k個のクラスタの重心から新たなmeanをつくる

これをクラスタが変わらなくなるまでくりかえる

k-means++

sklearnではこっちの工夫された方でできてる

# 必要なライブラリの import
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn import svm
from mlxtend.plotting import plot_decision_regions

# データの生成&可視化
X, y = datasets.make_blobs(centers=20, random_state=5)

#k-means
from sklearn.cluster import KMeans
model = KMeans(n_clusters=3) #3点取る
model.fit(X)

#出力
print(model.labels_)
plt.scatter(X[model.labels_ == 0, 0], X[model.labels_ == 0, 1], color='red' )
plt.scatter(X[model.labels_ == 1, 0], X[model.labels_ == 1, 1], color='blue' )
plt.scatter(X[model.labels_ == 2, 0], X[model.labels_ == 2, 1], color='green' )
plt.show()

うまくいかない例(渦巻き)

# 必要なライブラリの import
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn import svm
from mlxtend.plotting import plot_decision_regions

# データの生成&可視化
X, y = datasets.make_moons(n_samples=300, noise = .05)

#k-means
from sklearn.cluster import KMeans
model = KMeans(n_clusters=3) #3点取る
model.fit(X)

#出力
print(model.labels_)
plt.scatter(X[model.labels_ == 0, 0], X[model.labels_ == 0, 1], color='red' )
plt.scatter(X[model.labels_ == 1, 0], X[model.labels_ == 1, 1], color='blue' )
plt.scatter(X[model.labels_ == 2, 0], X[model.labels_ == 2, 1], color='green' )
plt.show()

DBSCAN

上のやつをなくすアルゴリズム
・近いものを繋げていく感覚
半径$ ε $内に含まれる円を仲間にみなすので、これの調整大事

外れ値検出は簡単だが、毎回結果が変わる欠点がある

# 必要なライブラリの import
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn import svm
from mlxtend.plotting import plot_decision_regions

# データの生成&可視化
X, y = datasets.make_moons(n_samples=300, noise = .05)

#DBSCAN
from sklearn.cluster import DBSCAN
model = DBSCAN(eps=0.3)
model.fit(X)

#出力
print(model.labels_)
plt.scatter(X[model.labels_ == 0, 0], X[model.labels_ == 0, 1], color='red' )
plt.scatter(X[model.labels_ == 1, 0], X[model.labels_ == 1, 1], color='blue' )
plt.show()

アソシエーション分析

「AならBのような相関ルールを見つける」手法

・全データの中でAならBを満たしている割合「支持度」

・条件部の一致に対し、結論部も一致している割合「信頼度」

条件部を気にしないときBとなる確率が、条件Aになることによってどれだけ増加するかの割合「リフト値」つまり、$p(B|A) / p(B)$

Aprioriアルゴリズム

BFSでしばく

# 必要なライブラリの import
import pandas as pd
from mlxtend.preprocessing import TransactionEncoder
dataset = [
    ['りんご', 'バナナ', '牛乳'],  
    ['バナナ', 'おむつ', 'ビール', '牛乳'],
    ['りんご', 'おむつ', 'ビール', 'コーラ'],
    ['りんご', 'バナナ', 'おむつ', 'ビール'],
    ['バナナ', 'コーラ']
]
te = TransactionEncoder()
#fit: ユニークラベルを学習 & transform: トランザクションデータを one-hot エンコード
te_ary = te.fit(dataset).transform(dataset)
cf = pd.DataFrame(te_ary, columns=te.columns_)
print(cf)

from mlxtend.frequent_patterns import apriori
# 最小サポート0.6で頻出アイテムセットを抽出
frequent_itemsets = apriori(cf, min_support=0.6, use_colnames
=True)
print(frequent_itemsets)

from mlxtend.frequent_patterns import association_rules
# 信頼度0.7でアソシエーションルールを抽出
rules = association_rules(frequent_itemsets, metric="confidence", min_threshold=0.7)
print(rules)
     おむつ    りんご    コーラ    バナナ    ビール     牛乳
0  False   True  False   True  False   True
1   True  False  False   True   True   True
2   True   True   True  False   True  False
3   True   True  False   True   True  False
4  False  False   True   True  False  False
   support    itemsets
0      0.6       (おむつ)
1      0.6       (りんご)
2      0.8       (バナナ)
3      0.6       (ビール)
4      0.6  (ビール, おむつ)
  antecedents consequents  ...  certainty  kulczynski
0       (ビール)       (おむつ)  ...        1.0         1.0
1       (おむつ)       (ビール)  ...        1.0         1.0

当たり前のルールを閾値で除いていく

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?