ギークなエンジニアを目指す男

基幹系SIerがWeb系とかネイティブ系の知識を蓄えようとするブログ

MENU

Kaggler-ja in-classコンペ途中経過 〜Fashion MNISTをkerasで〜

現在、7月9日より開催されているkaggler-jaというslackグループのin-classコンペに参加しています。
今日はその途中経過を報告したいと思います。
また、このモデルを構築するまでに試行錯誤したことなど、最後にまとめてありますので良ければご参考になさってください。

  • コンペの内容
  • ソースコード
  • 予測
  • 精度結果
  • この結果に到るまでに試行錯誤したこと
    • 参考にしたnotebook
    • オプティマイザの検証
    • レイヤーの検証
    • 画像の水増し処理
  • まとめ

コンペの内容

詳細は下記URLを参照していただければ分かると思いますが、簡単に言うとFashion MNISTのデータで学習モデルを作成し、その精度を競うコンペです。

Kaggler-ja In-class Competition 1

ソースコード

始めに、自分の提出したモデル構築のソースを載せておきます。

# ライブラリのimport
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import seaborn as sns
import itertools

from sklearn.model_selection import train_test_split
from sklearn.metrics import confusion_matrix
from keras import initializers
from keras.utils.np_utils import to_categorical # convert to one-hot-encoding
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten, Conv2D, MaxPool2D, Activation, MaxPooling2D
from keras.optimizers import RMSprop, Adadelta
from keras.preprocessing.image import ImageDataGenerator
from keras.callbacks import ReduceLROnPlateau, EarlyStopping

# データの読み込み
train = pd.read_csv('train.csv')

# 正解ラベルと入力データに分割
Y_train = train['label']
X_train = train.drop(labels=['label'], axis=1)

# 正規化
X_train = X_train / 255.0

# スケールの変換
X_train = X_train.values.reshape(-1, 28, 28, 1)

# 正解ラベルをone-hot-vectorに変換
Y_train = to_categorical(Y_train, num_classes=10)

# 入力データを、訓練データとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(X_train, Y_train, test_size = 0.1, random_state=2)

# コールバック関数の設定
# このコールバックは評価値を監視し,'patience'で指定されたエポック数の間改善が見られなかった場合,学習率を減らします.
learning_rate_reduction = ReduceLROnPlateau(monitor='val_acc', 
                                            patience=3, 
                                            verbose=1, 
                                            factor=0.5, 
                                            min_lr=0.00001)
# 過学習の抑制
# patientce = 20とし、val_lossの最小値が20回更新されなければ計算ストップ
early_stopping = EarlyStopping(monitor='val_loss', patience=20 , verbose=1)

# 画像の水増し処理
datagen = ImageDataGenerator(
        featurewise_center=False,  # set input mean to 0 over the dataset
        samplewise_center=False,  # set each sample mean to 0
        featurewise_std_normalization=False,  # divide inputs by std of the dataset
        samplewise_std_normalization=False,  # divide each input by its std
        zca_whitening=False,  # apply ZCA whitening
        rotation_range=5,  # randomly rotate images in the range (degrees, 0 to 180)
        horizontal_flip=False,  # randomly flip images
        vertical_flip=False)  # randomly flip images

#  水増し画像を訓練用画像の形式に合わせる
datagen.fit(X_train)

# CNNのモデル定義
model = Sequential()

model.add(Conv2D(filters = 32, kernel_size = (3,3),padding = 'Same', 
                 activation ='relu', input_shape = (28,28,1)))
model.add(Conv2D(filters = 32, kernel_size = (3,3),padding = 'Same', 
                 activation ='relu'))
model.add(MaxPool2D(pool_size=(2,2)))
model.add(Dropout(0.25))

model.add(Conv2D(filters = 64, kernel_size = (3,3),padding = 'Same', 
                 activation ='relu'))
model.add(Conv2D(filters = 64, kernel_size = (3,3),padding = 'Same', 
                 activation ='relu'))
model.add(MaxPool2D(pool_size=(2,2), strides=(2,2)))
model.add(Dropout(0.5))

model.add(Flatten())
model.add(Dense(256, activation = "relu"))
model.add(Dropout(0.5))
model.add(Dense(10, activation = "softmax"))

# オプティマイザ
optimizer =  Adadelta(lr=1.0, rho=0.95, epsilon=None, decay=0.0)

# コンパイル
model.compile(optimizer = optimizer , loss = "categorical_crossentropy", metrics=["accuracy"])

# エポック数とバッチサイズ設定
epochs = 100
batch_size = 100

# 学習
history = model.fit_generator(datagen.flow(X_train,y_train, batch_size=batch_size),
                              epochs = epochs, validation_data = (X_test,y_test),
                              verbose = 1, steps_per_epoch=X_train.shape[0] // batch_size
                              , callbacks=[learning_rate_reduction, early_stopping])

# 評価
score = model.evaluate(X_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
# =>Test loss: 0.16710302633792162
# =>Test accuracy: 0.94

94%の精度なので、まずまずかなぁと思いました。

精度と損失関数の遷移グラフも表示してみます。

続きを読む

クラス分類のための線形モデル(ロジスティック回帰 / 線形サポートベクタマシン)

こんばんは。
今日はクラス分類に用いることができる線形モデルを紹介します。
(ロジスティック回帰がメインです)

  • それぞれの線形モデルの境界線を表示してみる
  • 正則化パラメータ:Cの変更
  • ロジスティック回帰とcancerデータセット
  • p.s. 第100回 甲子園大会始まりましたね!

それぞれの線形モデルの境界線を表示してみる

今回使用するデータはmglearnに含まれるforgeデータと、sklearnに含まれるcancerデータです。

まずは、forgeデータの可視化と、ロジスティック回帰と線形サポートベクタマシンによる分類を行ってみます。

# ライブラリのインポート
from sklearn.linear_model import LogisticRegression # ロジスティック回帰
from sklearn.svm import LinearSVC # SVM
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import mglearn
from IPython.display import display
%matplotlib inline

# データの読み込み
X, y = mglearn.datasets.make_forge()
X.shape, y.shape
# => ((26, 2), (26,))

fig, axes = plt.subplots(1, 2, figsize=(10, 3))

# SVC, ロジスティック回帰のモデルを定義し、それぞれプロット
for model, ax, in zip([LinearSVC(), LogisticRegression()], axes):
    clf = model.fit(X, y)
    mglearn.plots.plot_2d_separator(clf, X, fill=False, eps=0.5, ax=ax, alpha=0.7)
    mglearn.discrete_scatter(X[:,0], X[:,1], y, ax=ax)
    ax.set_title("{}".format(clf.__class__.__name__))
    ax.set_xlabel("Feature 0")
    ax.set_ylabel("Feature 1")
    
axes[0].legend()

f:id:taxa_program:20180806001354p:plain

上記のように境界線が引かれ、2クラス分類が実行されます。
平行に近い直線で分類されていることが分かりますね。

では、この直線をもう少しデータに寄せる形に変更したい場合について、
正則化を決定するパラメータCの値を変更して学習させてみましょう。

続きを読む

Google Colaboratory内で画像やCSVファイルにアクセスしてみた

今日は新宿のもくもく会に参加しております。

  • Kaggle-jaのInClassコンペ
  • CSV読み込みするぞー

Kaggle-jaのInClassコンペ

来週の月曜日から、Kaggle-jaでInClassコンペが開催されます。
(主催者の方、準備など本当にありがとうございます)

課題は画像認識のため、僕のCPU環境だと学習に時間がかかると考え、そうだGoogle Colaboratory使えば良いじゃん?
ということで、環境だけ構築して放ったらかしていたColabのファイル読み込み手順の備忘録です。

CSV読み込みするぞー

下記サイトを参考にしました。

途中で気づいたのですが、投稿者はキカガクの吉崎さんでした。
(Udemyでとてもお世話になっております)

qiita.com

続きを読む

線形回帰とリッジ回帰をPythonで比べてみた

本日は回帰で頻出の線形回帰とリッジ回帰についてです。

  • 線形回帰とは
  • リッジ回帰
    • L1正規化とか、L2正規化ってなんだよ
  • スコアを比較してみる
  • リッジ回帰のalpha値をいろいろ変更してみる
  • 線形回帰とリッジ回帰の係数の大きさをプロットしてみる

線形回帰とは

訓練データにおいて、予測と真の回帰ターゲットyとの平均二乗誤差が最小になるように、パラメータwとバイアスbを求めるアルゴリズムです。
単回帰分析や重回帰分析などが該当します。

import mglearn
from sklearn.linear_model import LinearRegression # 線形回帰
%matplotlib inline

X, y = mglearn.datasets.load_extended_boston()
X.shape
# -> (506, 104)

# モデルの定義
model = LinearRegression(fit_intercept=False)
# 学習
model.fit(X_train, y_train)

print('Training ser score: {:.2f}'.format(model.score(X_train, y_train)))
print('Test set score: {:.2f}'.format(model.score(X_test, y_test)))

# -> Training ser score: 0.95
# -> Test set score: 0.61

リッジ回帰

直線回帰に正則化項の概念を加えた回帰分析です。
最小二乗法の式に正則化項(L2ノルム)を加え、その最小を求めることでモデル関数を発見します。
係数の絶対値の大きさを可能な限り小さくするのがモチベーション(w ≒ 0)であり、線形回帰に比べ、稼業適合(オーバーフィッティング)の危険が少ないのが特徴と言えます。

from sklearn.linear_model import Ridge
model = Ridge()
model.fit(X_train, y_train)

print('Training ser score: {:.2f}'.format(model.score(X_train, y_train)))
print('Test set score: {:.2f}'.format(model.score(X_test, y_test)))
# -> Training ser score: 0.89
# -> Test set score: 0.75

L1正規化とか、L2正規化ってなんだよ

下記のようなものらしい

続きを読む

k-最近傍法でアイリスのクラス分類問題を解く(python)

こんばんは。
本日は、機械学習の定番とも言える、アイリスの花のクラス分類問題をk-最近傍法を用いて解いてみようと思います。

実際、アイリスの花を分類したいというモチベーションがビジネス上役に立つかと問われると微妙ですが、学習だと割り切っていきましょう。(お花屋さんの方、すみません)

  • k-最近傍法とは
  • アイリスの花データを眺めてみる
  • データを可視化してみる
  • 学習から予測
  • k-最近傍法の利点と欠点

k-最近傍法とは

k-最近傍法とは、新しいデータポイントに対して、予測する際に新しい点に最も近い点を訓練セットから探し、新しい点に最も近かった点のラベルを予測データとする手法です。
(k-nearest neighbor algorithm という名前から、k-NNとも呼ばれます)
この手法では、近傍数というものをハイパーパラメータとして与えることができます。
近傍数を複数にした場合は、該当する点のラベルから多数決で予測ラベルを決定することになります。
言葉だけでの説明ではイメージしづらいと思いますので、いくつか図を紹介します。

下図は、近傍数 = 1 として予測を行なった結果です。
左上の星は●クラス
真ん中の星は▲クラス
右下の星は●クラス
に分類されていることが分かりますね。
(星は予測したいデータ)

続きを読む

Pythonで任意の値までの素数をすべて列挙してみる

こんばんは。

本日はPythonの演習ということで、素数列挙プログラムを作成しました。

  • ソース
  • 解説

ソース

私が作成したソースです。
おそらくちゃんと動きます。

import math

# 素数判定関数
def isPrime(num):
    # 2未満の数字は素数ではない
    if num < 2: return False
    # 2は素数
    elif num == 2: return True
    # 偶数は素数ではない
    elif num % 2 == 0: return False

    # 3 ~ numまでループし、途中で割り切れる数があるか検索
    # 途中で割り切れる場合は素数ではない
    for i in range(3, math.floor(math.sqrt(num))+1, 2):
        if num % i == 0:
            return False

    # 素数
    return True

# 素数判定
def callIsPrime(input_num=1000):
    numbers = []
    # ループしながら素数を検索する
    for i in range(1, input_num):
        if isPrime(i):
            numbers.append(i)

    # 素数配列を返す
    return numbers

# 関数の呼び出し
print(callIsPrime(1000))

出力はこんな感じです。

続きを読む

データベーススペシャリストの合格発表がありました。

4月に受験したデータベーススペシャリストの合格発表がありました。

taxa-program.hatenablog.com

  • 合格発表
  • 受験勉強開始時点の自分の能力
  • 午前試験対策
  • 午後試験対策
  • 勉強してみて(実務に生かせそうか)

合格発表

情報処理技術者では、WEBページへアクセスし合否確認を行うのですが、アクセス過多でサーバが重いこと・・・(毎年合格発表直後はこうです)

やっと成績照会のページへ。 ここで受験番号と照会用のパスワードを入力して、照会ボタンを押せば合否がでてきます。 どうせボタン押してもレスポンス悪いやろなぁって思いながらおしたら、一瞬で結果が返ってきました。

f:id:taxa_program:20180626183220j:plain

よっしゃぁぁぁぁっぁっぁっぁぁ!!
とは言えずに心の中でガッツポーズ。(会社のデスクだったため)

合格率を見てみると、13.9%だったようです。
ちなみに前年は14.5%なので、若干下がっていますね。

一応合格したので、自分が試験までにやったことを午前試験、午後試験に分けて書いてみます。
今後受験する人の参考になれば良いのですが。

受験勉強開始時点の自分の能力

自分語りするときは某掲示板でもスペックを要求されるため、以下に記します。
(受験時のスペックです)

年齢:27
学歴:情報系工学部卒
職業:SIer5年目 ERPパッケージの開発、導入など
DB知識:SQL作成は頻繁に行う。データベース設計も。
保有資格:基本情報技術者/応用情報技術者/普通自動車免許/普通自動二輪車免許

午前試験対策

とにかく過去問を解きました。

続きを読む