あゝお腹いっぱい、次なに食べよ

機械学習とかAWSとかiPadProとかGalaxynote8とか

S3のCSVファイルを Parquetに 変換する

お疲れ様です、sysopjpです 掲題の 毎分あがってくるCSVをちまちま parquetにするやつになります

import pyarrow as pa

import pyarrow.parquet as pq

import pandas as pd


def lambda_handler(event, context):
    bucket = event['bucket']
    key = event['key']
    s3path = 's3://{0}/{1}'.format(bucket, key)
    df = pd.read_csv(s3path,
                         names=['idx','col','umn'], dtype=str)
        table = pa.Table.from_pandas(df)
        # Arrow Table -> Parquet
        tmpfilename = '/tmp/{0}'.format(key)
        pq.write_table(table, tmpfilename, compression='gzip')
        s3.upload_file(tmpfilename, 'mybucket', key)

S3 の event からこのLambdaが呼ばれるようにしておきます
ちなみに、S3の伝搬が終わっておらず

よくfile not found するので DLQで
リトライできるように適当に組み込んでおいてください。

自分は SQSにいれて リトライ組み込んでます

Linux on Android with Galaxy note8 DeXmode

お疲れ様です、sysopjpです  

まずはこちらをごらんください。
 
 

 
お気づきだろうか?

f:id:sysop:20181002200832j:plain

 
そう、実はこれ、 android8.0上でUbuntu18.04が動いているのです
そしてはい!こちら!! 

f:id:sysop:20181002200046j:plain

 
スマホ上で pandas 動いてますね  
やばい Pythonista ついにお払い箱になった。。。  
あ、ちなみにデスクトップモードっぽいのは SC01k DeXモードです  
接続の全体像を見せるとこんな感じ。  
 

 木箱のなかにDeXにするためのUSB-C2HDMIが入っています
モニタ下のやつはスピーカー
今日は、この Ubuntu on Galaxynote8 の解説になります。  
あ、別にDeXモードじゃなくても動きますので 解説はスマホ画面でいきますね  
なお、Androidのサンドボックス内で動作するのでrootは不要ですが、利用するアプリが安定版ではないため自己責任でお願いします。  
sysopjpは、SC01kがおもちゃで、メインは iPhoneSEiPadProなので そこんとこよろしく。

 使うアプリ

気になる人は  
あたりみるといいんじゃないですかね。  Kotlin で開発されてるみたいです  

 必要時間

起動するだけなら 30分くらい  
pandasとか aws コマンド動かせるようになるまでは半日くらいかな?  apt-get install とか pip install pandas にむっちゃ時間かかるので  
Netflix とか amazonプライムとか用意しとくといいですよ  

実際にやってみる

では、実際にandroid上に Linux環境を構築してみましょう。「UserLAnd」を起動します。
 

 
右上の + から CreateNewすると Filesystemをdebianにするか Ubuntuにするか聞かれるので好きな方選んでください。
あと 名称つけましょう

作ったやつをクリックすると Settingがはじまります。
まあまあ 長いです、5分くらいかな、この間に  

アマゾンプライムとかNetflix でみるアニメ選ぶといいですよ  
今だとからくりサーカスの前に うしおととら 履修するとかもオススメですね!!!  
 
 

はい、勝手にConnectBotが立ち上がりましたね  
パスワードは userland です。  
あとは なんていうかまあ、普通の ubuntu なので
 
sudo apt-get update 
sudo apt-get upgrade 
sudo apt-get install -y build-essential python-dev  
 

 

などで必要なものをいれてください。
vim  でも git でも pythonでも aws 好きなものが入ります。  
っていうか pandas が動きます。大事なことなので二回書きますが
スマホ Galaxynote8 SC04k上で pandas が動きます。

f:id:sysop:20181002200435j:plain

 
あ、でもさすがに Dockerは動かなかったですね。  
 
以上、よろしくお願いします。

iPadのPythonista3でgit に草を生やす方が楽な気がしてきた

お疲れ様です、sysopjpです

掲題の通り
Pythonista on iPad から git clone とか git push とかしてみました

以下方法になります

Stash を起動 して ssh key 作成

そもそも Stash ってなんやねん? って人は以下の過去記事を見てください → iPadでStashの設定の仕方

$ ssh-keygen -t rsa -b 2048

気を取り直して ssh-keygen
すごくね? これだけで感動しますよね

Git にSSH をコピー

$ cat ~/.ssh/id_rsa.pub

表示されたデータをコピペして

https://github.com/settings/ssh

の NewSSH で 表示される画面にコピペ

git clone

stash で適当なディレクトリを作成し

git clone git@github.com:sysopjp/ipadPythonistaTest.git hoge

git add

$ git add .
Adding .
stash: <type 'exceptions.IOError'>: [Errno 21] Is a directory: '/private/var/mobile/Containers/Shared/AppGroup/169D4EC9-49B2-4BC3-BD8E-E6B96A7F85EB/Pythonista3/Documents/hoge/.'

およ?だめなのか?

$ git add README.md 
Adding README.md

ファイル指定しないといけないの、だいぶ面倒な気がする

git commit

[hoge]$ git commit -m '1st commit'
usage: Commit current working tree. [-h] [message] [name] [email]
Commit current working tree.: error: unrecognized arguments: -m

, もだめなんかい

[hoge]$ git commit 
Commit Message: 1st commit
Author Name: sysopjp
Save this setting? [y/n]y
Author Email: git@sysop.jp
Save this setting? [y/n]y
3d38b653ebe4c08e14edb1eeddd62f566853a755
[hoge]$ 

author とかそのあたりは二度目以降聞かれません

git push

stash$ git push
Attempting to push to: git@github.com:sysopjp/ipadPythonistaTest.git, branch: refs/heads/master
Enter username: username
Enter password: password
Push to git@github.com:sysopjp/ipadPythonistaTest.git successful.
success!

できました! QED!!

以上よろしくお願いします

深層学習と機械学習とパーセプトロンと周辺用語

お疲れ様です、sysopjpです tensorflowさっぱりわからないので 基礎的なところを履修してみました。 その共有になります。

まくら

過去産業革命とか、IT革命とかありましたが
今はAI革命の時代ですね

なんとか革命の後には、一般人が気軽に使えるようになり
"すこし"詳しい人が、なんとか革命で出来たものを
お守り(おもり)する仕事が大量に出ます

産業革命以後はモーターのお守り、自動車修理工場とか今でもたくさんありますね
IT革命以後は、サーバーのお守りする仕事、たくさん出ましたね、僕も3K時代のIT土方出身です。
つまりAI革命以後、大量に生まれる仕事は、AIのお守りです。

学術的どうこうは興味がないので
今の運用保守みたいな形にAIの仕事を落としこむには
どうしたらいいかなー、そんな事考えて自分は生きてますよ

え?こも? こも?こもでぃてぃ? あーなんかそんなんだと思いますハイ

対象の人

ディープラーニングに興味があるけどまだ何もした事がない人
数式見るとそっ閉じする人、つまり俺の事だ

対象外の人

微分積分行列計算などの数式がわかる人、すまぬ俺がわからないから解説できません、ちゃんと読める人のページ見て
AND回路といわれてわからないひと
python触ったことがない人、ごめんノンプログラマー向けの解説ではないんだ

勉強会所要時間

1万文字くらい書いたので
合計 1時間くらい用意してください
時間だけは、偉い人にもすごい人にも凡人にも平等に配布されてますから
僕ら凡人も一時間くらいは供出しましょう。
あと、python のプログラムは存在してるので
jupyter ノートブックに numpy いれるくらいは用意してください
VSCode on jupyte とか僕はおすすめ
過去記事あるから見てみて VSCodeOnJupterちょうべんり

歴史とかそこらへんの話

まずディープラーニングに至るまでに
3つの世界をたどる必要があります

  1. パーセプトロン
  2. ニューラルネットワーク
  3. ディープラーニング

歴史的にもパーセプトロンがすべての元になっており
Tensorflow の勉強をすると出てくる
活性化関数とか重みとか変数とか
パーセプトロンに出てきます
逆に言うとパーセプトロンを勉強する前に
ディープラーニングに、というかTensorflowに触れると
意味のわからない単語の羅列に殺されてしまうので
まずは パーセプトロンを勉強しましょう。

パラメーターとか基礎用語

単純なデータとして
身長体重の肉体データと年齢を入れると
(生まれた時点の肉体的な)男女を判断する分類器を想像してみます

入力値が 身長
体重
年齢

出力が
男性 (1)
女性 (0)
とします

一人目の方
田中太郎さん 男性
身長 x1 170
体重 x2 70
年齢 x3 30

この値を全部足し算します
170+70+30 = 270 ですね。

ここで 一つの仮説を立てます

仮説1 "全部足し算して 270未満は女性 "

では次の方見てみましょう

鈴木花子さん 女性
身長 140
体重 40
年齢 100

仮説1によれば 全部足し算して 270未満なら 女性ですが
これは 全部足して280なのに 女性です
よって、先ほどの仮説は否定されました。

ここで、「重み」という概念を持ち込みます
重みとは「重要度」の事です
この値は重要、この値は結果に対して影響が少ない
などを表す「変数」です。

私たち人間なら知ってるのでわかりますが
年齢は 男女の計算にあまり影響しません。
ここで年齢に対して 重要度 1% としてみます。

ついでに 身長と体重も それぞれ重みをつけて
身長の重要度80%、体重の重要度40%ぐらいにしてみます。

田中太郎さん
170x0.8+700.4+300.01 = 164.3

鈴木花子さん
140x0.8+400.4+1000.01 = 129

この重みの場合
全部足し算して 164以下は女性

という仮説が立てられます。

また、130以下は女性、という仮説も立てられます。

この重みと閾値を調整することで、正解が出しやすい値を求める
これが基本的な動きです。

この「重み」の事を「変数」パラメーター と呼びます

そして、閾値z以上は男性、閾値z未満は女性と判定することを
「発火」と呼びます
閾値zを 上回ると"発火"して男性と判断する、この閾値zを「バイアス」と呼びます。

また入力値、今回であれば 身長体重年齢の事を
ベクトルとかサンプルとかエンティティと呼びますが、
自分は一番簡単な呼び方であるXで呼んでます
そして出力のことを Yと呼びます。

パーセプトロンを作ってみよう

計算を単純にするため まずは AND回路を作ってみます

def AND(x1, x2):  
    w1 = 1 # x1の重み  
    w2 = 1 # x2の重み
    t = 1 # 発火点
    tmp = x1 * w1 + x2 * w2
    if tmp > t: # 発火
        return 1
    return 0
AND(0,0)
AND(0,1)
AND(1,0)
AND(1,1)

これの結果は 上から 0,0,0,1 です 図にすると下記の通り

0,0 は 0なので ❌
0.1 も 0なので❌
1,0 も 0なので❌
1,1 だけ 1 なので ⭕️

線がバイアス、発火点です
図を見ると
発火点は 1を超えて 2以下であれば どこでもいいのがわかりますね
実際にやって数値変えてみるとわかります
発火点1を超えて2未満にしてみてください

さて、これを 先ほどの身長体重に置き換えてみます
x1 が身長、x2が体重、x3が年齢
結果は 1が男性、0が女性にしましょう

田中太郎さん
身長170cm
体重70kg
年齢 30
男性 1

鈴木花子さん
身長 140cm
体重 40kg
年齢 100
女性 0

少しデータを増やして

斎藤二郎さん
身長165cm
体重60kg
年齢 50
男性 1

安藤貴子さん
身長156cm
体重 50kg
年齢 25
女性 0

重みが 身長80% 体重40% 年齢 1%、発火点が164でしたね

def SEIBETU(x1, x2, x3):
    w1 = 0.8 # 身長の重み
    w2 = 0.4 # 体重の重み
    w3 = 0.01 # 年齢の重み
    t = 164 # 発火点

    tmp = x1 * w1 + x2 * w2 + x3 * w3
    if tmp >= t: # 発火
        return 1
    return 0

さて、発火点や重みを修正して

SEIBETU(170,70,30) = 1
SEIBETU(140,40,100) = 0
SEIBETU(165,60,50) = 1
SEIBETU(156,50,25) = 0

こういう結果が出るように調整してみましょう

できましたか? お疲れ様でした。 今やった作業をパソコンにやらせる事が機械学習です。

学習

今やった調整をもう少し機械学習らしく しかし(最終的には)間違った手法を手でやってみます

w1 = np.random.random_sample()
w2 = np.random.random_sample()
t = 100

print(w1,w2,t)

> 0.7179794468589052 0.596054692240304 100

まず機械学習では重みの初期値を ランダムで決めます。 重みなんてはじめは、わかりませんからな。

本当は 発火点もランダムで決めるのですが、そこまでやると 手でやるのが面倒なので今回は省略して 100に設定します

今回は身長の重みが 0.71 体重の重みが 0.59 になったようですね。

次に 性別判定関数を修正します

def SEIBETU(x1, x2, y): # yは 欲しい結果
    tmp = x1 * w1 + x2 * w2
    if tmp >= t: # 発火
        if y != 1: # 本当は発火したくなかった
            print(t-tmp) # 差分を表示
        return 1
    if y != 0: # 本当は発火したかった
        print(t-tmp) # 差分を表示
    return 0

引数に正解データの Yを渡します 年齢も複雑になるので消しておきます。

また、はずれた場合は、どれくらい外れたか差分を表示します 早速実行してみましょう

SEIBETU(170,70,1)
> 1

SEIBETU(140,40,0)
> -24.359310249858893
> 1

二人目の人が 男性と判別されてしまいました。
この時、発火点100との差分は 24 ある、と表示されています
各入力値と重みを掛け算して足し込んだ値を
24 減らせば いいわけです。
どうしましょう。
ここで入力値を 24減らせばいい!と思った人
正解ですが間違いです。身長や体重を勝手に24kg落とさせるわけにはいきません

そこで、この入力値を「定数」とも呼びます
逆に修正していいのは重みの部分です
だからここが「変数」「パラメーター」と呼ばれます

重みを修正して、24 ほど減るように考えて見ます

ここで例えば w1 を修正して 24という値がひかれるようにするためには身長 140で割り算します
24/140 つまり 重みが0.17ぐらい減れば
数値は合いそうです
少し多めに切っておくと便利なので 0.18 にします

w1 = w1 - 0.18
SEIBETU(140,40,0)
> 0

うまくいったようですね
続けてやります

SEIBETU(165,60,1)
> 1

SEIBETU(156,50,0)
>  -13.727528322004417
> 1

また女性の判別に失敗しましたね
今度は 13ほど多いようです
先ほどと同じように考えると
13 / 156 = 0.08 なので 0.09 ほど w1 を修正すればいけそうです

w1 = w1 - 0.09
SEIBETU(156,50,0)
> 0

お うまくいきましたね

print(w1,w2,t)
> 0.44797944685890523 0.596054692240304 100

SEIBETU(170,70,1)
> 1

SEIBETU(140,40,0)
> 0

SEIBETU(165,60,1)
> 1

SEIBETU(156,50,0)
> 0

これで できあがりです。

さて、できあがってしまいましたね
本当は w1を減らしすぎて 男性判定に失敗する予定だったんですが
この程度の数字じゃ、そう上手くいかないですね
別の機会にやりましょう。

この重み部分を自動的に機械にやってもらいます
手でやるのが面倒というレベルではなく
深層学習ではパラメーターの数が数万数億になるので
人間の手では無理なレベルになります。

しかしこのレベルになると
上述のような修正では上手くできないことになります
と、いうのも
数億のパラメーターを調整するのに
あたった、はずれた
というトリガーで判定していると、ちょっと飛びすぎなのです
もうちょっと、こう、アナログちっくな滑らかな判定が必要です
僕らは現実世界で「多分男性」とか「多分女性」という
「多分」「おそらく」「だろう運転」の世界で生きています

そこで、当たり外れを 確率で表現することにしました。

「男性の確率 30% 」
みたいな表現をするために損失関数というもの出てきます。

例えば
SEIBETU(170,70,1)
これの返却値が 男性確率 80% = 0.8 女性確率 1%=0.01 だったとしましょう。
内部的にこの場合の損失は
0.2 になります。

返却値が 男性確率 90% = 0.9 女性確率 1%=0.01 だったとしましょう。
この場合損失は 0.1 になります

どちらも、男性とは判定しますが
後者の方が性能が高いのです。

こういう風に性能評価をしていくため
上述のようなやり方はディープラーニングでは使用されません

しかし、2つ程度の値から 2値を出すだけのAIならこれで十分です

胸をはっていいましょう
一つの自動分類器が完成しました

お疲れ様でした。

前半戦終了

後半戦

用語解説とかいきますー

活性化関数

活性化関数には伝統的にロジスティック関数である
シグモイド関数が使われるそうで
最近はReLUが流行りだそうです
ここまでの文章で、はいはいあれな
と思った人は、さすがにもういないと思いますが
もしいたら。ごめんなこんな話読ませて

いやわかんねぇよ、何それ、となった人がこのお話の対象です

まず、活性化関数ですが
なんだそれ、という話になります。

活性化関数は、発火用の関数です
「入力を足し合わせた数が発火点を超えたら発火する」
これです、
なんのこっちゃ?
はいプログラムでみましょう

活性化関数 activator をいれた場合

def activator(tmp):
    t = 164 # 発火点

    if tmp > t:
        return 1
    return 0

def SEIBETU(x1, x2, x3):
    w1 = 0.8 # x1の重み
    w2 = 0.4 # x2の重み
    w3 = 0.01
    return activator( x1 * w1 + x2 * w2 + x3 * w3 )

こうなります

そんだけ?はい単純に活性化関数と呼んだ場合は
そんだけです。

シグモイド ロジスティック ステップ関数 階段関数

さて、先ほどの

def activator(tmp):
    t = 164 # 発火点

    if tmp > t: # 発火
        return 1
    return 0

のような単純な閾値をもつ活性化関数はステップ関数と呼ばれます。

これは単純な 1か0か 2値を返します
しかし、これからやろうとしているニューロンネットワークはもうちょっと
アナログなデータです、濃淡がある、みたいな言い方もしますね

例えば、今日何を食べようと考えるとします
(これ書いてる時間が夜飯時間だったので)
カレーかラーメンかトンカツで悩んだとしましょう

昨日カレーくったから カレーは重みが低くて0 ラーメンかトンカツが活性化して
1だな

こう考えてます?
あー、ごめんもしこう考えてる人いたら、すまんけどちょっと一般的じゃない事自覚して生きてください。

一般的には
カレーは、無しではないけどー 昨日くったしなー
ラーメンって気分でもないし
トンカツ好きだから 躯体けど でも カロリーきになるしなー
そもそも、カロリーの事言い出すと 全部だめだしなー

短く書くと
「無しではないけどありっちゃあり」のような
数字で表すと小数点以下が入ってくる思考をしています。

これを実装するために
入力値を 0、1 だけにしてしまうステップ関数ではなく
小数点以下も 表現できるようにした活性化関数が必要とされたのです。

そこでは
ロジスティック関数と呼ばれる関数が使われるのが一般的になり
伝統的にはシグモイド関数 と呼ばれる関数が使われることになったとさ。
最後の方よくわかんねぇから

はい プログラムは 以下

import math
def sigmoid(x):
    return 1.0 / (1.0 + math.exp(-x))

実数ならどんだけでも 小数点で表せるらしいですが
僕らプログラマーはそんな無茶なことはしてはいけません
float32なら
だいたい40 近くでオーバーフローするので

sigmoid(30.0)
sigmoid(20.0)
sigmoid(10.0)
sigmoid(5.0)
sigmoid(4.0)
sigmoid(3.0)
sigmoid(2.0)
sigmoid(1.0)
sigmoid(0.0)
sigmoid(-1.0)
sigmoid(-2.0)
sigmoid(-3.0)
sigmoid(-4.0)
sigmoid(-5.0)
sigmoid(-10.0)
sigmoid(-20.0)
sigmoid(-30.0)

こんな感じで試してみましょう

結果
——
0.9999999999999065
0.9999999979388463
0.9999546021312976
0.9933071490757153
0.9820137900379085
0.9525741268224334
0.8807970779778823
0.7310585786300049
0.5
0.2689414213699951
0.11920292202211755
0.04742587317756678
0.01798620996209156
0.0066928509242848554
4.5397868702434395e-05
2.0611536181902037e-09
9.357622968839299e-14

まず 0は 0.5 に変換されます
そして、プラス側もマイナス側も
値が大きくなるほど 差分が小さくなりますが 0を突き抜けることはないし
1を突き抜けることもないですね。

これを図にしてみます

以下は、とりあえず写経してみましょう

import numpy as np
import matplotlib.pylab as plt

def sigmoid(x):
    return 1.0 / (1.0 + np.exp(-x))

def step(x):
    return np.array(x>0, dtype=np.int)

x = np.arange(-30.0, 30.0, 0.1)

print('ステップ関数')
y = step(x)
plt.plot(x, y)
plt.ylim(-0.1, 1.1)
plt.show()

print('シグモイドsigumoido関数')
y = sigmoid(x)
plt.plot(x, y)
plt.ylim(-0.1, 1.1)
plt.show()

動かない人は pip install matplotlib をしてください

以下のような図がでましたか?

形が似ているということがわかりますね。
しかし、小数点が使えるから、シグモイドはにょろーんとしていますね
このにょろーんとしてる感じが「ありっちゃありだがやっぱりなし!」
みたいなアナログチックな値を表すことに使えるのです

ベクトル 行列 numpyが便利

上の方で、入力値の事をベクトルとかエンティティとか呼ぶ
という話を書きました
深層学習は、実際のところ行列計算を基本とします

つまり
SEIBETU([170,70,30])

こう入力される事が基本です。
この行列データを活性化関数にかけるとしましょう
コードをちょっと書いてみればわかりますが
list だとfor分が必要になりますね

ここで numpy の登場です
numpy は行列データをひとまとめに扱う事が
得意なライブラリです。

たとえば
[170,70,30]
に全部1を足し算して

171,71,31

という行列を取得したいとします

このとき

import numpy as np
vec = np.array([170,70,30])
1 + vec

を実行してみましょう

array([171,  71,  31])

がでましたね。

全部 2で割り算してみるとか、100で掛けるとか
色々できます。
つまり、これにより、重みをまるっと掛け算できるわけです

さて、np.array() で配列を作れば
掛け算とかどうも簡単そうだな、ということがわかりました

そこで 先ほどとりあえず写経してもらったsigmoidをみてみましょう

def sigmoid(x):
    return 1.0 / (1.0 + np.exp(-x))

この X には np.array() が入ります
さきほど見た通り、1+np.array() は配列に
全部1を足し算した数字配列になりました

exp(-x) はどうなるでしょう?

これは、配列の中の各数字に math.exp() した数字配列が出てきます
それに 1 足して、さらに それを分数にできるんですね。

python使ってない人には意味わからんですね

とりま、この短いコードで
一挙に活性化した結果配列が手に入ることになり
単純なリストを使うより、np配列使った方が
コード量減って便利だねー
という気分になります。

ならない人ごめんなさい、
そんな重要な話しちゃうからコーヒーでも飲んで忘れといて
そのうち思い出してくれればいいです。

行列

ところで、これ、行列じゃなくて「配列」じゃね?
ともやもやしませんか?
あれ?しなかった?俺だけ?

実は numpy には それそのもの
np.array() 配列
ではなく
np.matrix() 行列

というものがあります。

なんでそっちつかわねぇの?
って話なんですが、これ掛け算した時に違いが出ます。

具体的に書くと

def SEIBETU(x1, x2, x3):
    w1 = 0.8 # x1の重み
    w2 = 0.4 # x2の重み
    w3 = 0.01
    return activator( x1 * w1 + x2 * w2 + x3 * w3 )

この関数を
SEIBETU([170,70,30])
というベクトルで受け取り、行列同士の掛け算もまとめてやるようにします。

def SEIBETU(x):
    w = np.array([0.8, 0.4, 0.01]) # 身長体重年齢の重み
    return x*w

SEIBETU(np.array([170,70,30])))

> array([ 136. ,   28. ,    0.3])

想定通りの動きをしましたね

今度は matrix で書いてみます

def SEIBETU(x):
    w = np.matrix([0.8, 0.4, 0.01]) # 身長体重年齢の重み
    return x*w

SEIBETU(np.matrix([170,70,30])

ValueError: shapes (1,3) and (1,3) not aligned: 3 (dim 1) != 1 (dim 0)

??

これ、実は 内積を計算しています
なので二次元ベクトル以上じゃないと計算できません
そして、内積計算にはルールがあって

2*3 の 行列に 掛け算できるのは

3*n の行列である

という、ルールがあります。
学校で習ったらしいですが覚えてます?僕は覚えてませんでした。

def NAISEKI(x):
    # 3 x 2 の行列
    w = np.matrix([[1,2],[3,4],[5,6]])
    return x*w

# 2 x 3 の行列
NAISEKI(np.matrix( [[1,2,3], [3,4,5]]   ))

こんな感じになります

2x3 の行列に掛け算していいのは 3xn の行列だけなので
[[1,2],[3,4],[5,6]] とか
[[1,2,3,4],[5,6,7,8],[9,10,11,12]]
こういう形式の行列しか掛け算できません
覚えておいて損はありませんが
これ、他の人のソース見ると
np.dot(np.array(),np.array())
という、配列を同士の内積を求めるための別関数で
処理している場合も多くあるので
わやですね、まぁそういう物もあるんだなー
と覚えておいてください。

—-

その他覚えておかないとわからん用語

性別判定AIを作るために
例えば 日本人1億2千万人のデータをもっていたとします

このデータを全部学習すれば日本人の生まれた時点での男女は
出せますが
全部学習していると時間が足りません

このデータから、ランダムに10人分のデータを抜き出して
学習してみることを考えます

この ランダムに取り出した「10人分のデータ」の事を
"バッチサイズ"と言います

10人分のデータを使って学習する、これじゃあ多分足りないですよね
なので、またランダムで別の10人を抜き出して学習します、
この繰り返し数をバッチ回数と呼びます

そして
バッチサイズ10人
バッチ回数100回

の学習を1エポックと数えます

つまり 10エポックは

(十人のデータを抜き出しして学習することを100回繰り返す) を 10回繰り返す

ということになります。

わかりにくい。。。

別に 一億二千万データ一回でもよくね?
という考えもありますが
省力化したいとか、実はこっちのほうが予測精度あがるとか
色々あるみたいですよ

あと AWS Batch ってありますが
こっちのバッチと同じ意味をを指してるみたいですね
バッチサーバーのことだと思っていたので
よくわからんぞこのサービスと思っていましたが
あれですね、語源が同じでも、全然別物ですね

—-

正規化

機械にやらせるなら、はじめから 数字は丸め込んでおく方が便利じゃね?
という考え方が 正規化です
引数ではノーマライズとか書いてあります。

例えば今回作った身長や体重などのデータは自然数ですが
当然、身長と体重では桁が違うわけで
重みの調整で割と苦労することになります。

そこで 身長も体重も
0.0〜1.0の範囲に丸め込んでしまいます
いくつか方法があるらしいですが
とりあえず わかりやすい方法として

全部の値から最小値を引き算してから
最大値と最小値の差分で割り算すると 正規化される

文章だとわからないですね

[1,2,3] の3要素で考えて見ましょう

最小値は 1
最大値は 3 ですね
コードにするとこんなのです

x = np.array([1,2,3])
x_hiku_min = x - 1
print(x)
sabun = 3 - 1

x / sabun

print(x)

> array([ 0. ,  0.5,  1. ])

紙ベースでも1分もあれば検算できるので確かめて見てください。

これをコードに直します

def min_max_normalization(x):
    x_hiku_min = x - x.min()
    sabun = x.max() - x.min()
    return x_hiku_min / sabun


min_max_normalization(np.array([1,2,3,4,5]))
min_max_normalization(np.array([1,2,3,4,5,6,7,8]))

必ず 0〜1の範囲に入っていますね。
これを使うと、x1 が 140だから 差分の12を減らすために w1 を~

みたいな事から解放されます。

また、この「正規化」みたいな処理を
「前処理」とか「プリプロセス」とか呼びます。
うちのチームだとクレンジングとか呼んでる事もありますね
厳密にはそれ違いますが、チーム内では伝わればなんでもOKや。

あー、他にもアンサンブル学習だのリサンプリングだの
ガン検診を当てる場合のサンプリング数だの
いろいろあるんですが1万文字超えちゃったので 今日はここまで

また次回もよろしくお願いします。

Amazonプライムデーで GearVRヘッドセットを買った

お疲れ様ですsysopjpです

オキュラスGOが巷で少し流行っていてほしいなーとか 思ったんですが、調べてみたらGearVRってオキュラスGOと たいして違いないんですね。

せっかく Galaxy note8 持ってるし GearVRかうぜー! って思ったんですが、今度はGear VRが
いくつも出ていて違いがわからない。

323
324
325
の三種類の中で一番安いの買おうと思ったんですが
あ、Note8は 325しか使えないのねーって事を知り
たまたまプライムデーで安くなっていたから買っちゃいました。

Gear VR 開封の儀

はい、というわけで開封の儀です

323とか買った人のブログ読んだら
すげーちゃっちぃ って書いてあったんですけど
割とまともな箱に入ってきました

出そうとして箱を開くと、パッケージのGear VRが 全体像描写になるのいいですね

ずずずずーっと出して

はい

箱はコントローラが入ってるやつですね

横には燦然と輝く Oclusの文字、そう、本当にたいした違いが無いわけですよ やたー、安く買えたぞー!!

ここが操作パッドになっているそうです

はいぱかっと開けまして

えーと、これをつけるのかな?
※ この付け方は NoGoodです、本来は コネクタはつけっぱなしで スマホを差し込みます、下手すると GearVRが壊れるので、買ったらまず説明書読みましょう

はいかちゃっとついたー!
ってあれ?どうやって装着すんの?
仕方ないから説明書探します

あ、こっちの箱がコントローラーだけかと思ったら
頭につけるストラップとか入ってるんですね ヤダー

と、いうわけで装着完了っと。

しかし画面がまっくら、えーーーーー???なんでーーー?

と思ったら、スマホのロック解除してから刺さないといけないそうです。

ぐぬぬぬぬ。。。 ちょっと面倒。

※調べたら Oclus は そんなことないので やはり GearVR買うより Oculus GOの方が使いやすいですね

使ってみた感想

いくつか困ったポイントがありまして

まず埃の混入、結構すぐ埃が入りますので カメラ用のブロアーを買った方がいいです

また GalaxyNote8 はでかすぎて、ヘッドフォンさしたまま GearVR に接続できないので
Bluetooth ヘッドフォンあったほうがいいです
もしくは 肩にのせるスピーカー があると、重低音を身体で感じる事ができるので
まじ映画館になります

次、コンテンツの不足

キラーコンテンツは 動画の再生、これは間違いないですが 再生動画で一番楽しいのはまるで映画館でみているような大画面映像です
しかし、しかしですね昔ソニーのHMDつかったときにも思ったんですが、
ただ画面がでかいんじゃダメなんですよ
映画館でみているような画面になるためには
「顔をあげると 画面の端が見えるくらいの視界に画面が入りきらないくらいの大画面」
これが、映画館のような大画面
っていう体験に繋がるのです。
言ってる意味わかりますかね?

まあなにはともあれ
Netflix に入らないとつまらないです
Amazon Prime もブラウザ経由なら再生できるって書いてあったのでやってみたんですが
えーと、まあつまんなかったです

また自分だけかもしれませんが
VR系動画は色収差が狂っており、中心部以外は 輪郭線が3重にぼやけて見えるので
すんげー疲れます 10分くらいで酔います

結局のところ、VR機能いらないんで、ジャイロ部分だけ活かして
映画館でみているかのような大画面で動画見れれば
それだけで十分だなーという代物でした。 片目つぶってみると、そういう体験になるので
そうやって楽しんでいますが
両目でただ 画面がでかい映画館モードになるだけの
無理に vrにする必要ないから、そういうのだれか作ってくれないかな。。。
DMM.make あたりで クラウドファンディングしながら 自作すればいいのかなー?

pythonista で 図を描く

お疲れ様です、sysopjp です

別記事を書いている最中に図が必要になったので 手書きで書こうと思ったんですが

あれ?pythonista で描けばいいんじゃね?

と思い立ったのでやってみます

# バイアスの図を描きたい
import numpy as np
import matplotlib.pyplot as plt

# 描画範囲の指定
# x = np.arange(x軸の最小値, x軸の最大値, 刻み)
# 線は繋がるので 直線を描きたいだけなら 刻みは 0.1 でも 1.0でもなんでもよい
x = np.arange(0, 1.1, 1.0)

# 計算式
y = 1.1-x

plt.plot(x, y)
plt.show()

はい 実行

速攻でしたね。

以上、よろしくお願いします。

iPadでpythonとかディープラーニングもすげー簡単にできちゃうSagemakerがヤバすぎるのでみんな使って!

お疲れ様です、sysopjpです

みんなSagemaker使ってます?

これやばい、ほんとやばい、何がヤバイって もう開発にmac とかいらない当たりがヤバイ

iPadが真のシンクライアントとして目覚める感じのヤバさがすごい

と、煽り気味に書いてみましたが、pythonとして 簡単に環境構築して開発できるあたりは Cloud9より簡単なのでまじsysopjp的にはおススメです

とりあえず今回は Sagemaker でインスタンス立てて
keras の pre-model 使って 好きな画像を
判定してみましょう

Sagemaker 使ってみよう

どんなボンクラでも どんなpcでも
ブラウザさえ使えれば python で開発したり、趣味のプログラムを組めます
今 python は求人多いですしね、学ぶにはオススメですよね!! そう、今回は実は機械学習関係ないです
題名にもありましたね、iPad + Sagemaker のお話です
iPad で ディープラーニングも

はい というわけで AWS ログインして Sagemaker をポチッとしましょう

あ、ちなみに無料期間は インスタンス稼働 250時間くらいです 毎日4時間遊ぶとしても 二ヶ月は無料で遊べますよ。やったー!

インスタンス作成画面

IAMロールだけはじめに作らないといけないので IAMロール作れるユーザーで入りましょう。

S3 へのアクセスどうするの?みたいな事言われるので 気になる人は特定のs3に、どうでもいい人は任意のs3にでもしておきましょう

面倒な人は、ここで作成されるIAMロールに S3 フルアクセスでも付与しましょう

画面右下の ノートブックインスタンスの作成をクリック

ステータス pending 進行するまでお待ちください だいたい5分くらいかかります

TensorFlow の 提供してるアーキテクト

五分待ってるあいだに小話しますね

これは tensorflow の提供してるアーキテクト図ですが

今から Sagemaker で やるのは 丸ついてる

pre-made estimator のところです

そもそも Sagemaker ってなんやねん?

ってところからいきますけど

自分が一ヶ月ほど触った結論として、以下の感じでした

1、機械学習へのとっかかり

Sagemaker には
組み込みアルゴリズムってものがありまして 例えば ラーメン二郎判定とか、アイマスのキャラ判定とか ネットによくありますよね、あれをpythonコード一行も書かないで
実現できるようになっています。
具体的には3ステップ

一, s3に学習データ(画像)を保存
二, s3に教師データ(画像のpath と その画像がなんの画像かを書いた テキストデータ) を保存
三, Sagemaker 組み込みアルゴリズムで実行

以上完了です。

会社でガハハ系の上司に
「最近でぃーぷらーにんぐ が流行りなんだってね! やってみてよ! 」
みたいな事言われて困った場合でもこの組込アルゴリズムだけで
3回ぐらいは会議でどうにかできます(実話

先ほどの図でいくと

pre-made estimator

のさらに上の部分になります、むっちゃ簡単にできます。

2、AWS engineerと機械学習 engineerは別のスキルだから分業しよう

機械学習engineerにAWSは難しすぎるけど、AWS engineerには機械学習が難しすぎます
そう思いませんかね? いや僕はそう思います
だって機械学習のネットワークを修正して精度をあげれる人と
そのモデルをトラブルなく運用できる人は別スキルでしょ? 今だってアプリ engineerとインフラ engineerは別でしょ?
Sagemaker は アプリ engineerとインフラ engineerと機械学習 engineerを結びつける
そんなキューピットなのです!!!

いや、何言ってんのかわからない?

アプリ engineer的な言い方をすると
Sagemakerのインターフェースに適合させれば
モデル作る人はネットワークにだけ集中して
アプリ engineerは インターフェースにだけ集中できるのです
そう Sagemaker を使うと機械学習が分業できるようになるんですね
素晴らしくないですか?

え?もっとわからない?
えー五分たっちゃうから 最後まで読んでからあとで質問にきて!!!

3, 機械学習とかとりあえず置いといて Python実行環境として使う

conda入ってるJupyter がボタン数回で作れるので
とりあえずなんも考えずに開発環境として使えます
今回は この3を実演して とりま次回に 1の分類器実際に作成してもらって
その次 2 の学習 engineerと協業を実際にしてみますね

さて、そろそろ終わったかな? 見てみてください

Sagemaker インスタンス初号機 起動!

InService になりましたね

さぁここの オープンを クリック!!しましょう 当然僕は iPad からやります
気がついてるかもしれませんが、ここまでも ここから先も全部iPad でやってるんですよ?

Jupyter notebook

はい、見慣れた人には見慣れた画面がでましたね

この時点で

こんだけの環境があります。

どうよ?ボタン今何回押しただけよ? それでこれやで? いやわかるよ、わかる
俺だって職場では Mac に Docker いれて Juypter してるもん
それでもできるよ、もちろんできる でもね、ほら考えてみ、これから新規で来る人に
Docker ファイル渡して起動させるのと こっちと どっちのほうが早かった? ねえどっちのほうが早かった?
そして Mac とか買うより どっちのほうが*やすかった? *

実は、自分、物欲が爆発して、 新しくMacbook 買おうと思ったら30万とか普通にして
たっけーなーってなってたんですよね
2018MBPももうすぐ出そうだし今買わないほうがいいなーとか
そうだ 安く買うなら 整備済み!ってそっち探したら日本では英字キーボード整備済みにないし
もう 米アップルから整備済みで輸入するか?って本気で考えてました

でもでも、 これで開発環境としては完全に事足りてるってことに
そう、気がついたんですね。

いやー、ほんと、iPad から簡単に作れて簡単に開発できるって ほんと素晴らしい!

実際に ディープラーニングモデルを一個使ってみる

https://keras.io/ja/

この Keras は日本語ドキュメントが豊富なので 読めばできます
とりあえず、premade estimatorをやるよーって先ほど宣言したので
やってみましょうね

画面右上の New から Conda tensorflow p36 を選択します

ちなみに anaconda と tensorflow が入っている python3.6 環境の意味です

最初のセルに これをいれて Shift+return してください。
コピペするより、手で入れるほうがおススメ
15年以上 engineerしてきた僕からのお勧め
ほんと手で打たないと体が覚えないから
目で見て手で入れたほうがいいよ

from keras.applications.resnet50 import ResNet50
from keras.preprocessing import image
from keras.applications.resnet50 import preprocess_input, decode_predictions
import numpy as np

model = ResNet50(weights='imagenet')

判定したい画像が必要なので ラーメン二郎でも犬でも猫でも神社仏閣でもなんでもいいので グーグルからでもURLをとってきてください

とりあえず 猫でもやりますか、判定してみたい画像のURLをwget します 自分はwikipedia からひっぱってみました

!wget https://upload.wikimedia.org/wikipedia/commons/3/33/Hannibal_Poenaru_-_Nasty_cat_!_(by-sa).jpg 

はい、Jupyter では 頭に ! いれると、Linuxコマンドが実行できます 実行は ふつうに Shift+return ですね

これで ローカルにコピーしてきたら 以下のソースを また書いて見ましょう

img_path='Hannibal_Poenaru_-_Nasty_cat_!_(by-sa).jpg'
img = image.load_img(img_path, target_size=(224, 224))
x = image.img_to_array(img)
x = np.expand_dims(x, axis=0)
x = preprocess_input(x)

preds = model.predict(x)
print(preds)

print('Predicted:', decode_predictions(preds, top=3)[0])

はい、実行したら こうなりましたね

この画像は一位 クーガー? あー 猫科の肉食獣だと思われたみたいですね たしかに牙が怖いw
著作権がー みたいな話になりそうなので ここには張っていませんが
グーグルで猫画像を検索して wget して色々やった限りでは
けっこーあたりますよ

さて、どうでしょう? ここまで ごちゃごちゃ話しながら実は記事自体は五千文字程度ですね プログラムに至っては何行? 環境構築にいたっては何ステップで終わった?

これで、ディープラーニングが、できちゃった え?あっさり? はいあっさい、終わりました

みんな狐につままれたような顔していますが、えー今日はこれで終わりです
そんな拍子抜けした顔されても自分も困ります。。。
実行だけならこれくらい簡単にできるからSagemakerやってねって記事なんだよ。。。

大丈夫、地獄をみたい人にはちゃんと ネットワーク図をプログラムさせてやるから!
機械学習なんて8割精度検証と事前作業だからそっちで地獄を見せてやるから安心してくれ!!

え?こんなの実務で使えるの?
使えますよ、アンサンブル学習にはむっちゃ使えます
それでは以上!!! 地獄の一丁目一番地 ステップワン! 終わり! よろしくお願いいたします!!!