深層学習とその他

機械学習したいマン

kaggleの始め方

アドベントカレンダー21日目です。

adventar.org

今日はリクエストみたいなことされたので、kaggleの始め方について書きたいとおもいます。

kaggleとは

つい先日軽く触れたのでここを少し参照してください。

looseleaf0727.hatenablog.jp

コンペに参加

kaggleではいろんなコンペが開かれています。コンペの一覧はこちらから確認できます。 Competitions | Kaggle

練習用のものや、実際に賞金が出るもの、終わったコンペなどが見られます。 今回は入門用のTitanicに挑戦してみます。 https://www.kaggle.com/competitions f:id:looseleaf0727:20171222132549p:plain

コンペの概要

それぞれのコンペをクリックした先のページ、Overviewに書かれています。 どのような課題があるのか、どのようなデータが与えられるのか、何を予測してほしいのか、賞金についてなど色々ここに書かれています。

今回のTitanicの例では、有名なタイタニック号の沈没の話ですが、乗船していた客に生存者がいました。生存したか、チケットの等級、性別、年齢・・・など様々な情報が学習データとして与えられます。この学習データを元に、予測を行うモデルを作成します。最終的には、生存したかどうかが抜けている本番データを用いて、生存したかどうかを予測します。

与えられるデータの中身やその説明などはDataタブに書かれています。 OverviewのEvaluationには、提出するファイルのフォーマットが書かれています。このフォーマットに基づいたファイルを提出することで、精度などのスコアが計算され、自分の順位を確認できるようになります。

データのダウンロードと予測

今回コンペのデータとして、学習に使うtrain.csv,検証に使うtest.csv,あとgender_submission.csvの3つのファイルが与えられています。train.csvを使って、予測をしていきましょう。

環境はjupyter notebook、python3でいきます。 基本的にはpandasとかいうの使うと便利なのでそれでいきましょう。

csvを読み込んでpandasのDataFrameにしました。headを使うことで指定した分だけデータを見れます。表で見れるのがいいですね。

import pandas as pd
train = pd.read_csv("train.csv")

train.head(3)

f:id:looseleaf0727:20171222170008p:plain

dtypeを見ておきます。

train.dtypes

>>>
PassengerId      int64
Survived         int64
Pclass           int64
Name            object
Sex             object
Age            float64
SibSp            int64
Parch            int64
Ticket          object
Fare           float64
Cabin           object
Embarked        object
dtype: object

null値が入ってないか確認しましょう。

train.isnull().sum()

>>>
PassengerId      0
Survived         0
Pclass           0
Name             0
Sex              0
Age            177
SibSp            0
Parch            0
Ticket           0
Fare             0
Cabin          687
Embarked         2
dtype: int64

性別で生存率が違うのかなあって思ったので調べてみましょう。欠損もラッキーなことにありませんでした。まずは人数を調べます。

len(train[train.Sex == "male"])
>>> 577

len(train[train.Sex == "female"])
>>> 314

性別ごとの生存率を見てみましょう。1なら生存してます。

(train[train.Sex == "male"]["Survived"] == 1).mean()
>>> 0.18890814558058924

(train[train.Sex == "female"]["Survived"] == 1).mean()
>>> 0.7420382165605095

男性は19%しか生存してないけど、女性は74%も生存してますね。
何も考えずに、男性なら死亡、女性なら生存で予測するモデルということにしましょう。

本番データを読み込んで、欠損値の確認をします。

test = pd.read_csv("test.csv")
test.isnull().sum()

>>>
PassengerId      0
Pclass           0
Name             0
Sex              0
Age             86
SibSp            0
Parch            0
Ticket           0
Fare             1
Cabin          327
Embarked         0
dtype: int64

先程の条件で、性別のみで決定をしていきます。
あとは、提出するフォーマットに合わせるため、Idと予測でセットにします。
注意点としては、index=Falseにしておかないと提出したときにエラーを出します。

Survived = []

for i in test.Sex:
    if i == "male":
        Survived.append(0)
    else:
        Survived.append(1)

out = pd.DataFrame(test.PassengerId)
out["Survived"] = Survived
out.to_csv("submission1.csv", index=False)

あとは、出力されたcsvを提出します。
Submit Predictionから提出できます。 f:id:looseleaf0727:20171222171800p:plain

csvファイルをアップロードし、Optionalですが、Describeを記入してもいいです。 f:id:looseleaf0727:20171222171812p:plain

スコアはLeaderBoardから確認できます。自分のスコアや、正しく動作したかなどが表示されます。 f:id:looseleaf0727:20171222172058p:plain

コンペのトップページで再び戻ってみると、順位を確認できます。 f:id:looseleaf0727:20171222172238p:plain

機械学習を使う

機械学習を使う際にはscikit-learnを使うと非常に楽ができます。 * 学習データと検証データの分割 * F1値などの表示 * 学習と予測 * 最適なパラメータの探索 * 混合行列の作成

使うアルゴリズムの選定は、scikit-learnに選ぶときに参考になる画像があります。そちらを見て決めていきましょう。

今回は色々検証したりしたのですが、めちゃめちゃ書くと文量が多くなるので途中でやめておきます・・・。 ソースコードは貼り付けておくので見てみてください。

trainerのextensionsについて

アドベントカレンダー20日目です。

adventar.org

今日はchainerのtrainer extensionsについて書いていきたいと思います。

Trainerについて

chainerのバージョン1.10.0でTrainerが実装されました。 従来は学習ループをがしがし記述していたのですが、Trainerはより抽象化されており、比較的簡単に学習の記述ができます。また、Trainer extesionsを使うことにより、様々な追加機能を使うことが出来ます。

Trainer Extensionsの一覧と公式の説明

簡易な説明はこちらで見ることが出来ます。

Trainer extensions — Chainer 3.2.0 documentation

  • chainer.training.extensions.dump_graph
    Returns a trainer extension to dump a computational graph.

  • chainer.training.extensions.Evaluator
    Trainer extension to evaluate models on a validation set.

  • chainer.training.extensions.ExponentialShift
    Trainer extension to exponentially shift an optimizer attribute.

  • chainer.training.extensions.LinearShift
    Trainer extension to change an optimizer attribute linearly.

  • chainer.training.extensions.LogReport
    Trainer extension to output the accumulated results to a log file.

  • chainer.training.extensions.observe_lr
    Returns a trainer extension to record the learning rate.

  • chainer.training.extensions.observe_value
    Returns a trainer extension to continuously record a value.

  • chainer.training.extensions.snapshot
    Returns a trainer extension to take snapshots of the trainer.

  • chainer.training.extensions.snapshot_object
    Returns a trainer extension to take snapshots of a given object.

  • chainer.training.extensions.ParameterStatistics
    Trainer extension to report parameter statistics.

  • chainer.training.extensions.PlotReport
    Trainer extension to output plots.

  • chainer.training.extensions.PrintReport
    Trainer extension to print the accumulated results.

  • chainer.training.extensions.ProgressBar
    Trainer extension to print a progress bar and recent training status.

補足程度の説明

  • chainer.training.extensions.dump_graph
    何も考えずに名前だけで推察すると、学習のグラフでも出してくれるのかな?って思いますが、実際はネットワークの計算グラフを出力します。長所なのか短所なのかdotで出力されるため、画像を確認するときは少し手間がかかります。

  • chainer.training.extensions.Evaluator
    テストデータを入力することでモデルの評価を行うことができます。ログをとるときにもこれを動かすとわかりやすいかもしれません。

  • chainer.training.extensions.ExponentialShift
    optimizerの数値を指数関数的に変化させていくことができる。これは結構便利そうに見えたので一度導入を試みたのですが、エラーを吐いてしまって以来使用していません。

  • chainer.training.extensions.LinearShift
    ExponentialShiftに対し、こちらはLinearにShiftします。使ったことがないのでわからないですが、ExponentialShiftとくらべてみたいところですね。

  • chainer.training.extensions.LogReport
    指定したタイミングごとに、ログをファイルに出力してくれます。これはかなり便利なので、Trainerを使うならほぼ間違いなく使うべきです。

  • chainer.training.extensions.observe_lr 

  • chainer.training.extensions.observe_value
    この2つはいまいちよくわかりませんでした。使用例をみて今度考えてみましょう。

  • chainer.training.extensions.snapshot
    trainerのsnapshotsをとります。これも非常に便利なので使ったほうがいいです。これを使うと、学習の途中から再開することが可能となります。

  • chainer.training.extensions.snapshot_object
    先程のものに対し、こちらはmodelなどのObjectを保存するのに使えます。これもほぼ間違いなく使うべきです。

  • chainer.training.extensions.ParameterStatistics
    W/data/meanなどのパラメータ情報をレポートします。見た感じではいまいち便利なのかはわからなかった・・・。

  • chainer.training.extensions.PlotReport
    これはグラフを生成してくれます。logファイルを読んでグラフを生成するという作業が不要になるのかな?

  • chainer.training.extensions.PrintReport
    LogReportはログファイルを出力しますが、こちらはprintしてくれます。これも特に使わない理由はないと思います。

  • chainer.training.extensions.ProgressBar
    進捗状態のバーを出してくれます。ある程度精神衛生に優しいので、jupyterとかで学習してないときにはおすすめです。

まとめ

extensionsには色々便利な機能があるので、できるだけたくさん使ったほうが幸せになれるかもしれない。

kaggleでお勉強

アドベントカレンダー19日目です。

adventar.org

今日はkaggleについて少々、あとkaggleを使ったお勉強について書きたいと思います。

kaggleとは

データサイエンスで現実の問題を解決するようなコンペが行われてるサイトです。 Kaggle: Your Home for Data Science

企業が現実世界で起こっている問題に対し、コンペを開きます。参加者は企業が公開するデータを元に、その課題に取り組み、予測を行うモデルを作成します。最終的には、ランキングの上位者には賞金が支払われ、その代わりに、ソースコードを提示します。

また、コンペが行われてる以外にも、データセットが公開されていたりします。kaggleに登録しているユーザーは、新しいデータに触ることができます。対して、データを登録するユーザーの上位は、賞金を受け取ることができます。これはkaggleの非常にいい点であると思います。

後は、kaggleのKarnelでソースコードを動かすことが出来たり、議論をする場もあったりします。

kaggleの良いところ

データ分析に興味がある人だったとしても、現実世界の何かしらの問題をデータ分析で解決してみたい、と思ったときにはそれに応じたデータが必要となります。kaggleでは、この問題を解決してほしいということがあり、それに必要なデータも与えられています。現実世界での問題を自分で解くことができるのは一つの楽しみかなと思います。

kaggleでお勉強

データ分析を勉強していきたいと思ったときに、どうやって勉強したらいいのかわからないと思います。実際自分もわかっていません。CS231nを見て勉強したり、PRMLを読んだりいろんな勉強法はあるかと思いますが、kaggleでお勉強するのも一つの手だと思います。

kaggleで実際に手を動かしながら学んだり、上位者の手法や、Kernelを見ることで理解を深めることができます。実際にデータ分析を行ってる人のソースコードを読むことができるのは、非常にいいところだと思います。

後は、ただ単純にお勉強という感じではなく、コンペに参加し、ランキングを上げるというゲーム感覚で学んでいけるのも非常にいいかなと思います。

まとめ

kaggle面白いので周りにも利用者が増えて欲しい。

pythonのCounterについて

アドベントカレンダー18日目です。

adventar.org

今日はPythonのCounterについて書いていきます。

Counterとは?

与えられた要素について数を数えます。公式の例がわかりやすいです。

c = Counter()                           # a new, empty counter
c = Counter('gallahad')                 # a new counter from an iterable
c = Counter({'red': 4, 'blue': 2})      # a new counter from a mapping
c = Counter(cats=4, dogs=8)             # a new counter from keyword args

8.3. collections — コンテナデータ型 — Python 3.6.3 ドキュメント

Counterを使ってみる

使い方は簡単です。 collectionsからCounterをimportします。 後は、Counterに要素を投げることで、数え上げて辞書型で保存します。極めて簡単ですね。

from collections import Counter

print(Counter("aiueooiusiuuu"))
>>> Counter({'u': 5, 'i': 3, 'o': 2, 'e': 1, 's': 1, 'a': 1})

今回は、Counterに入力するデータとしてオバマさんの演説を持ってきました。なぜオバマさんの演説かというと、英語で形態素解析がいらなくて楽だからです。文章はここから持ってきました。 www.nikkei.com

前処理として、改行を消したり、「,」「.」を消したり、「-」を空白に置換し、大文字は全て小文字にしました。

Counterに入力し、試しに上位10件の単語を見てみましょう。

sentence = "" #オバマさんの演説
counter = Counter(sentence)
count = counter.most_common()
print(count[:10])
>>> [('the', 74), ('and', 57), ('to', 50), ('of', 47), ('that', 41), ('we', 33), ('a', 31), ('our', 22), ('is', 15), ('us', 14)]

上位10件で円グラフを書きました。ただしコレの%は全体から見た数値ではないので要注意です。

import matplotlib.pyplot as plt
%matplotlib inline

x = [x[1] for x in count][:10]
label = [label[0] for label in count][:10]

plt.figure(figsize=(5,5), dpi=100)
plt.pie(x, labels=label, startangle=90, counterclock=False, autopct='%.1f%%', pctdistance=0.75)
plt.axis('equal') 
plt.show()

f:id:looseleaf0727:20171219000127p:plain

imagenetとその使い方について

アドベントカレンダー17日目です。https://blog.hatena.ne.jp/looseleaf0727/looseleaf0727.hatenablog.jp/edit?entry=8599973812327479500

adventar.org

今日はimagenetの説明と、使い方について書いていきたいと思います。

imagenetについて

こちらのことです。 ImageNet f:id:looseleaf0727:20171217225557p:plain

画像のデータベースで、分類などの学習に使うデータを集めたりすることが出来ます。具体的にどのような種類の画像があるかは、上のExploreから見ていくことが出来ます。 f:id:looseleaf0727:20171217225713p:plain

Exploreに飛んだ画面です。 様々なジャンルのツリーがあり、そこから更にサブツリーがあります。 一瞬誤解をしてしまいそうですが、カッコの中の数字はサブツリーの数であり、画像の数ではありません。 今回はbeachを見てみました。 たくさんの画像が出てきますが、重複に気をつける必要がありそうです。 f:id:looseleaf0727:20171217230207p:plain

上の検索窓でbreadについて検索してみました。 たくさんのbreadに関する内容が出てきています。 この中から、必要に応じて見ていくわけですね。 f:id:looseleaf0727:20171217230952p:plain

試しにItalian breadを開いてみました。画像の一覧が表示されました。Downloadsを押すことでダウンロードができます。 f:id:looseleaf0727:20171217231837p:plain

Download URLs of images in the synsetからは画像がダウンロードできます。 Download Bounding BoxesはYoloのような物体の位置を検出する際に使うデータだと思います。 f:id:looseleaf0727:20171217232055p:plain

画像のダウンロードの仕方

先程のDownload URLs of images in the synsetをクリックするとこのような画面になります。これは画像のURL一覧です。なので、ここから画像をダウンロードしてあげる必要があります。 f:id:looseleaf0727:20171217232602p:plain

先程のリンクをwgetしてリンク一覧を持ってきます。

wget http://image-net.org/api/text/imagenet.synset.geturls?wnid=n07687626

これでリンク集が手に入りました。あとはこのリンクから画像を拾うだけです。今回はpythonを使って拾いました。引数でリンクのファイルを渡すと拾ってきてくれます。保存ディレクトリは指定してないので、必要があれば修正してください。

import os
import sys
import codecs
import urllib.request

f = codecs.open(sys.argv[1], 'r', 'utf8', 'ignore')

for line in f.readlines():
    try:
        img = urllib.request.urlopen(line[0:-2])
        localfile = open(os.path.basename(line[0:-2]), 'wb')
        localfile.write(img.read())
        img.close()
        localfile.close()
    except Exception as e:
        print(e)

注意点

拾ってきた画像の中ではリンクが参照できず、エラーの画像などが入っている場合が多いです。ざっくりと確認して弾くのがいいと思います。

まとめ

imagenetを使ってみなさんも分類問題でもやってみましょう。

水平棒グラフの作成をした

アドベントカレンダー16日目です。

adventar.org

今日はmatplotlibで水平棒グラフを作成しました。

水平棒グラフとは

通常イメージする棒グラフは縦方向ですが、水平棒グラフは横に棒グラフが伸びていきます。こんな感じのが水平棒グラフです。 f:id:looseleaf0727:20171217002839p:plain

今回は、水平棒グラフをmatplotlibで作成したのでそれについて書いていきます。

水平棒グラフの作り方

plt.barhを使うことで作成できます。ただし、plt.plotとは少し値の指定が違うので気をつけてください。

いつも通り公式のドキュメントを見ましょう。 matplotlib.axes.Axes.barh — Matplotlib 2.1.1 documentation

必要となる値は、棒グラフの座標と高さです。 今回はサンプルのデータとして、適当にa-zの文字を1,000個選び、その個数を元に水平棒グラフを作成しました。 要素の種類の数だけ座標を作り、counterから個数とラベルをとりました。

import numpy as np
from collections import Counter
import matplotlib.pyplot as plt
import string
%matplotlib inline

chars = string.ascii_uppercase
char = [chars[x] for x in ary]

counter = Counter(char)
counter = counter.most_common()

y = np.arange(len(counter))
width = [counter[x][1] for x in range(len(counter))]
label = [counter[x][0] for x in range(len(counter))]

plt.figure(figsize=(10,8),dpi=100)
plt.barh(y, width, tick_label=label)
plt.tick_params(labelsize = 15)
plt.title("count")
plt.xlabel("number")
plt.grid()
plt.show()

本当はメルカリのデータでやってたんですが、載せていいのかわからないのでダミーデータにしたらゴミっぽいグラフになりました。

今回のコード

参考

Pythonの大文字と数字によるランダムな文字列の生成 - string - random | CODE Q&A [日本語]

ubuntu14.04 + python3 でopencvをいれて動画をいじろうとしたら苦戦した話

アドベントカレンダー15日目です。

adventar.org

今日はopencvをインストールしようとして苦戦した話を書いていきます。

成功するまでにやったこと

  1. pip install opencv-pythonで普通にインストール
  2. opencv-3.0.0 をビルド
  3. ffmpegを入れてもう一度ビルド
  4. Contribを入れてビルド
  5. Git checkoutでバージョン指定してビルド
  6. conda install -c https://conda.anaconda.org/menpo opencv3でインストール
  7. pip install opencv-contrib-pythonでインストール
  8. conda install opencvでインストール

最後の一つで成功しました。 ffmpegとかは多分必要な部分だと思います。

手こずった理由

今回は深層学習でのスタイル転移で、動画を入力して変換するという作業を行う過程でopencvを使います。opencv自体はpipですぐはいるのですが、なぜか動画が読み込めない・・・。読み込めているかどうかは以下のコードで確認しました。

import cv2

filename = "mp4_h264_aac.mp4" 
cap = cv2.VideoCapture(filename)
print(cap.read())

うまくいっていない場合には以下のような出力です。
>>> (False, None)

うまくいっている際には数値が出力されるはずです。

成功したインストール方法

自分はpyenvでanaconda3-4.1.0を使用しています。なので、condaでインストールが可能となります。

github.com こちらのREADME曰く、conda install opencvでインストールできるとのことです。

インストールした後、先程のコードを実行し直してみます。

(True, array([[[ 93,  27,   1],
        [ 92,  26,   0],
        [ 91,  25,   0],
        ...,
        [112,  45,   0],
        [112,  45,   0],
        [112,  45,   0]],

Trueが返ってきていて、値も入っています。これで動画の処理ができます。

まとめ

ビルドをしなくて済む方法をまず探るべき。