PythonでたまったQueueをMulti Threadでさばいていく方法

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

Queueにはいったジョブを指定したThread数で順番にさばいていきたいよ、っていうときに使います
あんまり大量にQueueにいれるとメモリからあふれて落ちるんだろうな

import threading
import queue
import time
from datetime import datetime

QUEUE = queue.Queue()


def worker():
    while True:
        _docs = QUEUE.get()
        job_worker(_docs)
        QUEUE.task_done()

def job_worker(docs):
    print(datetime.now())
    print(docs)
    time.sleep(1)
    return None

def main():

    _threads = []
    for _i in range(2):
        _t = threading.Thread(target=worker)
        _t.daemon = True
        _t.start()
        _threads.append(_t)

    _docs = ["a", "b", "c", "d", "e", "f", "g"]
    for _doc in _docs:
        QUEUE.put(_doc)

    QUEUE.join()

if __name__ == "__main__":
    main()

実行するとこんな出力になります、threadがふたつなのでふたつずつ処理されてますね

2017-12-17 17:55:49.769058
a
2017-12-17 17:55:49.769201
b
2017-12-17 17:55:50.770286
c
2017-12-17 17:55:50.770461
d
2017-12-17 17:55:51.771527
e
2017-12-17 17:55:51.771687
f
2017-12-17 17:55:52.772768
g

Python3.6で書いたサンプルです

PythonのSciPyで値の標準化

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

「平均が0、分散が1」ってやつです。
平均引いて標準偏差で割ればいいので大した計算量ではないのですが、SciPyを使うと関数一発。便利すぎる。

import numpy as np
from scipy.stats import zscore


def main():
    _array = np.array([1, 2, 3, 4, 5])
    _n = zscore(_array)

    print(_n)
    print(np.mean(_n))
    print(np.var(_n))


if __name__ == "__main__":
    main()
$ python standardization.py
[-1.41421356 -0.70710678  0.          0.70710678  1.41421356]
0.0
1.0

PythonでTwitterのStreaming APIを受信する

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

全Tweetの1%と言われるPublic streamsのsampleを受信してみます。

OAuthやらStreamやら、どう実装するかなーと調べてみるとRequests: 人間のためのHTTP があれば十分なことがわかったし、親切なサンプルコードも書かれてたのであっさり実装できてしまった。

OAuth 1 Authentication

Streaming Requests

import json

import requests
from requests_oauthlib import OAuth1


def main():
    _auth = OAuth1(
        API_KEY,
        API_SECRET,
        ACCESS_TOKEN,
        ACCESS_SECRET
    )

    _stream = requests.get(
        "https://stream.twitter.com/1.1/statuses/sample.json?language=ja",
        auth=_auth,
        stream=True,
    )

    for _line in _stream.iter_lines():

        _doc = json.loads(_line.decode("utf-8"))
        print(json.dumps(_doc, ensure_ascii=False, indent=2))


if __name__ == '__main__':
    main()

日本語のツイートだけ取得したかったのでlanguage=jaを追加しています。Requests便利すぎ。

CentOS7にPython3.6.0をソースからインストールした

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

久々に新しくec2に私用でインスタンスたてたのでこれまでずっとAmazon Linux使ってたけどCentOS7にしてみた。ついでに先日リリースされたPython3.6.0をインストールしてみました。

cd /usr/local/src/
sudo wget https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tgz
sudo tar zxfv Python-3.6.0.tgz
sudo chown -R centos. Python-3.6.0
cd Python-3.6.0
./configure --enable-shared --enable-optimizations
sudo make
sudo make install

「chownはなんのため?」と思われるでしょうが、tarボールを解凍したらパーミッションが501.gamesになっていて触れなかったのでcentosユーザーに変えました。なんでこうなったのかは知らんのですが、同じホストでPython3.5.2のソースコードをDLして試したらパーミッションはcentos.centosだったので、tarした環境の問題なんじゃないかと。

makeとmake installで30分以上待ちました。テストですごい時間かかってた。t2.microだったからなんだろうけど、3.5のころはここまで時間かかんなかった気がするんだよなぁ。

で、このまま起動しようとするとライブラリがみえないっていって怒られるので

sudo vi /etc/ld.so.conf

「/usr/local/lib」を追記

sudo /sbin/ldconfig
$ /usr/local/bin/python3
Python 3.6.0 (default, Dec 31 2016, 00:18:38)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-11)] on linux
Type "help", "copyright", "credits" or "license" for more information.

無事起動しました。

デフォルトのpythonを置き換えることはしなくて、併存です。どうせvenv使うんだし、それで十分です。最近はpyenv使う人が多いのかもしれないけど、標準でインストールされるvenvで十分なのであれこれインストールしたりはしません。

最近GCPが話題になっていて、AWSよりずっと安いっていう話も聞くんですけど、別にAWSにそんなに不満もないのでまだしばらくはAWS使おうかなと。

「Pokemon」で検索しても「Pokémon」がヒットするようにしよう

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

ふと気がつくと前回ブログ書いたのが5か月前という有様。安心してください、生きてますよ。

éとか、英字の上につくダッシュみたいな記号、アクセント記号って呼び方してましたけどダイアクリティカルマークっていうのが正しいんですね。

日本語の場合あんまり気にしないけど、海外のブランド名にもダイアクリティカルマーク付いてるの多いですよね。

例えばelasticsearchの公式にサンプルとして置いてある英語のアナライザーだと「Pokémon」は「Pokemon」で検索してもヒットしません。Solrも同様です。

まあ同義語展開しておけば済むんですけど、大量にある商品名とかブランド名の同義語をメンテするのとか気が遠くなるのでそれは避けたい。

で、elasticsearchにはちゃんとフィルターが用意されていて、前述のアナライザーに追記するだけでOK。

"filter": [
  "english_possessive_stemmer",
  "lowercase",
  "english_stop",
  "english_keywords",
  "english_stemmer",
  "asciifolding"
]

順番は最後で平気なはず。たぶん。
これでちゃんとヒットするようになりましたとさ。

当たり前ですが、Solrにもちゃんと同様のフィルターが用意されてます。ありがたい。

ASCII文字の置換してるだけみたいだけど、他の文字列に影響与えないか要検証。怖い怖い。

Pythonでitertoolsを使ってパラメータの総当り

2016-06-28
このエントリーをはてなブックマークに追加
import itertools

_x = ['0', '1', '2']
_y = ['a', 'b', 'c']

for _i, _j in itertools.product(_x, _y):
	print(_i, _j)

パラメータAには複数のパターン、パラメータBにも複数のパターン。それらの総当りパターンを出力したいっていう時に便利。

0 a
0 b
0 c
1 a
1 b
1 c
2 a
2 b
2 c
Tags:

scikit-learnのTfidfVectorizerで単語ごとのスコアを取得する

2016-06-17
このエントリーをはてなブックマークに追加
from sklearn.feature_extraction.text import TfidfVectorizer


def main():
    _docs = [
        'A friend to all is a friend to none.',
        'One good turn deserves another.',
        'He who runs after two hares will catch neither.',
        'It’s no use crying over spilt milk.',
        'Time and tide wait for no man.',
    ]

    _v = TfidfVectorizer(analyzer=text_split)
    _score =_v.fit_transform(_docs)

    print(_score.toarray())
    print(_v.get_feature_names())

def text_split(val):
    return val.split(' ')

if __name__ == '__main__':
    main()

$ python tf.py
[[ 0.2773501   0.          0.          0.          0.          0.2773501
   0.          0.2773501   0.          0.          0.          0.          0.
   0.          0.5547002   0.          0.          0.2773501   0.          0.
   0.          0.          0.2773501   0.          0.          0.          0.
   0.5547002   0.          0.          0.          0.          0.          0.        ]
 [ 0.          0.          0.          0.4472136   0.          0.          0.
   0.          0.          0.4472136   0.          0.          0.4472136
   0.          0.          0.4472136   0.          0.          0.          0.
   0.          0.          0.          0.          0.          0.          0.
   0.          0.4472136   0.          0.          0.          0.          0.        ]
 [ 0.          0.33333333  0.          0.          0.          0.
   0.33333333  0.          0.          0.          0.33333333  0.          0.
   0.          0.          0.          0.33333333  0.          0.          0.
   0.33333333  0.          0.          0.          0.33333333  0.          0.
   0.          0.          0.33333333  0.          0.          0.33333333
   0.33333333]
 [ 0.          0.          0.38775666  0.          0.          0.          0.
   0.          0.          0.          0.          0.38775666  0.          0.
   0.          0.          0.          0.          0.          0.38775666
   0.          0.31283963  0.          0.38775666  0.          0.38775666
   0.          0.          0.          0.          0.38775666  0.          0.
   0.        ]
 [ 0.          0.          0.          0.          0.38775666  0.          0.
   0.          0.38775666  0.          0.          0.          0.
   0.38775666  0.          0.          0.          0.          0.38775666
   0.          0.          0.31283963  0.          0.          0.          0.
   0.38775666  0.          0.          0.          0.          0.38775666
   0.          0.        ]]

[‘A’, ‘He’, ‘It’s’, ‘One’, ‘Time’, ‘a’, ‘after’, ‘all’, ‘and’, ‘another.’, ‘catch’, ‘crying’, ‘deserves’, ‘for’, ‘friend’, ‘good’, ‘hares’, ‘is’, ‘man.’, ‘milk.’, ‘neither.’, ‘no’, ‘none.’, ‘over’, ‘runs’, ‘spilt’, ‘tide’, ‘to’, ‘turn’, ‘two’, ‘use’, ‘wait’, ‘who’, ‘will’]

Pythonで標準偏差と偏差値を求めてみる

2016-04-04
このエントリーをはてなブックマークに追加
import numpy as np


def main():

    _v = np.array([35, 40, 45, 50, 100])

    _avg = np.average(_v)
    _std = np.std(_v)
    print(_avg, _std)

    _std_score = (((_v - _avg) * 10) / _std) + 50
    print(_std_score)

if __name__ == "__main__":

    # 偏差値@Wikipedia
    main()
54.0 23.5372045919
[ 41.92767352  44.05196996  46.1762664   48.30056285  69.54352728]

なんで標準偏差は関数があるのに偏差値はないんだろう。
あと、なんで偏差値は50を足すんだろう。0を中央にしてもいいと思うんだ。
学生向けに使うことが多い値だからマイナスというネガティブな値にマッピングされるされるのを避けたのかな。

Pythonのscikit-learnでグリッドサーチを使ってSVMのパラメータチューニングをしよう

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

SVMはパラメータが多すぎる。全部試すとか手間が掛かり過ぎる。
そんな悩みを解決したいグリッドサーチの使い方です。

from sklearn.svm import SVC
from sklearn.grid_search import GridSearchCV


def main():
    _s = GridSearchCV(
            SVC(),
            {
                "C": [0.1, 0.5, 1.0, 1.5],
                "kernel": ["rbf", "linear"],
                "gamma": [1, 1e-2, 1e-3, 1e-4],
            }
    )
    _s.fit(
        [
            [1, 0, 0, 0, 0],
            [1, 1, 0, 0, 0],
            [1, 1, 0, 0, 1],
            [0, 1, 1, 1, 1],
            [0, 0, 0, 1, 1],
            [0, 0, 1, 1, 1],
            [0, 0, 1, 1, 1]
        ],
        [1, 1, 1, 0, 0, 0, 0]
    )

    print(_s.best_estimator_)
    print(_s.best_score_)

if __name__ == "__main__":
    main()

上のコードだとCとカーネルとガンマだけを設定してますけど、SVCで指定できるパラメータは全部設定できます。

出力のところは見やすいように成形してます。便利すぎる。。。
全部のパラメータを1回で指定できるわけでもなくて、併用できないものは途中でエラー吐いたりもします。それでも、かなり実施回数は減らせます。

$ python grid.py
SVC(
    C=0.5,
    cache_size=200,
    class_weight=None,
    coef0=0.0,
    degree=3,
    gamma=1,
    kernel='linear',
    max_iter=-1,
    probability=False,
    random_state=None,
    shrinking=True,
    tol=0.001,
    verbose=False
)
1.0

Pythonでscikit-learnを使ってSVMによる分類

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

SVMなので二値分類です。多値分類でもSVMを使うこともありますが、あれは二値分類の繰り返しなのでやっぱりSVMを使うのであれば二値分類なんだろうなぁと思います。

LinearSVC、線形カーネルのサンプルです。相変わらずこんなに簡単にできるPythonってすごいって感心しちゃう。

from sklearn.svm import LinearSVC


def main():

    _training = [
        [0, 1, 0],
        [0, 0, 0]
    ]
    _estimator = LinearSVC()
    _estimator.fit(_training, [1, 0])

    _prediction = _estimator.predict([0, 1, 1])
    print(_prediction)

if __name__ == "__main__":
    main()
$ python sample.py
[1]

無事、1と分類されました。