技術をかじる猫

適当に気になった技術や言語、思ったこと考えた事など。

データサイエンスの育成講座(3)

東京大学のデータサイエンティスト育成講座 ~Pythonで手を動かして学ぶデ―タ分析~

東京大学のデータサイエンティスト育成講座 ~Pythonで手を動かして学ぶデ―タ分析~

# データ解析、機械学習系
import numpy as np
import numpy.random as random
import scipy as sp
import pandas as pd
from pandas import Series, DataFrame

%precision 3
'%.3f'

Pandas

代表的なデータ構造の Series から。
ラベルとかの情報を含む配列みたいな感じと認識。

データ型

sample_data = pd.Series([ 0, 10, 20, 30, 40, 50, 60, 70, 80, 90 ])
print(sample_data)
0     0
1    10
2    20
3    30
4    40
5    50
6    60
7    70
8    80
9    90
dtype: int64
sample_indexed_data = pd.Series(
    [0, 10, 20, 30, 40, 50, 60, 70, 80, 90],
    index=['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']
)
sample_indexed_data
a     0
b    10
c    20
d    30
e    40
f    50
g    60
h    70
i    80
j    90
dtype: int64
続きを読む

データサイエンスの育成講座(2)

東京大学のデータサイエンティスト育成講座 ~Pythonで手を動かして学ぶデ―タ分析~

東京大学のデータサイエンティスト育成講座 ~Pythonで手を動かして学ぶデ―タ分析~

と、続きでやってる。
jupiter-notebook があればいい。

一応色々端折る為に anaconda で作成。

# データ解析、機械学習系
import numpy as np
import numpy.random as random
import scipy as sp
import pandas as pd
from pandas import Series, DataFrame

# 可視化系
import matplotlib.pyplot as plt
import matplotlib as mpl
import seaborn as sns

%matplotlib inline
%precision 3
'%.3f'

Scipy

# Library of linear algebra
import scipy.linalg as linalg
matrix = np.array([[1, -1, -1], [-1, 1, -1], [-1, -1, 1]])
print(f'行列式 : {linalg.det(matrix)}')
行列式 : -4.0
inv_matrix = linalg.inv(matrix)
print(f'逆行列 :\n{inv_matrix}')
print(f'Dot積 : \n{ matrix.dot(inv_matrix) }')
逆行列 :
[[ 0.  -0.5 -0.5]
 [-0.5 -0.  -0.5]
 [-0.5 -0.5  0. ]]
Dot積 : 
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]
eig_value, eig_vector = linalg.eig(matrix)
print(f'固有値 : \n{eig_value}')
print(f'固有ベクトル : \n{eig_vector}')
固有値 : 
[-1.+0.j  2.+0.j  2.+0.j]
固有ベクトル : 
[[ 0.577 -0.816  0.428]
 [ 0.577  0.408 -0.816]
 [ 0.577  0.408  0.389]]
続きを読む

暫く積んでた本の着手

Kaggle やり始めて撃沈して、ちまちま勉強していたけど、そもそも基礎がなってない気がしてそれっぽい物を探した痕跡。
最近までずっと Salesforce で Trail 祭りしてたからなぁ(汗

東京大学のデータサイエンティスト育成講座 ~Pythonで手を動かして学ぶデ―タ分析~

東京大学のデータサイエンティスト育成講座 ~Pythonで手を動かして学ぶデ―タ分析~

利用する系のライブラリ

# データ解析、機械学習系
import numpy as np
import numpy.random as random
import scipy as sp
import pandas as pd
from pandas import Series, DataFrame

# 可視化系
import matplotlib.pyplot as plt
import matplotlib as mpl
import seaborn as sns

%matplotlib inline
%precision 3
'%.3f'

マジックコマンド

jupiter notebook の機能群

  • %run 外部コマンドの実行
  • %cp ファイルのコピー
  • %time 時間の計測
  • %precision numpy 拡張。表示する場合の有効桁数を指定する。
  • %matplotlib Matplotlib 拡張。グラフなどの表示法を設定できる。inline など。
  • %quickref コマンドの一覧表示など

numpy 近辺

# use array.
example_array = np.array([1, 4,  8, 16, 6, 8, 1, 5])

# tab key on after dot(.) to code complete
example_array.dtype
dtype('int64')
続きを読む

アプリからドライバまで 現役エンジニアの濃い話

sciencepark.connpass.com

gitその2 rebaseとrebase -iを理解してgit-flowをやりやすくする :サイエンスパーク

author: 須藤さん

www.slideshare.net

前回、gitsvn の違いから始まって、git-flow のモデルまで説明されました。
今回は git-flow の流れの続き。
rebase + rebase -i についての話です。

ざっくりまとめると以下の機能があります。

  1. rebase 指定したバージョンを元にコミット差分を乗せ直す機能です。
    コミット履歴を見れば非常にわかりやすいですが、ブランチマージと異なっていて、コミットや修正の履歴が直列になります。
  2. rebase -i はバージョンを指定して、履歴を操作する…という意味合いまでは一緒ですが、こちらはコミット履歴の統廃合することができます。
    これによって、任意のタイミングでコミットしても後から整形すればいいという使い方ができます。

rebase -i (コミット範囲) をすると、コミットログの一覧が出る。
これを編集して、git rebase continue すると、コミットログが綺麗にまとまる。

なぜこれらが必要なのかというと、github でプルリクエストをする時に、マージだと更新履歴がまともに見えないので論外。rebase は必須としても、履歴が汚れている場合は rebase -i をした方がいいというお話です。

内容的には初級向けの印象でした。
rebase -i 久々に見ました…自分一人でやってるとコミット履歴気にしないもんなぁ(汗

Scikit-learnで機械学習系の何か

author: 安原

機械学習とAI の言葉の範囲が異なるというところから始まり、機械学習にも様々な種類があるというお話から始まりました。
そこから、決定木と、ランダムフォレストの説明につながりました。

  • 決定木: 与えられた情報を「XX が YY 以上なら…」という様にしてデータを判断するツリーを決定木と言います。
  • ランダムフォレスト: 決定木を学習データをランダム振り分けで学習させ、しかもそれを複数本用意するアルゴリズム
    こうした複数の学習機を利用して多数決で決定する様なアルゴリズムをアンサンブル学習と言います。

こちらも機械学習初級向けの内容とは思います。
決定木が学習する過程で条件を学習選択するアルゴリズムなどに関して突っ込んだら 絶対深かった 多分収集つかなくなった(汗

マインドフルネス

www.slideshare.net

今この瞬間に意識を傾けて物を考えるという方法。
集中力アップのほか、ストレス軽減の効果がある。

マインドフルネス瞑想!

  1. 力を抜いて楽にする
  2. 目を閉じます
  3. 鼻から深呼吸します
  4. 呼吸を数回繰り返します
  5. キリがいいくらい(5分位)その状態を維持します

変に何か感じたら、呼吸に意識を傾けることで頭をリセットします。
これを知ってると気分のリセットなどには実に有用です。

唯一のライフハック系のお話!
これ系は勉強会で出てくることは滅多にないので貴重です(^_^;)

Kubernetesの勉強がてら勉強会

参加してきたのは以下。

SpringBootでマイクロサービスを作ってKubernetesにデプロイしてみる【実践編】 dreamarts.connpass.com

尚、当日資料は下記。

github.com

K8S とは?

コンテナオーケストレーション技術。
コンテナオーケストレーションは、

  • コンテナが落ちた時に自動でコンテナを用意してアップしてくれる
  • 新しいバージョンリリースの時には「新しいコンテナを作って新版デプロイ」「接続設定を新版に切り替え」「旧版コンテナの削除」を順次行ってくれる

要するにバックのサービス云々を意識せすに、サービス維持を自動化してもらうツールと言える。

特徴として

  • Declarative 宣言的
  • Immutable 固定化
  • AutoHealing 自己修復的

この特徴のおかげで、「致命的エラーが出た?新しいコンテナ作ればいいやん」という状況が生まれる。
ただし、このアーキテクチャを採用する場合

  • サーバサイドにセッション情報を保持する作りは崩壊する。
    • つまりステートレスサーバを作らなければならない(破棄前提)

個人的な意見だと Playframework でやればおk!

K8s の構成

基本的に

  • kubectl
    コントロールサーバ。ここから K8s
  • kube-apiserver
    kubectl からリクエストを受ける部分。
    こいつが kube-scheduler に処理を移譲する
  • kube-scheduler
    apiserver で受けた内容を元に、Pod を操作する部分。
  • Kubelet
    Podを起動し管理するエージェント
  • Pod
    コンテナ本体

という構成とのこと。

Docker

カーネルレベルの機能としてプロセスを分離し、そこで Ubuntuなどの様なコマンドセットを用意することで、それぞれのディストリビューションとして振る舞う。
という様なお話。

すみません、自分で調べてたので聞き流してしまいました(汗

Docker 周りはこの辺聞けばいいと思う。

11. dockerネットワーキングとか、kubernetesネットワーキングとか | Fukabori.fm

いまさらDockerに入門したので分かりやすくまとめます - Qiita

Flask 1.0.2 入門してみた

見通しよく、REST API を書きたいと思ったのだけど、Flask-restful がなんともしっかりした REST 特化しすぎてて微妙だったので、Flask 単品でちょっと実験したメモ

Install といっても…

Python だとこれだけ。

$ pip install Flask

ルーティング機構

と言っても非常にみたまま素直な感じ。
とてもわかりやすくてよい。

from flask import Flask, request

app = Flask(__name__)

@app.route('/seminers', methods=['GET', 'POST'])
def seminers():
    print(request)
    print(request.data)
    print(request.form)
    print(request.args)
    return 'Example message'

app.run(debug = True, port = 3000)

リクエスト等の受け取り

で、どうなるのか気になったのがここなので、色々上記に流し込んで試してみた。

まずは単純リクエス

$  curl http://localhost:3000/seminers

実行結果…まぁそうね。
null になってないあたり個人的に好き

<Request 'http://localhost:3000/seminers' [GET]>
b''
ImmutableMultiDict([])
ImmutableMultiDict([])

URL パラメータ突っ込むと

$ curl http://localhost:3000/seminers?welcome=data

args が反応する

<Request 'http://localhost:3000/seminers?welcome=data' [GET]>
b''
ImmutableMultiDict([])
ImmutableMultiDict([('welcome', 'data')])

今度は Form POST

$ curl -F "key=value" -F "msg=ひゃっはー"  http://localhost:3000/seminers

request.form が反応

<Request 'http://localhost:3000/seminers' [POST]>
b''
ImmutableMultiDict([('key', 'value'), ('msg', 'ひゃっはー')])
ImmutableMultiDict([])

ファイルを送信してみる。適当に ss.png ファイルをキャプチャで作って食わせた

$ curl -F "key=value" -F "file=@ss.png" http://localhost:3000/seminers

えーっと(汗

<Request 'http://localhost:3000/seminers' [POST]>
b''
ImmutableMultiDict([('key', 'value')])
ImmutableMultiDict([])

調べてみたら files フィールドに格納されるらしい

@app.route('/seminers', methods=['GET', 'POST'])
def seminers():
    print(request)
    print(request.data)
    print(request.files)
    print(request.form)
    print(request.args)
    return 'Example message'

書き換えたリトライ。
でたでた。form/maltipart-formdata の区別は自動でやってくれてるらしい。

<Request 'http://localhost:3000/seminers' [POST]>
b''
ImmutableMultiDict([('file', <FileStorage: 'ss.png' ('application/octet-stream')>)])
ImmutableMultiDict([('key', 'value')])
ImmutableMultiDict([])

なら、JSON はどうだろう?

$ curl -H 'Content-Type:application/json' -d "{"key":"val","key2":",val2"}" http://localhost:3000/seminers

ここにきて data が反応。
application/json にはデフォルトでは対応していない模様。

<Request 'http://localhost:3000/seminers' [POST]>
b'{key:val,key2:,val2}'
ImmutableMultiDict([])
ImmutableMultiDict([])
ImmutableMultiDict([])

json パッケージとか使えばどうとでもなりそう。

import json

@app.route('/seminers', methods=['GET', 'POST'])
def seminers():
    print(request)
    print(request.data)
    print(request.files)
    print(request.form)
    print(request.args)
    if request.headers['Content-Type'] == 'application/json':
        json_value = json.loads(request.data)
        print(json_value)
    return 'Example message'

そして投げ直す

$ curl -H 'Content-Type:application/json' -d "{\"key\":\"val\",\"key2\":\"val2\"}" http://localhost:3000/seminers

うまく行ったけど、あまりにダサい。
if とか腹立たしいのだけど…

<Request 'http://localhost:3000/seminers' [POST]>
b'{"key":"val","key2":"val2"}'
ImmutableMultiDict([])
ImmutableMultiDict([])
ImmutableMultiDict([])
{'key': 'val', 'key2': 'val2'}

application/json にしか公開しないとかねーのかと思ったのだけど、

flask.pocoo.org

まぁこういう振り分けこそコントローラの仕事だし仕方ないのか(汗

Pandas の練習がてら、勉強会のトレンドを探ってみた

この辺の続きです。

white-azalea.hatenablog.jp

4月の勉強会の開催状況と、事前申し込みの状況を眺めてみたが正解。

勉強会情報を拾ってくる

前回の流れですが、2サイト以上でやるので、少しだけ汎用化を考えてみた。
調べてみたら、ATND と COMPASSAPI仕様がほぼ同一だった。

まずは共通の定義を用意して

import requests
import sys

class ClassRoom:
    def __init__(self, title, limit, accepted, waiting):
        def or_zero(v):
            if isinstance(v, int):
                return v
            return 0
        self.title = title
        self.limit = or_zero(limit)
        self.joins = or_zero(accepted) + or_zero(waiting)

    def __str__(self):
        return f'ClassRoom({self.title}, {self.limit}, {self.joins})'


class ClassRoomLoader:
    def load_class_rooms(self, month: str) -> list:
        pass


class AbstractCompassAtnd(ClassRoomLoader):
    def __init__(self, api_url: str, max_event_num: int):
        self.api_url = api_url
        self.max_event_num = max_event_num


    def create_request_parameter(self, target_month: str, top: int):
        return {"ym": target_month, "count": self.max_event_num, "format": "json", "start": top}


    def request_to_compass(self, target_month: str, top: int) -> requests.Response:
        params = self.create_request_parameter(target_month, top)
        query = '&'.join([f'{key}={params[key]}' for key in params.keys()])
        print(f'Request: {self.api_url}?{query}')
        return requests.get(self.api_url + '?' + query)


    def convert(self, event) -> ClassRoom:
        try:
            return ClassRoom(event['title'], event['limit'], event['accepted'], event['waiting'])
        except:
            print(f'Error: {sys.exc_info()[0]}')
            print(f'Value: {event}')
            raise Exception('Cannot convert')


    def load_request(self, target_month: str, top: int):
        class_rooms = []
        r_get = self.request_to_compass(target_month, top)
        print(r_get.status_code)

        respond_json = r_get.json()

        for ev in respond_json['events']:
            class_rooms.append(self.convert(ev))

        return (respond_json['results_returned'], class_rooms)


    def load_class_rooms(self, month: str) -> list:
        getted = self.max_event_num
        current_top = 1
        class_rooms = []
        request = 0

        while getted == self.max_event_num:  # 最大数以下が返ってきている == まだ次がある
            request += 1

            getted, tmp_rooms = self.load_request(month, current_top)
            current_top += self.max_event_num
            class_rooms.extend(tmp_rooms)

            print(
                f'Request: {request}, Return: {getted}, currentTop: {current_top}')

        return class_rooms

単純に読み込む。
尚、読み取った勉強会情報は、pickle でダンプしておく。

class AtndLoader(AbstractCompassAtnd):
    COMPASS_API = 'http://api.atnd.org/events/'
    WANT_EVENT_NUM = 100

    def __init__(self):
        super().__init__(AtndLoader.COMPASS_API, AtndLoader.WANT_EVENT_NUM)

    def convert(self, event) -> ClassRoom:
        return super().convert(event['event'])

    def create_request_parameter(self, target_month: str, top: int):
        return {"ym": target_month, "count": self.max_event_num, "format": "json", "start": top}



class CompassLoader(AbstractCompassAtnd):
    COMPASS_API = 'https://connpass.com/api/v1/event/'
    WANT_EVENT_NUM = 100

    def __init__(self):
        super().__init__(CompassLoader.COMPASS_API, CompassLoader.WANT_EVENT_NUM)

    def create_request_parameter(self, target_month: str, top: int):
        return {"ym": target_month, "count": self.max_event_num, "order": 1, "start": top}

# import pickle for backup dump.
import pickle
if __name__ == "__main__":
    class_rooms = AtndLoader().load_class_rooms("201904")
    class_rooms.extend(CompassLoader().load_class_rooms("201904"))
    with open('backup.pickle', 'wb') as f:
        pickle.dump(class_rooms, f)
    print("\n".join([str(s) for s in class_rooms]))
続きを読む