scikit-learnでトレーニングデータとテストデータを分割する

2016-02-19
このエントリーをはてなブックマークに追加

機械学習させるときに用意したデータの9割を学習用データに、1割をテストデータに使ったりします。その分割を手軽にしてくれます。scikit-learnを使いたくてPython書いてるようなもんです。

from sklearn.cross_validation import train_test_split
import numpy as np

def main():

    _train_x, _train_y, _test_x, _test_y = train_test_split(
        np.array([
            [0, 1, 0, 1, 0, 1, 0, 1, 0, 1],
            [1, 1, 0, 1, 0, 1, 0, 1, 0, 1],
            [2, 1, 0, 1, 0, 1, 0, 1, 0, 1],
            [3, 1, 0, 1, 0, 1, 0, 1, 0, 1],
            [4, 1, 0, 1, 0, 1, 0, 1, 0, 1],
            [5, 1, 0, 1, 0, 1, 0, 1, 0, 1],
            [6, 1, 0, 1, 0, 1, 0, 1, 0, 1],
            [7, 1, 0, 1, 0, 1, 0, 1, 0, 1],
            [8, 1, 0, 1, 0, 1, 0, 1, 0, 1],
            [9, 1, 0, 1, 0, 1, 0, 1, 0, 1]
        ]),
        np.array([0, 1, 0, 1, 0, 1, 0, 1, 0, 1]),
        test_size=0.1
    )
    print(_train_x)

if __name__ == "__main__":
    main()

test_size=0.1、で10%をテスト用データとして分割してくれます。

[[0 1 0 1 0 1 0 1 0 1]
 [8 1 0 1 0 1 0 1 0 1]
 [7 1 0 1 0 1 0 1 0 1]
 [4 1 0 1 0 1 0 1 0 1]
 [2 1 0 1 0 1 0 1 0 1]
 [5 1 0 1 0 1 0 1 0 1]
 [6 1 0 1 0 1 0 1 0 1]
 [1 1 0 1 0 1 0 1 0 1]
 [3 1 0 1 0 1 0 1 0 1]]

これだけでシャッフルして指定した割合で分割してくれるからありがたい。

Pythonのスクリプトを起動するときのオプションを指定する方法

2016-01-26
このエントリーをはてなブックマークに追加

以前は optparse 使ってましたけど、廃止予定だそうです。で、今は argparse 使います。2.7以降はargparseが標準で入ってるそうなので、今時はもうoptparseも使えはするけどargparse一択でしょう。

from argparse import ArgumentParser

if __name__ == "__main__":

    _parser = ArgumentParser()

    _parser.add_argument(
        '-s',
        '--string',
        type=str,
        dest='string',
        required=True,
        help='String Value'
    )

    _parser.add_argument(
        '-n',
        '--number',
        type=int,
        dest='number',
        required=True,
        help='Number Value'
    )

    _args = _parser.parse_args()

    print(_args.string, _args.number)

なんのオプションも指定しないで起動すると

$ python sample.py
usage: sample.py [-h] -s STRING -n NUMBER
sample.py: error: argument -s/–string is required

「-sで文字列、-nで値を指定してね。-sは必須オプションだからエラーだよ。」
ってメッセージがでます。親切です。

$ python sample.py -s S -n N
usage: sample.py [-h] -s STRING -n NUMBER
sample.py: error: argument -n/–number: invalid int value: ‘N’

-n に文字列を与えてもエラーが出ます。ちゃんと型チェックしてくれます。親切です。

$ python sample.py -s Hello -n 123
(‘Hello’, 123)

便利。

PythonでWord2Vecを使って類義語抽出

2015-11-12
このエントリーをはてなブックマークに追加

今更のWord2Vec。

分かち書きしたテキストファイルを読み込ませて学習データを作って保存。保存した学習データを読み込んで類義語を出力するところまで。毎回学習してから類義語抽出っていう訳にもいかないから学習データの保存は必要ですよね、っていうサンプル。

Word2Vecはおもしろいし、いろいろ触ってるので今後もブログに書いていこう。このエントリも下書きのまま1年くらい放置されててちゃんとブログ書かねばと反省中。。。

from gensim.models import word2vec

def main():

    data = word2vec.Text8Corpus("/path/to/file")
    model = word2vec.Word2Vec(data, size=250, window=5, min_count=2, workers=4)
    model.save("./teacher.bin")

    model = word2vec.Word2Vec.load("./teacher.bin")
    for _w in model.most_similar(positive=['ジャケット']):
        print(_w)

if __name__ == "__main__":
    main()

Pythonでscikit-learnを使ってランダムフォレストの分類器を書いて、学習結果を保存してみた

2015-10-01
このエントリーをはてなブックマークに追加

分類するだけじゃなくて学習したデータを保存もしています。学習データがあったらデータを読み込んで利用します。

import os

from sklearn.ensemble import RandomForestClassifier
from sklearn.externals import joblib


class RandomForest(object):
    def __init__(self):
        if os.path.exists('./.supervised/data.bin'):
            self._m = joblib.load('./.supervised/data.bin')

        else:
            _training_data = [
                [2, 0, 0, 0],
                [0, 2, 0, 0],
                [0, 0, 2, 0],
                [0, 0, 0, 2],
            ]
            _training_label = [1, 2, 3, 4]

            self._m = RandomForestClassifier()
            self._m.fit(_training_data, _training_label)

            joblib.dump(self._m, './.supervised/data.bin')

    def start(self):
        _test_data = [
            [0, 4, 0, 0],
            [0, 0, 0, 2]
        ]
        _out = self._m.predict(_test_data)

        print(_out)

if __name__ == "__main__":
    _obj = RandomForest()
    _obj.start()

結果出力
[2 4]

Pythonでnumpyを使って値を正規化する

2015-09-24
このエントリーをはてなブックマークに追加
$ import numpy as np
$ _array = np.array([1, 2, 3])
$ _n_array = _array / np.amax(_array) * 1
$ print(_n_array)

[ 0.33333333  0.66666667  1.        ]

0から1の間に収めます。
こんなに簡単にできちゃうって素晴らしい。

Tags:

「人間のためのHTTP」Requestsでオレオレ証明書かつベーシック認証を突破する

2015-08-14
このエントリーをはてなブックマークに追加

Requests は「人間のためのHTTP」という謳い文句のhttpライブラリ。確かにとても便利。Python3であれば http.client 使えばいいんですけど、ついついRequestsを使ってしまう。

_response = requests.get(
     'https://TARGET_URL',
     auth=('user_name', 'passwd'),
     verify=False
)

auth=の部分がベーシック認証、verify=Falseがオレオレ証明書の許容。これだけです。簡単。

まあ、

InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised.

ってWarning吐きまくってるんですけどね。

Requestsが動くならPython2でも3でも動くはずです。

Pythonでジョブキューしてみる

2015-08-02
このエントリーをはてなブックマークに追加

PythonでジョブキューするといえばやっぱりCeleryがスタンダードなんだろうか。RQというシンプルなジョブキューライブラリもあるんですけど、今回はCeleryを動かしてみる。

インストールは簡単。

pip install Celery

バックエンドはRabbitMQかRedisで使うのが良さそうです。手元の環境にRedisが入っていたのでそのままRedisを使ってみます。

from celery import Celery

app = Celery('tasks', broker='redis://localhost:6379/0')

@app.task
def task(message):
    return "Hello {0}".format(message)

上記をjob.pyとして保存しておきます。で、このjob.pyをワーカーとして起動。このワーカーがデキューしてくれます。

$ celery -A job worker --loglevel=info

いろいろログを出力して起動してくれます。ワーカーの起動はいろいろオプションがあります。デーモンとして動かしたり並列で大量に立ち上げたり。非常に便利。

で、エンキューはもうインタラクティブシェルでもできます。

$ python
Python 3.4.2 (default, Oct 16 2014, 01:53:40)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-4)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from job import task
>>> task.delay("World.")

エンキューもこれだけ。
で、エンキューするとさっき立ち上げたワーカーの方でデキューしてジョブを捌いてくれます。

succeeded in 0.0014186919997882796s: 'Hello World.'

こんな簡単にジョブキューの仕組みが作れるなんて。

Pythonでscikit-learnを使ってNon-negative Matrix Factorization

2015-06-16
このエントリーをはてなブックマークに追加

Non-negative Matrix Factorization(NMFでググるといろいろ出てきます)、非負値行列因子分解です。

集合知プログラミング でも紹介されている特徴を抽出する方法です。推薦エンジンとかにも使われているそうです。

書籍では自前で実装されてますがscikit-learnに同じものがあるので便利に利用させていただきます。

import numpy as np
from sklearn.decomposition import ProjectedGradientNMF


def main():

    X = np.array([
        [1, 0, 0],
        [1, 1, 0],
        [0, 1, 0],
        [0, 1, 0],
        [0, 0, 1],
    ])

    model = ProjectedGradientNMF(init='nndsvdar')
    _res = model.fit_transform(X)
    print(_res)

if __name__ == "__main__":
    main()

実行するとこんな感じで出力されます。

$ python nfm.py
[[ -0.00000000e+00   9.15822497e-01  -0.00000000e+00]
 [  6.85467400e-01   9.15816894e-01  -0.00000000e+00]
 [  6.85636205e-01   2.24117374e-09  -0.00000000e+00]
 [  6.85636205e-01   2.24116561e-09  -0.00000000e+00]
 [ -0.00000000e+00  -0.00000000e+00   9.99944486e-01]]

素晴らしい。

サンプルデータをちゃんと投入すればもうちょっとまともな値がでてきます。パラメータの与え方はちゃんと検証して調整しないとです。

動かした環境はPython3.4で、

$ pip freeze
numpy==1.9.2
scikit-learn==0.16.1
scipy==0.15.1

Python便利。

Tornadoをデバッグモード、オートリロードで稼働させる

2015-05-24
このエントリーをはてなブックマークに追加

tornado

Wikipediaにも「Pythonで書かれたスケーラブルでノンブロッキングなWebサーバ、Webフレームワーク」と書かれたTornadoのデバッグモードをオンにしてファイルの変更を検知してリロードしてくれるようにするやり方。

import tornado.ioloop
import tornado.web


class MainHandler(tornado.web.RequestHandler):
    def get(self):
        self.write("Hello, world")

application = tornado.web.Application(
    [
        (r"/", MainHandler),
    ],
    debug=True
)

if __name__ == "__main__":
    application.listen(8888)
    tornado.ioloop.IOLoop.instance().start()

ほとんどサンプルのまんまです。

debug=True だけでオートリロードもしてくれます。簡単。これだとデバッグモード切り替えで都度コードの書き換えが必要になるのでコマンドライン引数で振る舞い変えるようにしたほうがいいでしょうね。

TornadoはPython3.2以降にも対応してるので安心です。

PythonでunixタイムスタンプをDatetimeオブジェクトに変換する

2015-05-22
このエントリーをはてなブックマークに追加
from datetime import datetime
print(datetime.fromtimestamp(1432049226))

これだけ。