コンテンツにスキップ

8 そのほかのアルゴリズム

8.1 ロジスティック回帰

ロジスティック回帰は回帰式を分類に応用したものです。回帰と付いていますが、分類に使用するものです。各結果について予測する回帰式を組み立て確率を出して分類を行います。

あやめの分析で行ってみます。other.ipynbに記述します。

import pandas as pd
from sklearn.model_selection import train_test_split

df =  pd.read_csv("iris.csv")
x = df[["SepalLength", "SepalWidth", "PetalLength", "PetalWidth"]]
y = df["Name"]

x_train, x_test, y_train, y_test = train_test_split(x, y, test_size = 0.2, random_state=0)

# ロジスティック回帰
from sklearn.linear_model import LogisticRegression
model = LogisticRegression(max_iter=1000)

model.fit(x_train, y_train)
model.score(x_test,y_test)

予測はpredictで可能です。

model.predict([[5.5, 3.8, 1.9, 1.2]])

ロジスティック回帰は各種類になる確率で答えを出すので、各種類別の確率を表示することが出来ます。データフレームに入れて分かりやすく出してみます。

result = model.predict_proba([[5.5, 3.8, 1.9, 1.2]])
pd.DataFrame(result, columns=model.classes_)

ロジスティック回帰では、通常の回帰分析と同じく、係数と切片が表示できます。係数の表示は通常の回帰分析と同じです。

model.coef_

あやめの場合、3種類ありますので種類毎に係数が表示されます。各種類にどのような特徴があるかが分かります。分かりやすくするためデータフレームで表示してみます。

pd.DataFrame(model.coef_, columns=x_train.columns, index=model.classes_)

なお、回帰式であるため、特徴量に差がある場合、標準化が必要です。

# パイプラインの構築
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.pipeline import make_pipeline

pipeline = make_pipeline(StandardScaler(), LogisticRegression(max_iter=1000))

# 学習
pipeline.fit(x_train, y_train)

係数を表示します。

model = pipeline.named_steps["logisticregression"]
pd.DataFrame(model.coef_, columns=x_train.columns, index=model.classes_)

8.2 ニューラルネットワーク

ニューラルネットワークとは人間の脳の神経細胞であるニューロンの動作を元にプログラムを構築したものです。

ニューロンは複数の電気信号が入ってきて、その大きさを判断して1つの電気信号を出力します。それを模したプログラムがパーセプトロンです。

パーセプトロンはデータを入力するときにある数を掛けます。これを重み付けといいます。それらを合計し、ある一定値(バイアス)以上なら1を出力し、そうでないなら0を出力します。

例えば、and出力をパーセプトロンで表してみます。 引数 x1とx2には1または0が入ってくるものとします。これに重み付け係数(w1とw2)を掛けて、バイアス(0.5)以上なら1、そうじゃないなら0を返します。

mlp.ipynb に以下を記述してみましょう。

# ANDの例
def percep(x1, x2):
    w1  = 0.3 # 重み1
    w2  = 0.3 # 重み2
    b   = 0.5 # バイアス

    a   =  x1 * w1 + x2 * w2

    if  a  >=  b:
        y = 1
    else:
        y = 0

    return y # 出力
print(percep(0, 0))
print(percep(0, 1))
print(percep(1, 0))
print(percep(1, 1))

この関数は重み付け係数とバイアスを変えるだけでORにすることもできます。重み付け係数を0.5、バイアスを0.3にするだけです。NANDにするには、重み付け係数を-0.5、バイアスを-0.7にします。

このように、重み付け係数とバイアスを変更することで、さまざまな処理を行えるようにします。

8.3 ディープラーニング

ニューラルネットワークはこのパーセプトロンをいくつもつなげ最終的な出力値を得ます。

例えば、あやめの分類を行うとします。4つの数値が入力です(SepalLength、SepalWidth、PetalLength、PetalWidth)。これを入力として最終的に3つの出力(3種類のどれか)を得ます。この3つの出力がそれぞれその答えになる確率が入ります。

当初は入力層と出力層しかありませんでしたが、現在はその中間に隠れ層を配置するディープラーニングが主流となっています。

手書き文字の認識をニューラルネットワークで行ってみます。 まずデータを用意し、訓練データとテストデータに分割します。

from sklearn import datasets

digits = datasets.load_digits()
x = digits.images
y = digits.target
x = x.reshape(-1, 64)
from sklearn.model_selection import train_test_split

x_train, x_test, y_train, y_test = train_test_split(x, y,  test_size=0.2, random_state=0)

scikit-learnのMLPClassifierで学習します。このとき、3層の隠れ層を配置しました。入力層は64個のデータです。これを100個のパーセプトロンで処理し、さらに50個、50個で処理し、最終的に出力層の10個にします。10個の中で最も確率が高いものが予測値となります。

from sklearn.neural_network import MLPClassifier

model = MLPClassifier(
    hidden_layer_sizes=(100,50,50),  # 隠れ層
    max_iter=100,               # 最大反復回数
    random_state=0
)
model.fit(x_train, y_train)

最大反復回数で指定した回数の学習を行います。 その後、評価を行います。

model.score(x_test,y_test)

学習過程を可視化してみます。当初の損失が大きい(予想の失敗が多い)状態から学習を重ねて損失が少なくなっていきます。これ以上減らない状態になっていれば学習は完了しています。逆に損失が大きくなっていく場合、過学習が起こっています。

import matplotlib.pyplot as plt
import seaborn as sns
sns.set_theme(font=["Meiryo"])

plt.plot(model.loss_curve_)
plt.title('学習過程での損失関数の推移')
plt.xlabel('反復回数')
plt.ylabel('損失')
plt.show()

ニューラルネットワークは画像の認識に高い効果を発揮します。