09 May 2017, 08:59

Vgg16 モデルに Batch Normalization を組み込む技

はじめに

Vgg16 モデルによる転移学習で、kaggle で結構いい成績がでているので、 転移学習すごくない?と思っている今日この頃。

Vgg16 モデルを使って、kaggle の MNIST コンペ に挑戦したらどうなるだろうと思っていろいろ試してみた。 結論からいうと、無謀な挑戦で挫折したのだけれども、得たことをまとめて置く。

Vgg16 モデルには、Batch Normalization が使われていない

Batch Normalization は、overfitting を防ぎ、学習をスピードアップさせるよい方法なのだが、 Vgg16 モデルには、Batch Normalization が使われていない。

なぜか?それは、VGG16 モデルができたとき、Batch Normalization は存在しなかったから。

Fast AI での解決方法

fast.ai の講義では Lesson4,5 で、VGG に Batch Normalization を組み込む方法を紹介している。

以下の ipynb がそれ。

以下の処理で、Vgg16 モデルの最後の Convolution レイヤのインデックス値を調べて、 FC 層を取っ払う。ここでコールしている Vgg16 クラスは、独自関数(keras とは関係ない)ので注意。

vgg = Vgg16()
model=vgg.model
last_conv_idx = [i for i,l in enumerate(model.layers) if type(l) is Convolution2D][-1]
conv_layers = model.layers[:last_conv_idx+1]
conv_model = Sequential(conv_layers)

取っ払った層(30 層)のみで、学習をする。

conv_feat = conv_model.predict_generator(batches, batches.nb_sample)
conv_val_feat = conv_model.predict_generator(val_batches, val_batches.nb_sample)
conv_test_feat = conv_model.predict_generator(test_batches, test_batches.nb_sample)

以下のような、BatchNorm と Dropout を含む層を作成する。

def get_bn_layers(p):
    return [
        MaxPooling2D(input_shape=conv_layers[-1].output_shape[1:]),
        Flatten(),
        Dropout(p/2),
        Dense(128, activation='relu'),
        BatchNormalization(),
        Dropout(p/2),
        Dense(128, activation='relu'),
        BatchNormalization(),
        Dropout(p),
        Dense(10, activation='softmax')
        ]
p=0.8
bn_model = Sequential(get_bn_layers(p))
bn_model.compile(Adam(lr=0.001), loss='categorical_crossentropy', metrics=['accuracy'])

この層をつかって、前に学習した conv_feat から学習を再開する。

bn_model.fit(conv_feat, trn_labels, batch_size=batch_size, nb_epoch=1, 
             validation_data=(conv_val_feat, val_labels))

うーむ、うなるような職人技だ。

Keras では、オプション指定で可能

Keras では、VGG16 がデフォルトで使うことが出来る。以下の記事が詳しい。

VGG16 というクラスが用意されている。

このクラスをつかうときに、include_top オプションを False に指定することで、 ネットワークの出力層側にある 3 つの全結合層を含まないように指定できるのだ。

このオプションをつかうと以下のように組み込むことが出来る。

def pretrained_model(img_shape, num_classes):
    model_vgg16_conv = VGG16(weights='imagenet', include_top=False)
    #model_vgg16_conv.summary()

    #Create your own input format
    keras_input = Input(shape=img_shape, name = 'image_input')

    #Use the generated model 
    output_vgg16_conv = model_vgg16_conv(keras_input)

    #Add the fully-connected layers 
    x = Flatten(name='flatten')(output_vgg16_conv)
    x = Dropout(0.8)(x)
    x = Dense(256, activation=layer_type, name='fc1')(x)
    x = BatchNormalization()(x)
    x = Dropout(0.8)(x)
    x = Dense(256, activation=layer_type, name='fc2')(x)
    x = BatchNormalization()(x)
    x = Dropout(0.8)(x)
    x = Dense(num_classes, activation='softmax', name='predictions')(x)

    #Create your own model 
    pretrained_model = Model(inputs=keras_input, outputs=x)
    pretrained_model.compile(optimizer=Adam(lr=0.001), loss='categorical_crossentropy', metrics=['accuracy'])

    return pretrained_model

元にした情報元は以下のリンク

VGG16 モデルで画像の入力サイズを変更したい

VGG16 は デフォルトで 226x226 のサイズの画像を処理するように設計されているけれども、 上のソースを使うことで、input shape を変更できる。

よし、これで MNIST に挑戦するぞ!と思ったら、なんとサイズに制限があった!!

公式ドキュメントによると、48x48 以上でなければいけないのだ。

正確に 3 つの入力チャンネルをもつ必要があり,width と height は 48 以上にする必要があります

MNIST は 28x28 なので、使えない。痛恨!!

今回の記事でとちゅうまで書いた中途半端な ipynb は以下です。

05 May 2017, 10:00

LSTMで為替の予測をしてみた

RNN(LSTM)入門2日目。依然として、全然わかりません。

このあたりが自分のスキルの限界なのかもしれない。Udacity DLNDで株の値動きの予測をする動画が紹介された。

FXのシステムトレードを以前やっていたので、ディープラーニングで学んだことが生かせればいいなと思い、株を為替に置き換えて、LSTMで為替の値動きの予測をしてみた。

この記事は以下の記事をベースに書いている。

また、以下のkaggleコンペのkernelsも大いに参考にした。

準備

  <p>
    まずは、為替データを準備する。以下のサイトから、2017/4/24 の USD/JPY の 10分刻みのデータをダウンロードする。
  </p>

  <ul>
    <li>
      <a href="https://www.dukascopy.com/swiss/english/marketwatch/historical/">Historical Data Feed :: Dukascopy Bank SA | Swiss Forex Bank | ECN Broker | Managed accounts | Swiss FX trading platform</a>
    </li>
  </ul>

  <p>
    githubにも使用したデータをアップロードした。
  </p>

  <ul>
    <li>
      <a href="https://github.com/tsu-nera/futurismo/blob/main/blog/ipynb/USDJPY_Candlestick_10_m_BID_24.04.2017-25.04.2017.csv">futurismo/USDJPY_Candlestick_10_m_BID_24.04.2017-25.04.2017.csv</a>
    </li>
  </ul>

  <h3 id="環境">
    環境<a class="anchor-link" href="#環境">¶</a>
  </h3>

  <ul>
    <li>
      TensorFlow 1.1.0
    </li>
    <li>
      Keras 2.0.2
    </li>
  </ul>
</div>

LSTM Network for Regression

  <p>
    チュートリアルにしたがって順にコードを書いていく。
  </p>
</div>

In [1]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="kn">from</span> <span class="nn">__future__</span> <span class="k">import</span> <span class="n">print_function</span>

import numpy as np # linear algebra import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv) from keras.layers.core import Dense, Activation, Dropout from keras.layers.recurrent import LSTM from keras.models import Sequential from sklearn.preprocessing import MinMaxScaler from sklearn.metrics import mean_squared_error import matplotlib.pyplot as plt import math

    <div class="output_subarea output_stream output_stderr output_text">
      <pre>Using TensorFlow backend.

In [2]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="c1"># parameters to be set </span>

look_back = 1 epochs = 30 batch_size = 1

In [3]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="c1"># fix random seed for reproducibility</span>

np.random.seed(7)

PrePare Data

In [4]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="c1"># read all prices using panda</span>

dataframe = pd.read_csv(‘USDJPY_Candlestick_10_m_BID_24.04.2017-25.04.2017.csv’, header=) dataframe.head()

Out[4]:

    <div class="output_html rendered_html output_subarea output_execute_result">
      <div>
        <table class="dataframe" border="1">
          <tr style="text-align: right;">
            <th>
            </th>

            <th>
              Local time
            </th>

            <th>
              Open
            </th>

            <th>
              High
            </th>

            <th>
              Low
            </th>

            <th>
              Close
            </th>

            <th>
              Volume
            </th>
          </tr>

          <tr>
            <th>
            </th>

            <td>
              24.04.2017 00:00:00.000
            </td>

            <td>
              109.072
            </td>

            <td>
              109.072
            </td>

            <td>
              109.072
            </td>

            <td>
              109.072
            </td>

            <td>
              0.0
            </td>
          </tr>

          <tr>
            <th>
              1
            </th>

            <td>
              24.04.2017 00:10:00.000
            </td>

            <td>
              109.072
            </td>

            <td>
              109.072
            </td>

            <td>
              109.072
            </td>

            <td>
              109.072
            </td>

            <td>
              0.0
            </td>
          </tr>

          <tr>
            <th>
              2
            </th>

            <td>
              24.04.2017 00:20:00.000
            </td>

            <td>
              109.072
            </td>

            <td>
              109.072
            </td>

            <td>
              109.072
            </td>

            <td>
              109.072
            </td>

            <td>
              0.0
            </td>
          </tr>

          <tr>
            <th>
              3
            </th>

            <td>
              24.04.2017 00:30:00.000
            </td>

            <td>
              109.072
            </td>

            <td>
              109.072
            </td>

            <td>
              109.072
            </td>

            <td>
              109.072
            </td>

            <td>
              0.0
            </td>
          </tr>

          <tr>
            <th>
              4
            </th>

            <td>
              24.04.2017 00:40:00.000
            </td>

            <td>
              109.072
            </td>

            <td>
              109.072
            </td>

            <td>
              109.072
            </td>

            <td>
              109.072
            </td>

            <td>
              0.0
            </td>
          </tr>
        </table>
      </div>
    </div>
  </div>
</div>

In [5]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">dataset</span> <span class="o">=</span> <span class="n">dataframe</span><span class="p">[</span><span class="s1">'Close'</span><span class="p">]</span>

In [6]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="c1"># reshape to column vector</span>

#close_prices = close.values.reshape(len(close), 1) dataset = dataset.values dataset = dataset.astype(‘float32’) close_prices = dataset.reshape((-1,1))

ここで、データを0~1の間に正規化する。scikit-learnにMinMaxScalerという便利な関数があって、fit_transformとすると、正規化できる。戻すときは、inverse_transformをコールする。

In [7]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="c1"># normalize the dataset</span>

scaler = MinMaxScaler(feature_range=(, 1)) close_prices = scaler.fit_transform(close_prices)

訓練用データを 23, テスト用データを 1/3に分ける。

In [8]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="c1"># split data into training set and test set</span>

train_size = int(len(close_prices) * 0.67) test_size = len(close_prices) - train_size train, test = close_prices[:train_size,:], close_prices[train_size:len(close_prices),:]

print(‘Split data into training set and test set… Number of training samples/ test samples:’, len(train), len(test))

    <div class="output_subarea output_stream output_stdout output_text">
      <pre>Split data into training set and test set... Number of training samples/ test samples: 192 96

create_dataset()で訓練用のラベルを生成する。現在のデータから一つ先(look_back=1)のデータ、つまり10分後の値動きを予想する。

  <p>
    ちなみにこの関数は便利で、look_backを2にすると、2つ前のデータ、つまり現在と10分前のデータから10分後のデータを予測することができる。look_backパラメータを調整することで、過去のデータから10分後のデータを予測できる。これを元の記事では、Window Methodと書いてある。
  </p>
</div>

In [9]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="c1"># convert an array of values into a time series dataset </span>

# in form # X Y # t-look_back+1, t-look_back+2, …, t t+1

def create_dataset(dataset, look_back): dataX, dataY = [], [] for i in range(len(dataset)-look_back-1): a = dataset[i:(i+look_back), ] dataX.append(a) dataY.append(dataset[i + look_back, ]) return np.array(dataX), np.array(dataY)

# convert Apple’s stock price data into time series dataset trainX, trainY = create_dataset(train, look_back) testX, testY = create_dataset(test, look_back) (trainX.shape, trainY.shape, testX.shape, testY.shape)

Out[9]:

    <div class="output_text output_subarea output_execute_result">
      <pre>((190, 1), (190,), (94, 1), (94,))</pre>
    </div>
  </div>
</div>

In [10]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="c1"># reshape input of the LSTM to be format [samples, time steps, features]</span>

trainX = np.reshape(trainX, (trainX.shape[], 1, trainX.shape[1])) testX = np.reshape(testX, (testX.shape[], 1, testX.shape[1])) (trainX.shape, testX.shape)

Out[10]:

    <div class="output_text output_subarea output_execute_result">
      <pre>((190, 1, 1), (94, 1, 1))</pre>
    </div>
  </div>
</div>

Build Model & Training

  <p>
    Kerasを利用してLSTMネットワークのモデルを作り、トレーニングを実施する。
  </p>
</div>

In [11]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="c1"># create and fit the LSTM network</span>

model = Sequential() model.add(LSTM(4, input_shape=(1, look_back))) model.add(Dense(1)) model.compile(loss=‘mean_squared_error’, optimizer=‘adam’) model.fit(trainX, trainY, epochs=epochs, batch_size=batch_size,verbose=2)

    <div class="output_subarea output_stream output_stdout output_text">
      <pre>Epoch 1/30

1s - loss: 0.1224 Epoch 230 0s - loss: 0.0332 Epoch 330 0s - loss: 0.0204 Epoch 430 0s - loss: 0.0160 Epoch 530 0s - loss: 0.0117 Epoch 630 0s - loss: 0.0082 Epoch 730 0s - loss: 0.0056 Epoch 830 0s - loss: 0.0041 Epoch 930 0s - loss: 0.0034 Epoch 1030 0s - loss: 0.0031 Epoch 1130 0s - loss: 0.0030 Epoch 1230 0s - loss: 0.0030 Epoch 1330 0s - loss: 0.0029 Epoch 1430 0s - loss: 0.0029 Epoch 1530 0s - loss: 0.0030 Epoch 1630 0s - loss: 0.0029 Epoch 1730 0s - loss: 0.0029 Epoch 1830 0s - loss: 0.0029 Epoch 1930 0s - loss: 0.0029 Epoch 2030 0s - loss: 0.0029 Epoch 2130 0s - loss: 0.0030 Epoch 2230 0s - loss: 0.0030 Epoch 2330 0s - loss: 0.0029 Epoch 2430 0s - loss: 0.0029 Epoch 2530 0s - loss: 0.0030 Epoch 2630 0s - loss: 0.0030 Epoch 2730 0s - loss: 0.0030 Epoch 2830 0s - loss: 0.0029 Epoch 2930 0s - loss: 0.0029 Epoch 3030 0s - loss: 0.0030

  <div class="output_area">
    <div class="prompt output_prompt">
      Out[11]:
    </div>

    <div class="output_text output_subarea output_execute_result">
      <pre>&lt;keras.callbacks.History at 0x7f29913c3b00&gt;</pre>
    </div>
  </div>
</div>

Predict

In [12]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="c1"># make predictions</span>

trainPredict = model.predict(trainX) testPredict = model.predict(testX)

In [13]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="c1"># invert predictions and targets to unscaled</span>

trainPredict = scaler.inverse_transform(trainPredict) trainY = scaler.inverse_transform([trainY]) testPredict = scaler.inverse_transform(testPredict) testY = scaler.inverse_transform([testY])

In [14]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="c1"># calculate root mean squared error</span>

trainScore = math.sqrt(mean_squared_error(trainY[], trainPredict[:,])) print(‘Train Score: %.5f RMSE’ % (trainScore)) testScore = math.sqrt(mean_squared_error(testY[], testPredict[:,])) print(‘Test Score: %.5f RMSE’ % (testScore))

    <div class="output_subarea output_stream output_stdout output_text">
      <pre>Train Score: 0.09638 RMSE

Test Score: 0.06509 RMSE

In [15]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="c1"># shift predictions of training data for plotting</span>

trainPredictPlot = np.empty_like(close_prices) trainPredictPlot[:, :] = np.nan trainPredictPlot[look_back:len(trainPredict)+look_back, :] = trainPredict

# shift predictions of test data for plotting testPredictPlot = np.empty_like(close_prices) testPredictPlot[:, :] = np.nan testPredictPlot[len(trainPredict)+(look_back*2)+1:len(close_prices)-1, :] = testPredict

In [16]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="c1"># plot baseline and predictions</span>

plt.plot(scaler.inverse_transform(close_prices)) plt.plot(trainPredictPlot) plt.plot(testPredictPlot) plt.show()

    <div class="output_png output_subarea ">
      <img src="http://futurismo.biz/wp-content/uploads/a3468b2a3ce342ea6e059347483820d6.png" />
    </div>
  </div>
</div>

予測結果は上の図。あまりにフィットしすぎて、なんかウソっぽいけれども、一応これが結果。

  <p>
    ちなみに、元の記事だとこの先もあるが、stepや state, stacked LSTMs が読んでもよくわからなかった。もう少し時間が必要。
  </p>

  <ul>
    <li>
      How to create an LSTM for a regression and a window formulation of the time series problem.
    </li>
    <li>
      How to create an LSTM with a time step formulation of the time series problem.
    </li>
    <li>
      How to create an LSTM with state and stacked LSTMs with state to learn long sequences.
    </li>
  </ul>

  <p>
    元記事を元に試してみたけれども、修正を加えるたびに精度が悪くなっていくのだった。
  </p>
</div>

おわりに

  <p>
    LSTMを FXのストラテジに応用できるか考えてみたのだけれども、よいストラテジが思いつかない。
  </p>

  <p>
    単純に回帰ならば、LSTMを使わなくてももっと簡単な方法がある。
  </p>

  <p>
    トレーニングに時間がかかるので、リアルタイムに過去のデータを処理して未来の値を予測できるのか?
  </p>

  <p>
    とはいえ、面白い話題なので、もう少し調べてみる。
  </p>
</div>

04 May 2017, 11:58

LSTM で坊ちゃんを学習させて文章生成

Udacity の Deep Learning Nanodegree Foundation week7。今回のテーマは RNN。

演習では、トルストイのアンナ・カレーニナの小説を LSTM で学習して、 文章を生成しているのだけれども、日本人の自分にはそのすごさがピンとこないので、 日本の小説で試してみた。

題材は、夏目漱石の坊ちゃん。

準備

青空文庫から坊ちゃんのテキストを入手した。

ルビ付きをダウンロードするとうまく学習できないと思って、 HTML 版からクリップボード経由で、テキストファイルにコピペした。

ipynb は以下。Udacity から提供された ipynb のインプットファイルを差し替えただけ。

ハイパーパラメータは酔う調整。以下のように設定した。

[sourcecode language=”python” title=””]
batch_size = 10 # Sequences per batch
num_steps = 50 # Number of sequence steps per batch
lstm_size = 128 # Size of hidden layers in LSTMs
num_layers = 2 # Number of LSTM layers
learning_rate = 0.01 # Learning rate
keep_prob = 0.5 # Dropout keep probability
[/sourcecode]

結果

オレオレいってますね。。。人工知能が小説をかける日はくるのだろうか・・・。

[sourcecode language=”text” title=””]
親切りにした. 山嵐とこんな所へは, おれはあったが, このおれは一人ではしたが, おれがこれでも, いいと, おれもおきませのような声だ. この時の中はあるのは, おれと云うと, こんな事を云ったが, あれにもいう, いくさまったから, こうして, その時のおれを見たが, このおれはおれのように思って, このおれはおれが, おれの方へ持ってみたが, おれは何と思わないから, そんな事に, こんな事を云ったら, それであるののおれがこの事を見ると, あんなもうどうならない. おれはおれは, おれももう, こうなってもいいから, こんなもんだ. おれが何と云うから, この時はおれの顔を出した. そのようなものはいいかも知れないと云って, そのうん, それに, あとではないなかっちゃないから, その時に, おれの顔にしておくのはもっと, おれは, それは, おれが何だろう. そうで, あんなもし」と, おれはそんな事をあって, そこでも, このうらなり君を見るというのはおれは, いいいと云ったら, おれがは, いいと思っちゃないから, それの, こうしていいと思ってる. それはいうと, いかした, このおれの事は, この一人には, それから, そうなっぽもこんな所へ出ると, おれはこんな, おれが何だかと云った.
「この時間を, いやなんです. いっしゃしたいと, いかなっと, おれのような所へ出たらいる. おれの事も, これにはおやじがないと, こんな事はこれはおれの方があると思った. いくしまい, これから, あの方が, おれがどうして来る. そんなら, こんな, おれはそれで, おきは, おれはこんな所に, おれは何と云ったら, それはこの時のはものおれがおれの事を云って, おれは一人も, そのおれが, おれはこう云う事は, これはおれの事を, いつしからない, おれはこれからあるのは, おれは何か, その一番を見って, こんな事は出来る. おれはおれは何があるまで, あんな事にはいる. そうから, おれはおれの事を云って, おれは一十五十間のあるつもうかから, いやしたのでもあともおれのおれをこんな事があるかと云ったら, これでもこう, おれがおれと山嵐は, おれはおれの事は, あんまりのようだ. あれにはもうあっぽどおれの事が出来ないと, これはあって, こんなものだ. おれはこれであなたが, あのおれはそれで, そのおきのおれの事をしまっている. おれはこんな, あとはおいたから, この時の中をはれったから, いやなんだ. おれは一番もうと云って来る. そのうらなら君の顔はないのだと思った. この時にはいったと云っていると, おれのお婆さん, おれの方を云ったら, いかない, あとうどうない. この時はあれないとも思ったが, これから, そのうち, いつものはあっても思っと, おれの顔を云うと, おれはこのおきの方を出る.
そのおれが, そのうちの人のはあっちが, いかしいと思ったら, おれの事を見るとおれのおれはおれはおやったのが, そうしたら, この時はあの人は, おれが山城屋が, いやにはいったからもう, あんなもとも, そのうらなり君のようでは, こうならないのは, あんな事は, この方におきと云われたから, おれはおれは, これから, あんなものか. いから, こうしまりゃなくれるのはありますから, いくなかったと思ったと, これはあのおれは, あとうんところはあとから云いている. おれの方を見るともうとう, あまりの事があった. おれはこのおれは, あまりなんだろう. いかしたもので, おれの顔はない. おれは一人ですか, この一つはいった. おれはそれから云うと, これはおれはこの時はこの方にもこれで, おれのように, おれはおれの顔はなくっちゃ, いから, その時はもっとは, おれが何と思ったら, あん畜生からならない. 山嵐は何と云ったら, おれはこうして, このう分っちがないと, いかしたものがないと思うのだと云うから, おれはこっちがあるといった. おれが山城屋の方へはある. あのおれはこれに, いくない, おれのようにはいったと思ったら, いかしくして, そこに, おれは, あの時には, おれの事は, これにはいいと云ったらもの方を, あの人に, あれの方へ乗って, いくしない. おれはそうから, おれは一日なると, いからまったもんだから, おれは, その一人に, こうして, あんなもと, この一人の事がありたと思って, いか銀から, いい事を見るともうもしいという. その方はこんな事がないのから, そう云うから, そうしていいと, この方は, それであるから, おいは, こうかかったから,
[/sourcecode]

03 May 2017, 09:30

Kaggle: Titanic 問題データ分析

はじめに

  <p>
    先日、Kaggleのタイタニック問題に挑んで惨憺たる結果を出しました。
  </p>

  <ul>
    <li>
      <a href="http://futurismo.biz/archives/6296">Kaggle のタイタニック問題に Keras で挑戦した。前処理が課題だと分かった。 | Futurismo</a>
    </li>
  </ul>

  <p>
    データ分析をするスキルが自分にはない。なんとか身につけたいと思っていたところ、<br /> Udemyの講座でKaggleのタイタニック問題を元にデータ分析を行っている講座を発見した。
  </p>

  <ul>
    <li>
      <a href="https://www.udemy.com/python-jp/learn/v4/">【世界で5万人が受講】実践 Python データサイエンス | Udemy</a>
    </li>
  </ul>

  <p>
    これはいい。まずは、講義にしたがってデータ分析してみたので、これはその講義メモです。
  </p>
</div>

目的

  <p>
    以下について、講義では調べている。
  </p>

  <ul>
    <li>
      タイタニック号の乗客はどのような人達だったのか?
    </li>
    <li>
      それぞれの乗客はどのデッキにいたか?また、それは客室の種類とどのような関係にあったか?
    </li>
    <li>
      乗客は主にどこから来たのか?
    </li>
    <li>
      家族連れか、単身者か?
    </li>
  </ul>
</div>

SetUp

  <p>
    タイタニック号のデータは下記のURLのtrainからダウンロードできる。
  </p>

  <ul>
    <li>
      <a href="https://www.kaggle.com/c/titanic/data?train.csv">https://www.kaggle.com/c/titanic/data?train.csv</a>
    </li>
  </ul>

  <p>
    まずは,csvの中身を確認。カラムの意味は <a href="https://www.kaggle.com/c/titanic/data">kaggleのサイト</a> を参照。
  </p>
</div>

In [3]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="kn">import</span> <span class="nn">pandas</span> <span class="k">as</span> <span class="nn">pd</span>

from pandas import Series, DataFrame titanic_df = pd.read_csv(‘train.csv’) titanic_df.head()

Out[3]:

    <div class="output_html rendered_html output_subarea output_execute_result">
      <div>
        <table class="dataframe" border="1">
          <tr style="text-align: right;">
            <th>
            </th>

            <th>
              PassengerId
            </th>

            <th>
              Survived
            </th>

            <th>
              Pclass
            </th>

            <th>
              Name
            </th>

            <th>
              Sex
            </th>

            <th>
              Age
            </th>

            <th>
              SibSp
            </th>

            <th>
              Parch
            </th>

            <th>
              Ticket
            </th>

            <th>
              Fare
            </th>

            <th>
              Cabin
            </th>

            <th>
              Embarked
            </th>
          </tr>

          <tr>
            <th>
            </th>

            <td>
              1
            </td>

            <td>
            </td>

            <td>
              3
            </td>

            <td>
              Braund, Mr. Owen Harris
            </td>

            <td>
              male
            </td>

            <td>
              22.0
            </td>

            <td>
              1
            </td>

            <td>
            </td>

            <td>
              A/5 21171
            </td>

            <td>
              7.2500
            </td>

            <td>
              NaN
            </td>

            <td>
              S
            </td>
          </tr>

          <tr>
            <th>
              1
            </th>

            <td>
              2
            </td>

            <td>
              1
            </td>

            <td>
              1
            </td>

            <td>
              Cumings, Mrs. John Bradley (Florence Briggs Th&#8230;
            </td>

            <td>
              female
            </td>

            <td>
              38.0
            </td>

            <td>
              1
            </td>

            <td>
            </td>

            <td>
              PC 17599
            </td>

            <td>
              71.2833
            </td>

            <td>
              C85
            </td>

            <td>
              C
            </td>
          </tr>

          <tr>
            <th>
              2
            </th>

            <td>
              3
            </td>

            <td>
              1
            </td>

            <td>
              3
            </td>

            <td>
              Heikkinen, Miss. Laina
            </td>

            <td>
              female
            </td>

            <td>
              26.0
            </td>

            <td>
            </td>

            <td>
            </td>

            <td>
              STON/O2. 3101282
            </td>

            <td>
              7.9250
            </td>

            <td>
              NaN
            </td>

            <td>
              S
            </td>
          </tr>

          <tr>
            <th>
              3
            </th>

            <td>
              4
            </td>

            <td>
              1
            </td>

            <td>
              1
            </td>

            <td>
              Futrelle, Mrs. Jacques Heath (Lily May Peel)
            </td>

            <td>
              female
            </td>

            <td>
              35.0
            </td>

            <td>
              1
            </td>

            <td>
            </td>

            <td>
              113803
            </td>

            <td>
              53.1000
            </td>

            <td>
              C123
            </td>

            <td>
              S
            </td>
          </tr>

          <tr>
            <th>
              4
            </th>

            <td>
              5
            </td>

            <td>
            </td>

            <td>
              3
            </td>

            <td>
              Allen, Mr. William Henry
            </td>

            <td>
              male
            </td>

            <td>
              35.0
            </td>

            <td>
            </td>

            <td>
            </td>

            <td>
              373450
            </td>

            <td>
              8.0500
            </td>

            <td>
              NaN
            </td>

            <td>
              S
            </td>
          </tr>
        </table>
      </div>
    </div>
  </div>
</div>

In [4]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">titanic_df</span><span class="o">.</span><span class="n">info</span><span class="p">()</span>

    <div class="output_subarea output_stream output_stdout output_text">
      <pre>&lt;class 'pandas.core.frame.DataFrame'&gt;

RangeIndex: 891 entries, 0 to 890 Data columns (total 12 columns): PassengerId 891 non-null int64 Survived 891 non-null int64 Pclass 891 non-null int64 Name 891 non-null object Sex 891 non-null object Age 714 non-null float64 SibSp 891 non-null int64 Parch 891 non-null int64 Ticket 891 non-null object Fare 891 non-null float64 Cabin 204 non-null object Embarked 889 non-null object dtypes: float64(2), int64(5), object(5) memory usage: 83.6+ KB

train.csvのなかには、891人の乗客のデータが含まれるけれども、AgeやCabinが Nanが多いことがわかる。

タイタニック号の乗客はどのような人達だったのか

性別に関して、女性、男性の数を調べる。

In [5]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>

import matplotlib.pyplot as plt import seaborn as sns %matplotlib inline

In [6]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">sns</span><span class="o">.</span><span class="n">countplot</span><span class="p">(</span><span class="s1">'Sex'</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">titanic_df</span><span class="p">)</span>

Out[6]:

    <div class="output_text output_subarea output_execute_result">
      <pre>&lt;matplotlib.axes._subplots.AxesSubplot at 0x7f1942ae6a90&gt;</pre>
    </div>
  </div>

  <div class="output_area">
    <div class="prompt">
    </div>

    <div class="output_png output_subarea ">
      <img src="http://futurismo.biz/wp-content/uploads/d51c9a4dafed2cd880f8d588f220ad72.png" />
    </div>
  </div>
</div>

女性の二倍近く男性が多いことがわかる。

客室のクラスで層別化

In [7]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">sns</span><span class="o">.</span><span class="n">countplot</span><span class="p">(</span><span class="s1">'Sex'</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="n">titanic_df</span><span class="p">,</span> <span class="n">hue</span><span class="o">=</span><span class="s1">'Pclass'</span><span class="p">)</span>

Out[7]:

    <div class="output_text output_subarea output_execute_result">
      <pre>&lt;matplotlib.axes._subplots.AxesSubplot at 0x7f194d251dd8&gt;</pre>
    </div>
  </div>

  <div class="output_area">
    <div class="prompt">
    </div>

    <div class="output_png output_subarea ">
      <img src="http://futurismo.biz/wp-content/uploads/7fb95fc331eefbb698644f3780b2890d.png" />
    </div>
  </div>
</div>

In [8]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">sns</span><span class="o">.</span><span class="n">countplot</span><span class="p">(</span><span class="s1">'Pclass'</span><span class="p">,</span><span class="n">data</span><span class="o">=</span><span class="n">titanic_df</span><span class="p">,</span><span class="n">hue</span><span class="o">=</span><span class="s1">'Sex'</span><span class="p">)</span>

Out[8]:

    <div class="output_text output_subarea output_execute_result">
      <pre>&lt;matplotlib.axes._subplots.AxesSubplot at 0x7f193f6ef588&gt;</pre>
    </div>
  </div>

  <div class="output_area">
    <div class="prompt">
    </div>

    <div class="output_png output_subarea ">
      <img src="http://futurismo.biz/wp-content/uploads/6eb2b11a900f4bf0456df8ec822e5e62.png" />
    </div>
  </div>
</div>

三等客室の男性が多いことがわかる。

子供という新しい列を追加

  <p>
    子供を優先して助けたということがkaggleのサイトにかかれているので、子供がどのくらいいるかを調べる。ここでは、16歳未満が子供。
  </p>
</div>

In [9]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="k">def</span> <span class="nf">male_female_child</span><span class="p">(</span><span class="n">passenger</span><span class="p">):</span>
<span class="n">age</span><span class="p">,</span><span class="n">sex</span> <span class="o">=</span> <span class="n">passenger</span>
<span class="k">if</span> <span class="n">age</span> <span class="o">&lt;</span> <span class="mi">16</span><span class="p">:</span>
    <span class="k">return</span> <span class="s1">'child'</span>
<span class="k">else</span><span class="p">:</span>
    <span class="k">return</span> <span class="n">sex</span>

titanic_df[‘person’] = titanic_df[[‘Age’,‘Sex’]].apply(male_female_child,axis=1)

In [12]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">sns</span><span class="o">.</span><span class="n">countplot</span><span class="p">(</span><span class="s1">'Pclass'</span><span class="p">,</span><span class="n">data</span><span class="o">=</span><span class="n">titanic_df</span><span class="p">,</span><span class="n">hue</span><span class="o">=</span><span class="s1">'person'</span><span class="p">)</span>

Out[12]:

    <div class="output_text output_subarea output_execute_result">
      <pre>&lt;matplotlib.axes._subplots.AxesSubplot at 0x7f19433e22e8&gt;</pre>
    </div>
  </div>

  <div class="output_area">
    <div class="prompt">
    </div>

    <div class="output_png output_subarea ">
      <img src="http://futurismo.biz/wp-content/uploads/5e2fc220fd19b91aba0ba0ab152dc580.png" />
    </div>
  </div>
</div>

In [13]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">titanic_df</span><span class="p">[</span><span class="s1">'person'</span><span class="p">]</span><span class="o">.</span><span class="n">value_counts</span><span class="p">()</span>

Out[13]:

    <div class="output_text output_subarea output_execute_result">
      <pre>male      537

female 271 child 83 Name: person, dtype: int64

1等客室、2客室には子供が少ない。3客室に多い。これで年齢分布が分かった。

  <p>
    次に、カーネル密度推定で分布を見てみる。
  </p>
</div>

In [17]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">fig</span> <span class="o">=</span> <span class="n">sns</span><span class="o">.</span><span class="n">FacetGrid</span><span class="p">(</span><span class="n">titanic_df</span><span class="p">,</span> <span class="n">hue</span><span class="o">=</span><span class="s2">"person"</span><span class="p">,</span> <span class="n">aspect</span><span class="o">=</span><span class="mi">4</span><span class="p">)</span>

fig.map(sns.kdeplot, ‘Age’, shade=True) oldest = titanic_df[‘Age’].max() fig.set(xlim=(, oldest)) fig.add_legend()

    <div class="output_subarea output_stream output_stderr output_text">
      <pre>/home/tsu-nera/anaconda3/lib/python3.6/site-packages/statsmodels/nonparametric/kdetools.py:20: VisibleDeprecationWarning: using a non-integer number instead of an integer will result in an error in the future

y = X[:m/2+1] + np.r_[0,X[m/2+1:],0]*1j

  <div class="output_area">
    <div class="prompt output_prompt">
      Out[17]:
    </div>

    <div class="output_text output_subarea output_execute_result">
      <pre>&lt;seaborn.axisgrid.FacetGrid at 0x7f193f213e80&gt;</pre>
    </div>
  </div>

  <div class="output_area">
    <div class="prompt">
    </div>

    <div class="output_png output_subarea ">
      <img src="http://futurismo.biz/wp-content/uploads/8922e58c431d0cc763e62204ea897a07.png" />
    </div>
  </div>
</div>

In [18]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">fig</span> <span class="o">=</span> <span class="n">sns</span><span class="o">.</span><span class="n">FacetGrid</span><span class="p">(</span><span class="n">titanic_df</span><span class="p">,</span> <span class="n">hue</span><span class="o">=</span><span class="s2">"Pclass"</span><span class="p">,</span><span class="n">aspect</span><span class="o">=</span><span class="mi">4</span><span class="p">)</span>

fig.map(sns.kdeplot,‘Age’,shade= True) oldest = titanic_df[‘Age’].max() fig.set(xlim=(,oldest)) fig.add_legend()

    <div class="output_subarea output_stream output_stderr output_text">
      <pre>/home/tsu-nera/anaconda3/lib/python3.6/site-packages/statsmodels/nonparametric/kdetools.py:20: VisibleDeprecationWarning: using a non-integer number instead of an integer will result in an error in the future

y = X[:m/2+1] + np.r_[0,X[m/2+1:],0]*1j

  <div class="output_area">
    <div class="prompt output_prompt">
      Out[18]:
    </div>

    <div class="output_text output_subarea output_execute_result">
      <pre>&lt;seaborn.axisgrid.FacetGrid at 0x7f193f238208&gt;</pre>
    </div>
  </div>

  <div class="output_area">
    <div class="prompt">
    </div>

    <div class="output_png output_subarea ">
      <img src="http://futurismo.biz/wp-content/uploads/1716019788b55655778ec18831b54e9c.png" />
    </div>
  </div>
</div>

それぞれの乗客はどのデッキにいたか(Cabin)?

  <p>
    Cabinは Nanが多いので、これを取り除く。Cabinは頭文字(Cxx, Dxx, Exx など)でレベル別に分けられるので、レベル別に見てみる。
  </p>
</div>

In [19]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">deck</span> <span class="o">=</span> <span class="n">titanic_df</span><span class="p">[</span><span class="s1">'Cabin'</span><span class="p">]</span><span class="o">.</span><span class="n">dropna</span><span class="p">()</span>

In [23]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">levels</span> <span class="o">=</span> <span class="p">[]</span>

for level in deck: levels.append(level[]) cabin_df = DataFrame(levels) cabin_df.columns = [‘Cabin’] sns.countplot(‘Cabin’,data=cabin_df,palette=‘winter_d’,order=sorted(set(levels)))

Out[23]:

    <div class="output_text output_subarea output_execute_result">
      <pre>&lt;matplotlib.axes._subplots.AxesSubplot at 0x7f193f0ce780&gt;</pre>
    </div>
  </div>

  <div class="output_area">
    <div class="prompt">
    </div>

    <div class="output_png output_subarea ">
      <img src="http://futurismo.biz/wp-content/uploads/0bfa7bd5bc987b02fdd1c4af6558cc2b.png" />
    </div>
  </div>
</div>

A,B,C,D,E,F,G… T と T が外れ値となっている(間違ったデータ??)ので、Tを取り除く。

In [24]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">cabin_df</span> <span class="o">=</span> <span class="n">cabin_df</span><span class="p">[</span><span class="n">cabin_df</span><span class="o">.</span><span class="n">Cabin</span> <span class="o">!=</span> <span class="s1">'T'</span><span class="p">]</span>

sns.countplot(‘Cabin’,data=cabin_df,palette=‘summer’,order=sorted(set(cabin_df[‘Cabin’])))

Out[24]:

    <div class="output_text output_subarea output_execute_result">
      <pre>&lt;matplotlib.axes._subplots.AxesSubplot at 0x7f193f00ecf8&gt;</pre>
    </div>
  </div>

  <div class="output_area">
    <div class="prompt">
    </div>

    <div class="output_png output_subarea ">
      <img src="http://futurismo.biz/wp-content/uploads/c024cc6b97ab2f8b039a9ee8f305f511.png" />
    </div>
  </div>
</div>

乗客はどこから乗ったか?

  <p>
    Embarkedのカラムを見る。C,Q,S という値は、それぞれCherbourg, Queenstown, Southhampton。Southhamptonが圧倒的におおいことが分かる。
  </p>
</div>

In [25]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">sns</span><span class="o">.</span><span class="n">countplot</span><span class="p">(</span><span class="s1">'Embarked'</span><span class="p">,</span><span class="n">data</span><span class="o">=</span><span class="n">titanic_df</span><span class="p">,</span><span class="n">hue</span><span class="o">=</span><span class="s1">'Pclass'</span><span class="p">)</span>

Out[25]:

    <div class="output_text output_subarea output_execute_result">
      <pre>&lt;matplotlib.axes._subplots.AxesSubplot at 0x7f193efbff60&gt;</pre>
    </div>
  </div>

  <div class="output_area">
    <div class="prompt">
    </div>

    <div class="output_png output_subarea ">
      <img src="http://futurismo.biz/wp-content/uploads/f7d081bd05719cad80c2bc53cb7f6d4b.png" />
    </div>
  </div>
</div>

In [27]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">titanic_df</span><span class="o">.</span><span class="n">Embarked</span><span class="o">.</span><span class="n">value_counts</span><span class="p">()</span>

Out[27]:

    <div class="output_text output_subarea output_execute_result">
      <pre>S    644

C 168 Q 77 Name: Embarked, dtype: int64

ちなみに自分が小学生のとき、タイタニックの音楽を合奏する機会があって、Southhamptonのマーチをリコーダーで演奏した。

  <p>
    <a href="http://www.youtube.com/watch?v=fCPC6-6n5Uo"><img src="http://img.youtube.com/vi/fCPC6-6n5Uo/0.jpg" alt="IMAGE ALT TEXT HERE" /></a>
  </p>
</div>

家族連れか、単身者か?

  <p>
    Aloneのカラムを追加します。
  </p>
</div>

In [30]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">titanic_df</span><span class="p">[</span><span class="s1">'Alone'</span><span class="p">]</span> <span class="o">=</span> <span class="n">titanic_df</span><span class="o">.</span><span class="n">Parch</span> <span class="o">+</span> <span class="n">titanic_df</span><span class="o">.</span><span class="n">SibSp</span>

titanic_df[‘Alone’].loc[titanic_df[‘Alone’] >] = ‘With Family’ titanic_df[‘Alone’].loc[titanic_df[‘Alone’] == ] = ‘Alone’

    <div class="output_subarea output_stream output_stderr output_text">
      <pre>/home/tsu-nera/anaconda3/lib/python3.6/site-packages/pandas/core/indexing.py:141: SettingWithCopyWarning: 

A value is trying to be set on a copy of a slice from a DataFrame

See the caveats in the documentation: http://pandas.pydata.org/pandas-docs/stable/indexing.html#indexing-view-versus-copy self._setitem_with_indexer(indexer, value)

In [31]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">sns</span><span class="o">.</span><span class="n">countplot</span><span class="p">(</span><span class="s1">'Alone'</span><span class="p">,</span><span class="n">data</span><span class="o">=</span><span class="n">titanic_df</span><span class="p">,</span><span class="n">palette</span><span class="o">=</span><span class="s1">'Blues'</span><span class="p">)</span>

Out[31]:

    <div class="output_text output_subarea output_execute_result">
      <pre>&lt;matplotlib.axes._subplots.AxesSubplot at 0x7f193ef73eb8&gt;</pre>
    </div>
  </div>

  <div class="output_area">
    <div class="prompt">
    </div>

    <div class="output_png output_subarea ">
      <img src="http://futurismo.biz/wp-content/uploads/94b2a136ff9bd372b77372348e344399.png" />
    </div>
  </div>
</div>

単身者がおおい。

In [32]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">titanic_df</span><span class="p">[</span><span class="s2">"Survivor"</span><span class="p">]</span> <span class="o">=</span> <span class="n">titanic_df</span><span class="o">.</span><span class="n">Survived</span><span class="o">.</span><span class="n">map</span><span class="p">({</span><span class="mi"></span><span class="p">:</span> <span class="s2">"no"</span><span class="p">,</span> <span class="mi">1</span><span class="p">:</span> <span class="s2">"yes"</span><span class="p">})</span>

sns.countplot(‘Survivor’,data=titanic_df,palette=‘Set1’)

Out[32]:

    <div class="output_text output_subarea output_execute_result">
      <pre>&lt;matplotlib.axes._subplots.AxesSubplot at 0x7f193eef0b70&gt;</pre>
    </div>
  </div>

  <div class="output_area">
    <div class="prompt">
    </div>

    <div class="output_png output_subarea ">
      <img src="http://futurismo.biz/wp-content/uploads/89f48756a8c20b39fbb7dd564e0d8807.png" />
    </div>
  </div>
</div>

大勢の人がなくなっていることがわかる。客室の種類は関係があるのかをみると、3等客室が死亡者が多いことがわかる。

In [33]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">sns</span><span class="o">.</span><span class="n">factorplot</span><span class="p">(</span><span class="s1">'Pclass'</span><span class="p">,</span><span class="s1">'Survived'</span><span class="p">,</span><span class="n">data</span><span class="o">=</span><span class="n">titanic_df</span><span class="p">,</span> <span class="n">order</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">])</span>

Out[33]:

    <div class="output_text output_subarea output_execute_result">
      <pre>&lt;seaborn.axisgrid.FacetGrid at 0x7f193f082e10&gt;</pre>
    </div>
  </div>

  <div class="output_area">
    <div class="prompt">
    </div>

    <div class="output_png output_subarea ">
      <img src="http://futurismo.biz/wp-content/uploads/a584fc48dd2faee368d63127ee2d1451.png" />
    </div>
  </div>
</div>

「女性と子供を先に」というポリシーが本当に実施されていたかをみる。グラフを見ると、女性や子供の生存率が高い。

In [34]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">sns</span><span class="o">.</span><span class="n">factorplot</span><span class="p">(</span><span class="s1">'Pclass'</span><span class="p">,</span><span class="s1">'Survived'</span><span class="p">,</span><span class="n">hue</span><span class="o">=</span><span class="s1">'person'</span><span class="p">,</span><span class="n">data</span><span class="o">=</span><span class="n">titanic_df</span><span class="p">,</span> <span class="n">order</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">aspect</span><span class="o">=</span><span class="mi">2</span><span class="p">)</span>

Out[34]:

    <div class="output_text output_subarea output_execute_result">
      <pre>&lt;seaborn.axisgrid.FacetGrid at 0x7f193ed63f98&gt;</pre>
    </div>
  </div>

  <div class="output_area">
    <div class="prompt">
    </div>

    <div class="output_png output_subarea ">
      <img src="http://futurismo.biz/wp-content/uploads/4d46ccd0c0c9cdc3a67c660cb14b887b.png" />
    </div>
  </div>
</div>

生存率と年齢の、クラスの関係を見てみると、年齢が高いと生存率が下がる。

In [36]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">generations</span><span class="o">=</span><span class="p">[</span><span class="mi">10</span><span class="p">,</span><span class="mi">20</span><span class="p">,</span><span class="mi">40</span><span class="p">,</span><span class="mi">60</span><span class="p">,</span><span class="mi">80</span><span class="p">]</span>

sns.lmplot(‘Age’,‘Survived’,hue=‘Pclass’,data=titanic_df,palette=‘winter’, x_bins=generations,hue_order=[1,2,3])

Out[36]:

    <div class="output_text output_subarea output_execute_result">
      <pre>&lt;seaborn.axisgrid.FacetGrid at 0x7f193f0ddac8&gt;</pre>
    </div>
  </div>

  <div class="output_area">
    <div class="prompt">
    </div>

    <div class="output_png output_subarea ">
      <img src="http://futurismo.biz/wp-content/uploads/a81c169dfff765508baed3e42d6f04f8.png" />
    </div>
  </div>
</div>

性別と年齢の関係もみる。

In [37]:
<div class="inner_cell">
  <div class="input_area">
    <div class=" highlight hl-ipython3">
      <pre><span class="n">sns</span><span class="o">.</span><span class="n">lmplot</span><span class="p">(</span><span class="s1">'Age'</span><span class="p">,</span><span class="s1">'Survived'</span><span class="p">,</span><span class="n">hue</span><span class="o">=</span><span class="s1">'Sex'</span><span class="p">,</span><span class="n">data</span><span class="o">=</span><span class="n">titanic_df</span><span class="p">,</span><span class="n">palette</span><span class="o">=</span><span class="s1">'winter'</span><span class="p">,</span><span class="n">x_bins</span><span class="o">=</span><span class="n">generations</span><span class="p">)</span>

Out[37]:

    <div class="output_text output_subarea output_execute_result">
      <pre>&lt;seaborn.axisgrid.FacetGrid at 0x7f193ecdac88&gt;</pre>
    </div>
  </div>

  <div class="output_area">
    <div class="prompt">
    </div>

    <div class="output_png output_subarea ">
      <img src="http://futurismo.biz/wp-content/uploads/fb35b6ecad305e6d0e026ca7ec9bb145.png" />
    </div>
  </div>
</div>

まとめ

  • 男性が女性よりも多い。
  • 女性や子供は男性よりも生存率が高い。(-> personがfactor候補)
  • サウサンプトンからの乗客が多い。
  • 高齢者ほど生存率が低い(->Ageがfactor候補)
  • クラスが高いほど生存率が高い(-> PClassがfactor候補)
  • 単身者が多い

以上を踏まえてKaggle再挑戦

以上から、前回の特徴量を見直して、Kaggle再挑戦しました。

その結果は、5759位でした。

You advanced 305 places on the leaderboard!

Your submission scored 0.75598, which is an improvement of your previous score of 0.74163. Great job!

300人抜きしたけれども、まだまだ改善が必要です。

03 May 2017, 06:20

Jupyter Notebook で書いた ipynb を WordPress の記事にするには jupy2wp が便利

Jupyter Notebook で実行した結果や、matplotlib や seaborn で生成した図を、 そのまま WordPress に表示して、記事にしたいとする。

調べてみると、以下の やり方があるようだ。

  1. gist に アップロードして公開したものを WordPress に 埋め込む。
  2. Jupyter Notebook を html 形式で、ダウンロードする。
  3. .ipynb ファイルを nbconvert で html ファイルにして WordPress に入力する。
  4. jupy2wp を使う。

gist を埋め込む

Jupyter Notebook には、Gist-it という extentions がある。 extentions の有効方法については、以下の README を参照。

これを有効にすると、ツールバーに gist のマークが現れる。 ポチルだけで、gist に ipynb がアップロードされて、公開される。

注意点は、gist-it の設定画面から Github personal access token を入力することだ。 そうしないと、anonymous として gist が公開される。

しかし、この方法は自分は好まない。なぜなら、gist を WordPress に 埋め込んだとき、 コードの高さが固定されてスクロールバーが出てきてしまうからだ。この回避方法がわからなかった。 もし、この問題が回避できれば、gist はいいかもしれない。

どういう仕組みかわからないけれども、図表も表示される。

HTML 形式でダウンロードする

Jupyter Notebook の notebook を開いて、 File > Download as > HTML から html 形式でダウンロードする。

出来た html ファイルを WordPress のテキスト画面に貼り込む

この作戦も、自分は好まない。なぜなら、Jupyter Themes を使っているのだけれども、 Themes が反映された状態で HTML がダウンロードされるからだ。

黒背景を使っているので、真っ黒な画面になった、よくない。

nbconvert をつかう

以下のサイトで紹介されている方法。

1.Jupyter Notebook でコンテンツを作り、Save する 2.nbconvert で html ファイルに変換する

[sourcecode language=”sh” title=”” ]
$ jupyter nbconvert –to html –template basic 出来たファイル.ipynb
[/sourcecode]

3.出来た html ファイルを WordPress のテキスト画面に貼り込む 4.Wordpress の CSS ファイルに最後に示した CSS を追加する。

これはいいかもしれない。しかし、もっといい方法を見つけた。

jupy2wp を使う

jupy2wp というツールを使う。

インストール方法は README 参照。ちょっとコマンドオプションが長いけれども、以下のように使う。

[sourcecode language=”bash” title=”” ]
python -m jupy2wp.jupy2wp –xmlrpc-url http://futurismo.biz/xmlrpc.php –user username –password hogehoge –nb titanic-cnn.ipynb –title “Kaggle: Titanic 問題データ分析” –categories [Python, 統計] –tags keras
[/sourcecode]

こうすると、下書きの状態で、ipynb で表示されていた内容がそのまま記事として投稿される。

さらに、画像は、/upload フォルダ配下に自動でアップロードされて保存される。これはいい。

02 May 2017, 10:19

TOEICほぼ900点達成

2017年4月の公開テストで895(L475/R420)をとりました。

ほぼ、900です。自分の中ではもう十分TOEIC満足です。

どうやって、TOEIC900達成したか?それは・・・ひたすらバカみたいに努力したから。

1700時間勉強したのだ。

このFuturismoのブログ、2016年はほとんど記事を更新していない。なにをしていたかというと、ひたすらTOEICを勉強していた。

正直、エンジニアやめようかと思ってた。

このサイトに、勉強時間の目安が書いてある。400点の人でも1500時間で900可能らしい。

自分がTOEICの勉強をはじめたのが、2015年11月でその時点で805点。

たった、90点あげるために1700時間も費やした。自分はバカなんじゃないかと思う。そうとう効率が悪い。

いや、実際バカなのだった。IQが89しかない(平均は100)。心理テストの結果、言語能力が人並みよりも特に低いのだ。

それでも、能力は努力で克服できることを証明したくて、バカみたいに頑張り、諦めなかった。GRITを信じた。

その結果だ。

 

TOEIC900とっても、英語は喋れないし、相変わらずMOOCのレクチャーは分からないし、英文読むのはしんどい。

まだまだ英語全然できない。

とりあえず、もうTOEICはいいです。別のことに時間を使います。

02 May 2017, 09:38

Udemy 悪くないかもしれない、機械学習系の講座が充実。セールで大人買いしよう!

2017-05-02-183736_572x189_scrot.png

Udemy で実践データサイエンスを受けてる。これが悪くない。

初 Udemy です

初 Udemy の講座。今まで、Udemy はべらぼうな価格設定のため舐めてました。

通常の講座が 15000 円とか 25000 円とかなので、 こんな値段で購入する人いないでしょと思っていたけれども、 Udemy は 頻繁にセールをすることで有名らしい。年中セールをやっているとか。

通常の値段で購入する人は滅多にいないだろう。 私は、1200 円で購入しました。GW は 教師の日??とかいうキャンペーンをやってる。

4 月の頭にも、新生活応援キャンペーンを実施していた。

Udemy 悪くないかも

Udemy は 思っていたよりも悪くないと思う。Udemy については、 アフィリエイトのせいか、coursera や edX や Udacity に比べて宣伝のサイトがわんさかあるので、 Udemy がなにかを知りたいひとは、そのサイトへ。ベネッセがバックにいるらしい。

自分が高評価したのは、コンテンツがバラエティに富んでいるからだ。 日本語のコンテンツで探してはダメ、英語のコンテンツで検索すること。

coursera や Edx, Udacity は大学や大企業がバックについているけれども、 Udemy は個人が講座を開いているので、バラエティに富んでいる。

ここが高評価のポイント。日本語コンテンツがあるのもうれしいね。

自分が購入したもの、全部 10 $だよ

私は、以下の Machine Learning & Deep Learning の講座を全部 10 ドル 1200 円で大人買いした。

他にも、いろいろと 機械学習系の講座を購入。

その他、システムトレードに興味があるので、以下の講座を購入。

すべて10ドル。15 万以上割引で購入したと思う。もともとの価格設定が狂ってるけど。

購入した講座、全てやり切れないと思うけれども、セールに煽られて散財してしまった yo。

02 May 2017, 07:05

ダークな黒背景でクールにデータ解析!Jupyter Notebook Themes & Emacs KeyBinding

最近、Emacs よりも Jupyter Notebook の使用率が高いのだけれども(?!)、 今朝 twitter の タイムラインを眺めてたらこんなツイートが流れてきたので、飛びついた。

試してみたら、ものすごくクールだったので、スクショをとってみたのが以下。黒背景、メチャガチャクールだ。

Jupyter Themes

Jupyter Notebook を 黒背景にするには、Jupyter Themes という extentions を使う。

インストールは pip から。

pip install jupyterthemes

これで、jt コマンドが利用出来るようになる。

テーマは以下のテーマがある。私の大好きな monokai がある!!これは、うれしい! 他にも solarized の Light と Dark がある。

$ jt -l
Available Themes: 
   oceans16
   chesterish
   grade3
   solarizedl
   monokai
   onedork
   solarized-light

テーマの適用には、-t <theme> をつけて jt を呼ぶ。

jt -t monokai

フォルダはこんな感じ。

オプションに -N -T をつけると、ツールバーと ノート名を表示できる。

私の最終的な設定は、以下にした。 code のフォントは プログラミングに適していると言われている Ricty で有名な inconsolata。

jt -t monokai -f inconsolata -N -T 

追記

seaborn の縦軸横軸の表示が、背景が黒だとなにもみえなくなった。以下で解決。

custom_style = {'axes.labelcolor': 'white',
                'xtick.color': 'white',
                'ytick.color': 'white'}
sns.set_style("darkgrid", rc=custom_style)

Emacs KeyBindings

こうなったら、Emacs ライクに Jupyter Notebook をしようと思い、 Emacs ライクにキーバインディングをする方法も調べてみた。以下の extentions を入れる。

pip install jupyter-emacskeys

これで、コードを書くときに Emacs keyBindings が使える、と思ったがここで一つ問題が。 Ctrl + n は Emacs では 下に移動に割当たっているのだけれども、 ブラウザでは新しいウィンドウを開くに割り当てられているので、使えない。

これは、Ctrl + n で新しいウィンドウを開くのを無効にする firefox プラグイン、 “Menu Wizard”を入れることで解決できた。

このプラグイン、バグっているのか再起動すると、設定が消えるので、 ブラウザを立ち上げるたびに設定しないといけないのが難点。 Shift-Alt-M で設定画面が開くのでそこで設定する。

さよなら Emacs

これで Jupyter Notebook が markdown ではなく org-mode でかければ最強なのだけれどもそんなマイナーなニーズには対応していない。

とはいえ、データサイエンティストを目指すには Emacs とはおさらばだ!!

01 May 2017, 06:36

Kaggle のタイタニック問題に Keras で挑戦した。前処理が課題だと分かった。

Kaggle のタイタニック問題に Keras で挑戦しました。

前置き

タイタニック問題は、Kaggle の看板コンペということで、いろんな人が挑戦している。

自分も早くデータサイエンティストになりたいので、登竜門であるコンペに挑戦してみた。

タイトルが、Titanic: Machine Learning from Disaster とある通り、機械学習を 使って問題を解くことが求められているのだけれども、自分の ToolBox には、 ニューラルネットワーク一本槍しかない。

他の手法も身につけたいのだけれども、他にも手を出すと知識が発散してしまうので、 今はニューラルネットワークひとつにかけている。

最近 Keras をいじりはじめたので、Keras でニューラルネットワークを組んで問題に挑戦してみた。

考察

モデルのチューニングが難しい。

以下のようなモデルを組んでみたのだけれども、精度が 75%。 これで上位 90% という惨憺たる結果。

# create model
model = Sequential()
model.add(Dense(64, input_shape=(8,)))

for i in range(0, 8):
    model.add(Dense(units=64))
    model.add(Activation('relu'))

model.add(Dense(units=1))
model.add(Activation('linear'))

model.compile(loss='mean_squared_error', optimizer='rmsprop')

9 層の Dense レイヤ(Relu 関数で activate) のあとに、1 ノードの出力層を設けた。 コスト関数は、最小二乗誤差、最適化手法は RMSProp.

Bach Norm や Dropout 層を入れることも検討したのだけれども、そうすると精度が下がる。 この設計以上にシンプルにしたり、複雑にしてみたりしたのだけれども、精度が下がる。

チューニング方法が試行錯誤なので、難しい。いい方法がないか、考察中。 チューニングにベストプラクティスはあるのだろうか?直感に頼るしかないのだろうか? 経験を積めば、知識が増えて、いい方法がすぐに思いついたりするのだろうか?

前処理はズルをしました

どういう特徴量を使うかは、以下の記事を参考(パクリ)にしました。

本当は、以下のようなデータ分析をしてデータの傾向を見る必要があるのだけれども、 そういうスキルが自分にはまだない。これから時間をかけて身につけていく。

おそらくだけれども、この前処理の段階を改善することで、精度がグンと上がるのだと思う。 Udemy に参考になりそうな講座がいくつかあるので、購入しようか検討中。(追記:セールだったので購入した。1200 円!)

そういう気づきを得られただけでも、今回参加した価値はあったと思う。 とにかく動くことで課題が明確になる。

コード

github に jupyter notebook をアップロードしました。

29 Apr 2017, 22:10

3 つの戦略で Overfitting を撃退!Tensorflow v1.1 を使って CNN で MNIST に挑んだ

はじめに

fast.ai の Practical Deep Learning for Coders を受けてます。week3 のテーマは overfitting. いかにして、overfitting を防いで精度を向上させるかという話。 理論のあと実際の MNIST のデータを使って精度を向上させるレクチャーがあった。

先週、ちょうど Kaggle の手書き数字認識に挑戦していたので、 今回習ったことを Kaggle に適用してみて、精度が実際どうなるか見てみました。

また、先週 tensorflow 1.1 がリリースされて、 TensorFlow から Keras の機能が使えるようになったので、 それも試してみました。

結論から書くと、1050 位から 342 位への大躍進!上位 20%に近づきました。

Overfitting を防ぐ戦略

Overfitting とは

まずは、Overfitting についておさらい。過学習ともいう。

Overfitting とは、訓練データの精度はいいのだけれども未知のデータの精度が悪いこと。 モデルが汎化されていない状態を指す。

どうやって、確認するかというと、訓練データの他に Validation データを用意して Training のときに、訓練データと validation データの精度を出す。 もし、訓練データの精度がいいけれども、validation データの精度が悪いと Overfitting が起こっている可能性が高い。

Overfitting

OverFitting を防ぐ戦略

講義の中では、以下のステップで対策することが示される。

  1. Add more data
  2. Use data augmentation
  3. Use architectures that generalize well
  4. Add regularization
  5. Reduce architecture complexity.

とくに、2 と 4 に関して、実践的な手法である

が示される。

Dropout

階層の深いニューラルネットワークを精度よく最適化するために Hinton 教授 たちによって提案された手法。

その手法とは、ニューロンをランダムに消去しながら学習する手法。 訓練時に隠れ層のニューロンをランダムに選び出し、 その選び出したニューロンを消去する。

こんな手法で過学習を防げるのかとはじめは驚いたものの、 確かにこれで精度が出るのだ。

今回は、以下のクラスを利用した。

Data Augmentation

画像データを妥当な修正を加えることで、追加合成データを作成すること。 たとえば、ひっくり返したり、回したり、ズームしたり、クリッピングしたり、 色を変更したりなどなど。

参考:

Tensorflow(keras)には、ImageDataGenerator というクラスがあり、これを利用する。

Bach Normalization

Bach Normalization とは、 各層でのアクティベーションの分布を適度な広がりを持つように調整すること。

前処理として、データを加工することはよくやることだけれども、 アクティベーションされた分布に処理を加えることが特徴。これによって、

などの利点がある。

Tensorflow(keras) では、以下のクラスがある。

MNIST に挑戦

今回は、以下の Keras(backend は Theano)を Tensorflow v1.1 にポーティングした。

今回作成した、自分の Jupyter Notebook は以下。

以下、コードの抜粋を以下に示す。

まずは、import。tensorflow.contrib.keras.python.keras と書く。 この書き方がわからずハマった。

import tensorflow as tf
from tensorflow.contrib.keras.python.keras.models import Sequential
from tensorflow.contrib.keras.python.keras.layers import Flatten, Dense, Dropout, Lambda, Conv2D, BatchNormalization, MaxPool2D
from tensorflow.contrib.keras.python.keras.optimizers import Adam
from tensorflow.contrib.keras.python.keras.preprocessing.image import ImageDataGenerator

ネットワークを構成。ちょくちょく BatchNormalization の層が入っているところがポイント。 Dropout 層も出口のところに設けてある。

def get_model_bn_do():
    model = Sequential()
    model.add(Lambda(norm_input, input_shape=(28,28,1)))
    model.add(Conv2D(filters=32,kernel_size=(3,3), activation='relu'))
    model.add(BatchNormalization(axis=1))
    model.add(Conv2D(filters=32,kernel_size=(3,3), activation='relu'))
    model.add(MaxPool2D())
    model.add(BatchNormalization(axis=1))
    model.add(Conv2D(filters=64,kernel_size=(3,3), activation='relu'))
    model.add(BatchNormalization(axis=1))
    model.add(Conv2D(filters=64,kernel_size=(3,3), activation='relu'))
    model.add(MaxPool2D())
    model.add(Flatten())
    model.add(BatchNormalization())
    model.add(Dense(512, activation='relu'))
    model.add(BatchNormalization())
    model.add(Dropout(0.5))
    model.add(Dense(10, activation='softmax'))
    model.compile(Adam(), loss='categorical_crossentropy', metrics=['accuracy'])
    return model

以下のようなネットワークができあがる。

Layer (type)                 Output Shape              Param #   
=================================================================
lambda_1 (Lambda)            (None, 28, 28, 1)         0         
_________________________________________________________________
conv2d_1 (Conv2D)            (None, 26, 26, 32)        320       
_________________________________________________________________
batch_normalization_1 (Batch (None, 26, 26, 32)        104       
_________________________________________________________________
conv2d_2 (Conv2D)            (None, 24, 24, 32)        9248      
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 12, 12, 32)        0         
_________________________________________________________________
batch_normalization_2 (Batch (None, 12, 12, 32)        48        
_________________________________________________________________
conv2d_3 (Conv2D)            (None, 10, 10, 64)        18496     
_________________________________________________________________
batch_normalization_3 (Batch (None, 10, 10, 64)        40        
_________________________________________________________________
conv2d_4 (Conv2D)            (None, 8, 8, 64)          36928     
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 4, 4, 64)          0         
_________________________________________________________________
flatten_1 (Flatten)          (None, 1024)              0         
_________________________________________________________________
batch_normalization_4 (Batch (None, 1024)              4096      
_________________________________________________________________
dense_1 (Dense)              (None, 512)               524800    
_________________________________________________________________
batch_normalization_5 (Batch (None, 512)               2048      
_________________________________________________________________
dropout_1 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 10)                5130      
=================================================================
Total params: 601,258.0
Trainable params: 598,090.0
Non-trainable params: 3,168.0

data augmentation を ImageDataGenerator で実施する。 パラメータでいろいろ変更できるようになっている。

gen = ImageDataGenerator(rotation_range=8, width_shift_range=0.08, shear_range=0.3,
                            height_shift_range=0.08, zoom_range=0.08)
batches = gen.flow(features, labels, batch_size=batch_size)
test_batches = gen.flow(valid_features, valid_labels, batch_size=batch_size)

fit_generator で学習。ちなみに、train_on_batch 関数だと、メモリ枯渇を起こした。

model.fit_generator(batches, batches.n//batch_size, epochs=1,
                    validation_data=test_batches, validation_steps=test_batches.n//batch_size)

predict_classes 関数でテストデータを予測。

classes = model.predict_classes(test_features)