http.server(旧SimpleHTTPServer)の使い方

http.serverとは

Pythonの標準ライブラリの一つで、簡単なHTTPサーバを立てることができます。
これを用いてサービスを提供するというよりは、検証用途で使うことが多いです。

Python2.xではSimpleHTTPServerでしたが、
Python3.xではhttp.serverに移行しました。

使い方

コマンドライン上で使うことが多いかと思います。

  1. 作業ディレクトリを作成し、移動します。
  2. 作業ディレクトリにソースファイルを配置します。(今回は簡単のため、以下のようなindex.htmlを配置します。)
    1
    2
    3
    4
    5
    6
    7
    <html>
    <head>
    </head>
    <body>
    <p>Hello, World!</p>
    </body>
    </html>
  3. 作業ディレクトリにて下記のコマンドを実行します。
    1
    python3 -m http.server 8000
    Python2.xの場合は、代わりに以下のコマンドを実行してください。
    1
    python -m SimpleHTTPServer 8000
    -mはライブラリをスクリプトと実行するためのオプションです。
    また、8000はポート番号を指定しています。
  4. ブラウザでアドレスにlocalhost:8000と入力します。
  5. Hello, Worldが表示されればOK!

あとは、ソースファイルで実行してみてください。

コマンドラインに以下のように、ログが表示されるのでデバッグがしやすく便利です。

1
2
3
4
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
127.0.0.1 - - [10/Mar/2020 20:49:26] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [10/Mar/2020 20:49:26] code 404, message File not found
127.0.0.1 - - [10/Mar/2020 20:49:26] "GET /favicon.ico HTTP/1.1" 404 -

OSError: [Errno 48] Address already in useの対処

1
python3 -m http.server 8000

と実行した際に

1
OSError: [Errno 48] Address already in use

のようなエラーが出る場合があります。

これは、すでに別のプロセスが利用中のポートを使おうとした際に発生するエラーです。

プロセスIDを調べる

下記のようにして、指定したポートを使用しているプロセスを調べることができます。

1
lsof -i:8000
1
2
3
4
[MYNAME@MBA-3 sandbox]$lsof -i:8000
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
Python 35873 MYNAME 4u IPv4 0xaf2bced821389259 0t0 TCP *:irdmi (LISTEN)
Python 35873 MYNAME 7u IPv4 0xaf2bced825313ed9 0t0 TCP localhost:irdmi->localhost:50829 (CLOSE_WAIT)

この場合、プロセスIDは35873となります。

プロセスを終了する

1
kill -9 35873

これで、プロセスを終了できたので、再度コマンドを実行してください。

1
python3 -m http.server 8000

今度は、うまくサーバが立ち上がるはずです。

より複雑なアプリケーションを作るために

実際のアプリケーションは、より複雑なフレームワークで実装するのが一般的です。

有名なフレームワークには、FlaskDjangoがあります。

それぞれ、簡単な記事があるのでよろしければご覧ください。

Flaskの使い方

Djangoの使い方

記事情報

  • 投稿日:2020年3月10日
  • 最終更新日:2020年3月12日

第8回「scikit-learnによる計算」(連載:scikit-learnで学ぶ機械学習)

はじめに

連載「scikit-learnで学ぶ機械学習」を始めますに書いた通り、scikit-learnを用いて機械学習について学んで行きたいと思います。

前回の記事「データセット読み込みユーティリティ」では、scikit-learnのデータローダーについて学びました。

本記事のテーマは、「scikit-learnによる計算」です!

といってもこのテーマ名ではよく分かりませんね。

具体的には、増分学習について学びます。

増分学習

partial_fitを使うことで、与えたデータに対して1エポックの学習ができます。

  • 学習データが次々と追加されていく
  • 学習データの量が多く、一度にメモリに展開できない
    といったシーンで役立ちます。
    こういった学習を増分学習と言います。

コードの全体像

先に、完成後のソースコードを貼り付けておきます。

1
2
3
4
5
6
from sklearn.linear_model import SGDClassifier
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
clf = SGDClassifier(loss='log')
for i in range(1000):
clf.partial_fit(X_train, y_train, classes=[0, 1])
print (clf.score(X_test, y_test))

データセットローダーのインポート

1
from sklearn.linear_model import SGDClassifier

SGD学習を行う線形モデルをロードします。

のちに誤差関数をlogに設定することで、
ロジスティック回帰をSGDで学習させることができます。

from sklearn.linear_model import LogisticRegressionのロジスティック回帰実装ではSGDでの学習ができません。)

データセットの分割

1
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

モデルのインスタンスを作成

1
clf = SGDClassifier(loss='log')

losslogに設定します。

他の誤差関数も使用可能で、hingeとした場合は線形SVMとなります。

学習

1
2
for i in range(1000):
clf.partial_fit(X_train, y_train, classes=[0, 1])

1000エポック学習させています。

partial_fitfitと違い、classesを引数に与える必要があります。(初回だけで十分ですが、コードを簡単にするため毎回与えています。)

評価

1
print (clf.score(X_test, y_test))

まとめ

scikit-learnの増分学習の使い方がご理解いただけたでしょうか。

これにて、連載「scikit-learnで学ぶ機械学習」は終了です。

お疲れ様でした。

csvデータの学習方法を知りたい方は

CSVファイルをpandasで読み込み、scikit-learnで学習させる

もどうぞ。

機械学習の入門〜NumPyによるロジスティック回帰の実装を勉強したい方は

連載「ゼロから始める機械学習」

データ分析と機械学習の関係については以下の記事でまとめています。

データ分析とは何か?機械学習との関係について

記事情報

  • 投稿日:2020年3月9日
  • 最終更新日:2020年3月31日

第7回「データセット読み込みユーティリティ」(連載:scikit-learnで学ぶ機械学習)

はじめに

連載「scikit-learnで学ぶ機械学習」を始めますに書いた通り、scikit-learnを用いて機械学習について学んで行きたいと思います。

前回の記事第6回「データセット変換」では、標準化について学びました。

本記事のテーマは、「データセット読み込みユーティリティ」です!

scikit-learnでは、標準で利用できるデータセットが準備されています。

これらのデータセットはサンプルコードなどでよく使われます。

実際これまでの記事でもirisbreast_cancerを利用させていただきました。

今回はそんな「データセット読み込みユーティリティ」の使い方を紹介していきます。

データの種類

scikit-learnでは、データは大きく以下の二つに分類されています。

  • Toy Datasets
  • Real World Datasets

前者の場合、ライブラリの中にデータセットが含まれているのでオフラインでも動作します。
後者の場合、初めて利用する際にはデータをweb経由でロードするため時間がかかります。

Toy Datasets

  • boston
  • iris
  • diabetes
  • digits
  • linnerud
  • wine
  • breast_cancer

    Real World Datasets

  • olivetti_faces
  • 20newsgroups
  • 20newsgroups_vectorized
  • lfw_people
  • lfw_pairs
  • covtype
  • rcv1
  • kddcup99
  • california_housing

コードを動かそう

今回はToy Datasetsdigitsを利用しようと思います。

digitsデータセットの概要
0~9までのグレースケールの数字の画像です。
画素数は8×8ピクセルで、1797枚の

コードの全体像

先に、完成後のソースコードを貼り付けておきます。

1
2
3
4
5
6
7
8
from sklearn.datasets import load_digits
import matplotlib.pyplot as plt
digits = load_digits()
for i,img in enumerate(digits.images[:10]):
plt.subplot(2, 5, i + 1)
plt.imshow(img)
plt.axis('off')
plt.show()

データセットローダーのインポート

1
from sklearn.datasets import load_digits

digitsのデータセットローダーをインポートします。

グラフ描画ライブラリのインポート

1
import matplotlib.pyplot as plt

データセットのロード

下記のようにするだけで必要なデータを全てdigitsに展開できます。

1
digits = load_digits()

データの確認

ここで、データの確認をしてみましょう。

1
2
>>> dir(digits)
['DESCR', 'data', 'images', 'target', 'target_names']

順に

  • DESCR・・・データセットの概要
  • data・・・特徴量
  • images・・・特徴量を二次元配列(8×8)に変形したもの
  • target・・・ラベル
  • target_names・・・ラベル名

となっています。

特徴量、ラベルの形状の確認

1
2
3
4
5
6
>>> print (digits.data.shape)
(1797, 64)
>>> print (digits.image.shape)
(1797, 8, 8)
>>> print (digits.target.shape)
(1797,)

画像の確認

1
2
3
4
5
for i,img in enumerate(digits.images[:10]):
plt.subplot(2, 5, i + 1)
plt.imshow(img)
plt.axis('off')
plt.show()

以下のように描画されれば成功です。

まとめ

scikit-learnのデータセットローダーの使い方がご理解いただけたでしょうか。

次回のテーマは第8回「scikit-learnによる計算」で、増分学習にいて扱います。お楽しみに!

記事情報

  • 投稿日:2020年3月8日
  • 最終更新日:2020年3月9日

ABC158D String Formation

問題

https://atcoder.jp/contests/abc158/tasks/abc158_d

方針

愚直に支持された通りにシミュレーションを行う。

ポイント

Pythonのlistは末尾への要素追加をappendO(1)のコストで行えますが、
先頭への要素追加insertO(n)のコストがかかってしまいます。

そこで、両端キューを使います。

Pythonの両端キューは標準ライブラリdequeとして実装されています。

両端キューは要素の追加が、先頭・末尾ともにO(1)のコストで行えます。

メモ

dequeにはreverseメソッドが存在するのですが、
これを利用した場合TLEとなってしまったので、
自前でdequeの方向を管理することにしました。

コード

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from collections import deque
d = deque()
s = input()
d.append(s)
rev = 0 # dequeの方向を記録。0なら通常、1なら逆向きを表す。
Q = int(input())
for q in range(Q):
op = input().split()
if op[0] == '1':
rev = (rev + 1) % 2
else:
if (int(op[1]) + rev) % 2 == 0: # dequeの向きを考慮してどちらに追加するか分岐
d.append(op[2])
else:
d.appendleft(op[2])
ans = ''.join(list(d))
if rev == 1: # dequeが逆向きなら最後に戻す
ans = ans[::-1]
print (ans)

記事情報

  • 投稿日:2020年3月7日
  • 最終更新日:2020年3月7日

第6回「データセット変換」(連載:scikit-learnで学ぶ機械学習)

はじめに

連載「scikit-learnで学ぶ機械学習」を始めますに書いた通り、scikit-learnを用いて機械学習について学んで行きたいと思います。

前回の記事第5回「可視化」では、ROC曲線について学びました。

本記事のテーマは、「データ変換」です!

機械学習モデルの学習を行う際は、

生のデータを用いるのではなく、適切な前処理を行うことによって精度が向上するケースがよくあります。

(そもそも、前処理をしないと学習が行えない場合もある。)

そこで、今回は「データセット変換」について学んでいきましょう。

標準化

標準化は代表的な前処理手法の一つです。

データの平均が0に、分散が1となるように変換する操作のことを標準化と言います。

標準化をすることで

  • 学習の安定
  • 速い収束

が期待できます。

デメリットはほとんどないといっていいでしょう。

統計量の計算をするときに、テストデータを使わないこと

よくやりがちなミスは、

標準化するために統計量(平均と分散)の計算をする際に、

テストデータを用いてしまうことです。

実際にはテストデータは未知のデータですので、統計量の計算時にが学習データのみを利用します。

つまり、下記のような手順となります。

  1. 学習データを用いて統計量を計算する
  2. 統計量を用いて学習データを変換する
  3. 統計量を用いてテストデータを変換する

コードを動かそう

第3回「モデル選択と評価」でも利用した、breast_cancerという乳がんのデータセットを利用します。

コードの全体像

先に、完成後のソースコードを貼り付けておきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn import preprocessing
breast_cancer = load_breast_cancer()
X = breast_cancer.data
y = breast_cancer.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
clf = LogisticRegression()
clf.fit(X_train, y_train)
print (clf.score(X_test, y_test))

scaler = preprocessing.StandardScaler().fit(X_train)
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)
clf = LogisticRegression()
clf.fit(X_train_scaled, y_train)
print (clf.score(X_test_scaled, y_test))

コードの大部分は第1回「教師あり学習」で解説しています。

初出のコードについて解説します。

preprocessingのインポート

1
from sklearn import preprocessing

標準化StandardScalerpreprocessinに実装されています。

X_trainの統計量を計算

1
scaler = preprocessing.StandardScaler().fit(X_train)

X_train, X_testの変換

1
2
X_train_scaled = scaler.transform(X_train)
X_test_scaled = scaler.transform(X_test)

先ほどX_trainfitしたscalerをどちらにも使うのがポイント。

結果

コード全体を実行すると二つのスコアが出力される

  • 標準化なし
  • 標準化あり
    の2パターンである。
    場合によるが、標準化した場合の方がスコアがよかったのではないでしょうか。
    このようにたった3行のコードで標準化を行うだけで、スコアが良くなります。

まとめ

今回は、scikit-learnでの標準化にチャレンジしました。

次回のテーマは「データセット読み込みユーティリティ」です。お楽しみに!

記事情報

  • 投稿日:2020年3月7日
  • 最終更新日:2020年3月22日

第5回「可視化」(連載:scikit-learnで学ぶ機械学習)

はじめに

連載「scikit-learnで学ぶ機械学習」を始めますに書いた通り、scikit-learnを用いて機械学習について学んで行きたいと思います。

前回の記事(第4回「検査」)では、Partial Dependence Plots(部分従属プロット)について学びました。

本記事のテーマは、「可視化」です!

機械学習モデルの評価を行う際は、数値を出すだけではなく可視化をすることで、モデルの性能について考察することができます。

ROC曲線

ROC曲線を理解するためには、True PositiveとFalse Positiveを理解する必要があります。

True PositiveとFalse Positive

二値分類を考えます。

陽性と予測し、実際に陽性であったものをTrue Positive

陽性と予測したが、実際には陰性であったものをFalse Positive

と言います。

少しややこしいですが、

一つ目の単語(TrueまたはFalse)が、実際に予測が当たったかどうか

二つ目の単語(PositiveまたはNegative)が、モデルの予測

を表します。

ROC曲線の意味

ある予測器があったとします。

予測器の感度はとても小さい、すなわち全てのサンプルを陰性と予測するとします。

この予測器の感度を徐々にあげていくと、いずれは全てのサンプルを陽性と予測するようになりますね。

その過程をプロットしたのがROC曲線です。

(画像は https://oku.edu.mie-u.ac.jp/~okumura/stat/ROC.html より引用)

このグラフは、

  • 横軸がFalse Positive Rate
  • 縦軸がTrue Positive Rate

を表しています。

最初(感度が低く全てを陰性と予測する)は点は左下に位置していて、感度をあげると右上に移動していきます。
最後(全てを陽性と予測する)は右上に到達します。

AUC

先ほど説明したように、点は必ず最初は左下、最後は右上に位置するわけですが、

その過程を考えてみると、良い予測器ほど

  • False Positive Rateは小さい
  • True Positive Rateは大きい

というようになるわけですから、グラフが左上を通ることになります。

このことからプロットの下部の面積でモデルの良さを測ることができます。

この面積をAUCと呼びます。

コードを動かそう

第3回「モデル選択と評価」でも利用した、breast_cancerという乳がんのデータセットを利用します。

コードの全体像

先に、完成後のソースコードを貼り付けておきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import matplotlib.pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
from sklearn.metrics import plot_roc_curve
breast_cancer = load_breast_cancer()
X = breast_cancer.data
y = breast_cancer.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.9, random_state=0)
lr = LogisticRegression()
lda = LinearDiscriminantAnalysis()
svc = SVC()
models = [lr, lda, svc]
ax = plt.gca()
for model in models:
model.fit(X_train, y_train)
plot_roc_curve(model, X_test, y_test, ax=ax)

順に解説をしていきます。

グラフ描画ライブラリのインポート

1
import matplotlib.pyplot as plt

乳がんデータセットのインポート

1
from sklearn.datasets import load_breast_cancer

train_test_splitのインポート

後ほど、学習データとテストデータの分割に用いるので、インポートします。

1
from sklearn.model_selection import train_test_split

モデルのインポート

この記事では、複数のモデルを比較するため3つのモデルをインポートします。

  • ロジスティック回帰
  • サポートベクターマシン
  • 線形判別分析
    1
    2
    3
    from sklearn.linear_model import LogisticRegression
    from sklearn.svm import SVC
    from sklearn.discriminant_analysis import LinearDiscriminantAnalysis

ROC曲線プロットのインポート

1
from sklearn.metrics import plot_roc_curve

データセットのロードと分割

1
2
3
4
breast_cancer = load_breast_cancer()
X = breast_cancer.data
y = breast_cancer.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.9, random_state=0)

タスクが簡単すぎるためモデルの差を分かりやすくするために、学習データの比率を10%としています。

モデルのインスタンスを作成

1
2
3
4
lr = LogisticRegression()
lda = LinearDiscriminantAnalysis()
svc = SVC()
models = [lr, lda, svc]

最後にリストに格納しています。

ROC曲線のプロット

1
2
3
4
ax = plt.gca()
for model in models:
model.fit(X_train, y_train)
plot_roc_curve(model, X_test, y_test, ax=ax)

モデルの学習をして、プロットを上書きしていきます。

(実行環境によって結果は変わるため、これはあくまで参考です。)

AUCが最も高い(線の下部の面積が最も広い)のがロジスティック回帰(青線;AUC=0.98)であることが分かります。

すなわち、この検証においてはロジスティック回帰が最も優れているという結果となります。

まとめ

今回は、scikit-learnでのROC曲線の可視化について学びました

次回のテーマは「データセット変換」です。お楽しみに!

記事情報

  • 投稿日:2020年3月6日
  • 最終更新日:2020年3月22日

第4回「検査」(連載:scikit-learnで学ぶ機械学習)

はじめに

連載「scikit-learnで学ぶ機械学習」を始めますに書いた通り、scikit-learnを用いて機械学習について学んで行きたいと思います。

本記事は、第4回「検査」です!

近年、機械学習では解釈性のニーズが高まっています。

機械学習において解釈性とは、

なぜモデルがその予測をしたかを説明できるかどうか

ということです。

この記事ではsklearnを使って、
どの特徴量が予測に影響しているかを可視化してみたいと思います。

Partial dependence plots

Partial Dependence Plots(部分従属プロット)は、
学習済みのモデルに対して、どの特徴量が予測に影響しているかをプロットします。

先に、このアルゴリズムでプロットした図をみてみましょう。

4つの図があると思います。
各図の横軸が説明変数(特徴量)、縦軸が目的変数(ラベル)に対応しています。

左上・左中央の図は水平なグラフとなっていますが、
右上・左下の図は傾いている箇所があることがわかります。

グラフが傾いている場合、それらの特徴量が予測に影響している
という意味を持ちます。

コードを動かそう

機械学習のコードを動かしてみよう(scikit-learn)でも利用した、フィッシャーのアヤメと呼ばれるデータを利用してみたいと思います。

コードの全体像

先に、完成後のソースコードを貼り付けておきます。

1
2
3
4
5
6
7
8
9
10
11
12
13
from sklearn.datasets import load_iris
from sklearn.linear_model import LogisticRegression
from sklearn.inspection import plot_partial_dependence
import matplotlib.pyplot as plt
iris = load_iris()
X = iris.data
y = iris.target
clf = LogisticRegression()
clf.fit(X, y)
features = range(0,4)
plot_partial_dependence(clf, X, features, target=0)
plot_partial_dependence(clf, X, features, target=1)
plot_partial_dependence(clf, X, features, target=2)

順に解説をしていきます。

アヤメデータセットのインポート

1
from sklearn.datasets import load_iris

ロジスティック回帰モデルのインポート

1
from sklearn.linear_model import LogisticRegression

部分従属プロットのインポート

1
from sklearn.inspection import plot_partial_dependence

グラフ描画ライブラリのインポート

1
import matplotlib.pyplot as plt

as pltとするのが通例です。

アヤメデータのロード

1
iris = load_iris()

先ほど説明したアヤメのデータを変数irisに代入する。

Xに特徴量(説明変数、入力ベクトル)を代入

1
X = iris.data
1
2
>>> X.shape
(150, 4)

データの数(サンプル数)が150で説明変数の種類(次元)が4であることが確認できます。

yにラベル(目的変数、出力ベクトル)を代入

1
y = iris.target

今回のtargetは0,1,2のいずれかの数字が保持されています。
つまり、3クラス分類問題です。

ロジスティック回帰モデルのインスタンスを作成

1
clf = LogisticRegression()

多クラス分類問題でも、2クラス分類問題と同様の書き方でインスタンスを作成します。

学習を行う

1
clf.fit(X, y)

今回は正解率の評価は行わないので、データを分割しません。

プロットの準備

1
features = range(0,4)

プロットに利用するリストを作成します。

4は特徴量の数です。

部分従属プロット

1
plot_partial_dependence(clf, X, features, target=0)

コードを実行すると上の図のようにグラフが表示されると思います。
(グラフの形は異なる場合があります)

target=0の意味ですが、これはラベル0のクラスの予測に対しての
各特徴量の影響を出力せよ、という意味です。他のクラスについてもみていきましょう。

部分従属プロット(続き)

1
2
plot_partial_dependence(clf, X, features, target=1) 
plot_partial_dependence(clf, X, features, target=2)

まとめ

今回は、scikit-learnでの検査(部分従属プロット)について学びました。

次回のテーマは「可視化」です。お楽しみに!
第5回「可視化」

記事情報

  • 投稿日:2020年3月4日
  • 最終更新日:2020年3月22日

第3回「モデル選択と評価」(連載:scikit-learnで学ぶ機械学習)

はじめに

連載「scikit-learnで学ぶ機械学習」を始めますに書いた通り、scikit-learnを用いて機械学習について学んで行きたいと思います。

本記事は、第3回「モデル選択と評価」です!

データを集めて学習しようと思った際に、

  • どのようにモデルや学習アルゴリズムを評価するか

を決める必要があります。また

  • 最適なハイパーパラメータは何か

知りたくなることもあるでしょう。そういった際に、scikit-learnのModel selection and evaluationを使うと良いです。

前々回の記事第1回「教師あり学習」や前回の記事第2回「教師なし学習」がまだの方は、そちらもどうぞ!

Model selection and evaluation

scikit-learnのModel selection and evaluationには以下のようなアルゴリズムが実装されています。

  • クロスバリデーション
  • グリッドサーチ
  • 評価指標

今回はクロスバリデーションについて、コードを動かしながら理解してみましょう。

クロスバリデーションとは

第1回「教師あり学習」の記事にもきたように、学習に用いたデータを使って、評価を行うことは通常良くないとされています。

そこで、第1回「教師あり学習」では、sklearn.model_selection.train_test_splitを使って、データの70%を学習データに、30%をテストデータに利用していました。

このような方法をホールドアウト法と言います。

ホールドアウト法のデメリット

ホールドアウト法では、当然学習データとしてしか使われないデータと、テストデータとしてしか使われないデータが出てきまいます。

また、テストデータの量が全体に対して小さいため、不安定(乱数の影響を受けやすい)な指標となる場合があります。これは特に元のデータが少ない場合に顕著です。

クロスバリデーションで解決

そこでローテーションをすることで、全てのデータが学習データとしてもテストデータとしても使われるようにするのがクロスバリデーションです。

例えば、5分割する場合は学習データが80%、テストデータが20%となり、全部で5セットの学習と評価が行われることになります。

これによって、先のホールドアウト法のデメリットが解消されるわけです。ホールドアウト法の拡張として、解釈しても良いでしょう。

逆にクロスバリデーションのデメリットは計算コストが増えてしまう点ですので、その点には留意しましょう。

使い分け

基本的には、以下のようにご理解いただければOKです。

  • データ量が多い時に適した手法・・・ホールドアウト法
  • データ量が少ない時に適した手法・・・クロスバリデーション

コードを動かそう

第1回「教師あり学習」で扱った、ロジスティック回帰モデルでのbreast_cancerの学習をクロスバリデーションで評価してみましょう。

コードの全体像

先に、完成後のソースコードを貼り付けておきます。

1
2
3
4
5
6
7
8
9
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import cross_val_score
from sklearn.linear_model import LogisticRegression
breast_cancer = load_breast_cancer()
X = breast_cancer.data
y = breast_cancer.target
clf = LogisticRegression()
scores = cross_val_score(clf, X, y, cv=5, scoring='accuracy')
print (scores)

順に解説をしていきます。

乳がんデータセットのインポート

今回もbreast_cancerという乳がんのデータセットを利用します。

1
from sklearn.datasets import load_breast_cancer

cross_val_scoreのインポート

後ほど、学習データとテストデータの分割に用いるので、インポートします。

1
from sklearn.model_selection import cross_val_score

ロジスティック回帰モデルのインポート

1
from sklearn.linear_model import LogisticRegression

乳がんデータセットのロード

1
breast_cancer = load_breast_cancer()

Xに特徴量(説明変数、入力ベクトル)を代入

1
X = breast_cancer.data

全部で569サンプル、特徴量の数は30です。

yにラベル(目的変数、出力ベクトル)を代入

1
y = breast_cancer.target

ロジスティック回帰モデルのインスタンスを作成

1
clf = LogisticRegression()

このあとクロスバリデーションを行うわけですが、インスタンスの作成は通常通りでOKです。

評価を行う

1
2
scores = cross_val_score(clf, X, y, cv=5, scoring='accuracy')
print (scores)

5分割のクロスバリデーションを行います。評価指標はこれまでと同じく、accuracyを用います。

5回分のスコアがリストとして返却されているのを確認しましょう。

続き

第4回「検査」

記事情報

  • 投稿日:2020年3月4日
  • 最終更新日:2020年3月7日

第2回「教師なし学習」(連載:scikit-learnで学ぶ機械学習)

はじめに

連載「scikit-learnで学ぶ機械学習」を始めますに書いた通り、scikit-learnを用いて機械学習について学んで行きたいと思います。

本記事は、第2回「教師なし学習」です!

  • 教師あり学習の概要
  • 混合ガウス分布のコード
    を解説していきたいと思います
    前回の記事第1回「教師あり学習」がまだの方は、そちらもどうぞ!

教師なし学習とは

データの構造

まず、教師なし学習で扱うデータの構造について説明します。

教師あり学習の場合(復習)

教師あり学習のデータは二つの要素を持っていると説明しました。
それは

  • 特徴量(説明変数、入力ベクトル)
  • ラベル(目的変数、出力ベクトル)
    でした

教師なし学習の場合

教師なし学習のデータは特徴量のみを持っています。

教師なし学習の目的

教師なし学習には

  • クラスタリング
  • 次元削減
    などの種類があります。

クラスタリングは、データの特徴を捉えて集合(クラスタと呼ばれる)に分割するため

次元削減は、データを可視化したり圧縮するため

に用いられます。

ちょっと、難しいと思われた方も大丈夫です。

コードを動かしながら理解してみましょう。

コードを動かそう

分類問題は教師あり学習のタスクとしてもよく取り上げられますが、
クラスタリングでも解くことができます。

混合ガウス分布モデルを用いたクラスタリングで、簡単な分類問題を解いてみましょう。

コードの全体像

先に、完成後のソースコードを貼り付けておきます。

1
2
3
4
5
6
7
8
from sklearn.datasets import load_breast_cancer
from sklearn.mixture import GaussianMixture
breast_cancer = load_breast_cancer()
X = breast_cancer.data
y = breast_cancer.target
gmm = GaussianMixture(n_components=2)
pred = gmm.fit_predict(X)
print ((pred == y).mean(), (pred != y).mean())

順に解説をしていきます。

乳がんデータセットのインポート

前回に続いて、今回もbreast_cancerという乳がんのデータセットを利用します。

breast_cancerには細胞核の情報とその診断結果(悪性腫瘍か良性腫瘍か)が記録されています。

1
from sklearn.datasets import load_breast_cancer
1
2
3
4
5

## 混合正規分布モデルのインポート
混合正規分布モデル(混合ガウス分布モデル)のインポートをします。
```python
from sklearn.mixture import GaussianMixture

混合正規分布モデルは、複数の正規分布の重ね合わせでデータの分布を捉えるモデルです。
今回でいうと、正規分布の一つの山がクラスタ(悪性腫瘍か良性腫瘍か)に相当します。

Xに特徴量(説明変数、入力ベクトル)を代入

1
X = breast_cancer.data

全部で569サンプル、特徴量の数は30です。

yにラベル(目的変数、出力ベクトル)を代入

1
y = breast_cancer.target

混合正規分布モデルのインスタンスを作成

1
gmm = GaussianMixture(n_components=2)

この時、n_componentsとして、クラスタ数を指定します。

breast_cancerは悪性腫瘍か良性腫瘍かの二択ですので2を指定します。

今回のように、設定すべきクラスタ数がわかっている場合は良いですが、

そうでない場合はクラスタの推定を行うこともあります。

モデルの学習と予測を行う

1
pred = gmm.fit_predict(X)

教師なし学習ですので、引数にXのみを与えているのがポイントです。

これだけで、データの分類が行えてしまいます。

評価を行う

予測と正解が一致しているかを全てのテストサンプルについて確認し、平均をとります。
ただし、01を逆転して割り当てている可能性があるので、二つの結果を表示します。

1
print ((pred == y).mean(), (pred != y).mean())

両者の最大値をとると、おおよそ95%程度の正解率となっているのではないでしょうか。

教師あり学習(ロジスティック回帰)では96%でした)

このように、クラスタリングという全くラベル情報を与えないアルゴリズムでも、

簡単な分類問題であれば解けてしまうのです。

続き

第3回「モデル選択と評価」

記事情報

  • 投稿日:2020年3月3日
  • 最終更新日:2020年3月7日

第1回「教師あり学習」(連載:scikit-learnで学ぶ機械学習)

はじめに

連載「scikit-learnで学ぶ機械学習」を始めます)に書いた通り、scikit-learnを用いて機械学習について学んで行きたいと思います。

本記事は、第1回「教師あり学習」です!

  • 教師あり学習の概要
  • ロジスティック回帰のコード
    を解説していきたいと思います

教師あり学習とは

データの構造

まず、教師あり学習で扱うデータの構造について説明します。

教師あり学習のデータは二つの要素を持っています。

それは

  • 特徴量(説明変数、入力ベクトル)
  • ラベル(目的変数、出力ベクトル)

です。

例えば、花の品種を予測する問題を考えてみます。
この時、

  • 花弁の長さや幅・・・特徴量
  • 品種・・・ラベル

となります。

教師あり学習の流れ

  1. 既知のデータ(特徴量とラベル)があったとします。これを学習データと呼びます。
  2. どのような教師あり学習のアルゴリズムを用いるか決めます。これをモデルと呼びます。
  3. 学習データを用いてモデルのパラメータを調整します。これを学習と呼びます。
  4. 未知のデータ(特徴量)とモデルを用いて未知のデータのラベルを計算します。これを予測と呼びます。

ちょっと、難しいと思われた方も大丈夫です。

コードを動かしながら理解してみましょう。

コードを動かそう

コードの全体像

先に、完成後のソースコードを貼り付けておきます。

1
2
3
4
5
6
7
8
9
10
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
breast_cancer = load_breast_cancer()
X = breast_cancer.data
y = breast_cancer.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)
clf = LogisticRegression()
clf.fit(X_train, y_train)
print (clf.score(X_test, y_test))

順に解説をしていきます。

乳がんデータセットのインポート

sklearn.datasetsには、様々なデータセットがあります。

今回はbreast_cancerという乳がんのデータセットを利用してみたいと思います。

細胞核の情報とその診断結果(悪性腫瘍か良性腫瘍か)がペアになっているデータセットです。

1
from sklearn.datasets import load_breast_cancer

train_test_splitのインポート

後ほど、学習データとテストデータの分割に用いるので、インポートします。

1
from sklearn.model_selection import train_test_split

ロジスティック回帰モデルのインポート

ロジスティック回帰と呼ばれる教師あり学習の中でもベーシックなモデルを使ってみたいと思います。

1
from sklearn.linear_model import LogisticRegression

なお、ややこしいのですがロジスティック回帰は「回帰」ではなく「分類」を行うためのモデルです。

乳がんデータセットのロード

1
breast_cancer = load_breast_cancer()

Xに特徴量(説明変数、入力ベクトル)を代入

1
X = breast_cancer.data

Xの形状を確認し、サンプル数と特徴量の数をみてみましょう。

1
2
>>> breast_cancer.data.shape
(569, 30)

全部で569サンプル、特徴量の数は30のようです。
次に、特徴量の名前をみてみましょう。

1
2
3
4
5
6
7
8
9
10
11
>>> breast_cancer.feature_names
array(['mean radius', 'mean texture', 'mean perimeter', 'mean area',
'mean smoothness', 'mean compactness', 'mean concavity',
'mean concave points', 'mean symmetry', 'mean fractal dimension',
'radius error', 'texture error', 'perimeter error', 'area error',
'smoothness error', 'compactness error', 'concavity error',
'concave points error', 'symmetry error',
'fractal dimension error', 'worst radius', 'worst texture',
'worst perimeter', 'worst area', 'worst smoothness',
'worst compactness', 'worst concavity', 'worst concave points',
'worst symmetry', 'worst fractal dimension'], dtype='<U23')

yにラベル(目的変数、出力ベクトル)を代入

1
y = breast_cancer.target

yの中身を確認してみましょう。

1
2
>>> y
(省略)

01でデータが表現されていることが確認できます。

余談:なぜXは大文字でyは小文字なの?

  • 特徴量の形状・・・(サンプル数,特徴量の数)
  • ラベルの形状・・・(サンプル数,)

となっていて、形状はそれぞれ行列ベクトルです。

そのため、scikit-learnなどのサンプルコードではその点を意識して使い分けています。

特に明確な決まりがあるわけではありませんので、スタイルの問題だと思っていただければ大丈夫です。

trainとtestに分割

1
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

sklearn.model_selection.train_test_splitを使ってデータを分割しましょう。
分割後のイメージは下の表のようになります。

以前、こちらの記事にも書いた内容です。要約すると、

学習に用いたデータを使って、評価を行うことは通常良くないとされています。

私たち人間が受けるテストと同じで、
「事前にテストの問題が公表されているテスト」は暗記してしまえば良いのであまり意味がないです。

「事前にテストの類題や過去問は公表するが、本番のテストの内容は公表しないテスト」
方が適切に評価ができるというわけです。

ロジスティック回帰モデルのインスタンスを作成

1
clf = LogisticRegression()

モデルの学習を行う

1
clf.fit(X_train, y_train)

テストデータで評価を行う

予測と正解が一致しているかを全てのテストサンプルについて確認し、平均をとります。

これが、scoreメソッドで一発でできます。

1
print (clf.score(X_test, y_test))

scoreメソッドを使わずに書き下すと、以下のようになります。

1
print ((clf.predict(X_test)==y_test).mean())

続き

第2回「教師なし学習」

記事情報

  • 投稿日:2020年3月2日
  • 最終更新日:2020年3月7日