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

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

oracleexdata につなぐために sql plus docker を テストで 作ってみた

お疲れ様です、sysopjpです

掲題の通り、ちょろっとExdataに繋ぐだけなのに インストールしたくなかったので

docker探したけど、いいのなかったんで ちょろっと作りました


Dockerfile

FROM frolvlad/alpine-glibc

MAINTAINER sysopjp


RUN apk --update add unzip libaio


# wget で落とそうとしたらTo connect to edelivery.oracle.com insecurely, use `--no-check-certificate'. で怒られた

# ライセンスに同意を押さないといけないとか

# 対処が面倒だったから

# http://www.oracle.com/technetwork/topics/linuxx86-64soft-092277.html

# から直接DLしてカレントに置いといてください

ADD instantclient-basic-linux.x64-12.2.0.1.0.zip ./

ADD instantclient-sqlplus-linux.x64-12.2.0.1.0.zip ./

ADD instantclient-sdk-linux.x64-12.2.0.1.0.zip ./

ADD instantclient-jdbc-linux.x64-12.2.0.1.0.zip ./


RUN unzip instantclient-basic-linux.x64-12.2.0.1.0.zip && \
    unzip instantclient-sqlplus-linux.x64-12.2.0.1.0.zip && \
    unzip instantclient-sdk-linux.x64-12.2.0.1.0.zip && \
    unzip instantclient-jdbc-linux.x64-12.2.0.1.0.zip

RUN rm instantclient-basic-linux.x64-12.2.0.1.0.zip && \
    rm instantclient-sqlplus-linux.x64-12.2.0.1.0.zip && \
    rm instantclient-sdk-linux.x64-12.2.0.1.0.zip && \
    rm instantclient-jdbc-linux.x64-12.2.0.1.0.zip && \
    apk del --purge unzip


ENV LD_LIBRARY_PATH instantclient_12_2


CMD /instantclient_12_2/sqlplus $URL

How to use

docker run -e URL=<user>/<password>@//xxx.yyy.ap-northeast-1.rds.amazonaws.com:1521/ORCL -ti sysopjp/splplus-alpine  
駄文

いま唐突に思い出したんですが

sysopjp が How to use って文章知ったのは デスノートでした。

葦原先生ありがとう謝恩祭!キンドルよりジャンプブックスの方が安い!

お疲れさまですsysopjpです!

ワールドトリガー連載再開ですね!やった!嬉しい

というわけで、紙の方は既にあるんですが、葦原先生に届けとばかりに電子書籍版をジャンプ+で買おうとしたら

どこから買えるねん??

となったので、そこらへんの共有です 結論から言うと

1.ジャンプ+各話掲載の最終ページから買う

2.ジャンプブックスから買う

の2パターンでした。 あ!あと!18巻まで揃えて7000円キッカリで済みます キンドルで買うより少し安いですね!やった!

ジャンプ+でコミックスを買う

ジャンプ+単体ではコミックスを買う場合、メニューからいきなりは辿れません

まず、現在やってるワールドトリガー無料掲載を押します

f:id:sysop:20181020184001j:plain

もしくは左上のメニューから作品検索して出てくる各話買えるやつを開きます ちなみに、ここで買える各話分 一度閉じたらみれなくなるタイプのやつです、一回読めればいいや! っていうなら全話買ってもコミックスの半額ですむので検討の余地はありますね!

とりあえず、無料掲載してる一話の最後のページが

f:id:sysop:20181020184005j:plain

ここから買うことができます。

メニューとか作品詳細にも用意しといてほしい……

ジャンプコミックスはジャンプブックスで買えます

その遷移もなんかやだなーって人は

https://play.google.com/store/apps/details?id=com.access_company.android.sh_jumpstore

f:id:sysop:20181020183905j:plain

このためだけにアプリ落とすのが嫌だー って人は

http://jumpbookstore.com/

ブラウザからもかえますよ!

とりあえずアプリの方で解説しますね

さあ買おう

文字で書いてもわかりにくいので、スクショでいきますね

f:id:sysop:20181020183909j:plain

f:id:sysop:20181020183913j:plain

f:id:sysop:20181020183918j:plain

f:id:sysop:20181020183925j:plain

f:id:sysop:20181020183930j:plain

f:id:sysop:20181020183935j:plain

18巻までなら、7380コインなので、5000と2000で買えます!(大事

でも12/4に19巻が出ますので、そうするとコイン買い足し必要になるし、いっそ10800コイン買っておいて取っておくのもいいと思いますよ!

f:id:sysop:20181020183941j:plain

さて、読むときなんですが ジャンプブックスのアプリ

もしくは、ジャンプ+の本棚からも読めます

f:id:sysop:20181020183946j:plain

f:id:sysop:20181020183951j:plain

f:id:sysop:20181020183956j:plain

100話って何巻まで?

ちなみに、12/3日まで無料連載してる100話は 12巻の途中くらいまでになります

まあそこまで、節約したい人は、一回きりしか読めないけど各話で買うのが一番安いですよ

以上になります!どうぞよろしくお願いします

Gradient boosting tree iPad pro + Sagemaker

お疲れ様です、sysopjpです

scikit-learnとか sklean とか名前も安定していないし

GBTとかGBTDとか、GBTCとかえーと よくわかんなかったのでまずは使ってみました 後でこの認識間違ってるよとかツッコミくだしあ

環境は ipad pro+Sagemakerです。

Gradient boosting tree

まずはデータを用意します https://archive.ics.uci.edu/ml/datasets/Adult

!wget https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.data

カラム情報は https://archive.ics.uci.edu/ml/machine-learning-databases/adult/adult.namesに書いてありました

age: continuous.

workclass: Private, Self-emp-not-inc, Self-emp-inc, Federal-gov, Local-gov, State-gov, Without-pay, Never-worked.

fnlwgt: continuous.

education: Bachelors, Some-college, 11th, HS-grad, Prof-school, Assoc-acdm, Assoc-voc, 9th, 7th-8th, 12th, Masters, 1st-4th, 10th, Doctorate, 5th-6th, Preschool.

education-num: continuous.

marital-status: Married-civ-spouse, Divorced, Never-married, Separated, Widowed, Married-spouse-absent, Married-AF-spouse.

occupation: Tech-support, Craft-repair, Other-service, Sales, Exec-managerial, Prof-specialty, Handlers-cleaners, Machine-op-inspct, Adm-clerical, Farming-fishing, Transport-moving, Priv-house-serv, Protective-serv, Armed-Forces.

relationship: Wife, Own-child, Husband, Not-in-family, Other-relative, Unmarried.

race: White, Asian-Pac-Islander, Amer-Indian-Eskimo, Other, Black.

sex: Female, Male.

capital-gain: continuous.

capital-loss: continuous.

hours-per-week: continuous.

native-country: United-States, Cambodia, England, Puerto-Rico, Canada, Germany, Outlying-US(Guam-USVI-etc), India, Japan, Greece, South, China, Cuba, Iran, Honduras, Philippines, Italy, Poland, Jamaica, Vietnam, Mexico, Portugal, Ireland, France, Dominican-Republic, Laos, Ecuador, Taiwan, Haiti, Columbia, Hungary, Guatemala, Nicaragua, Scotland, Thailand, Yugoslavia, El-Salvador, Trinadad&Tobago, Peru, Hong, Holand-Netherlands.

これをリストにしておく

col = ['age', 'workclass', 'fnlwgt', 'education', 'education-num',
       'marital-status', 'occupation', 'relationship', 'race', 'sex',
       'capital-gain', 'capital-loss', 'hours-per-week', 'native-country',
       'label']

説明変数と目的変数

データをXとYに分けます。

そもそも名称からして 説明変数、X、学習データ 目的変数、Y、教師データ 他にも呼び名がたくさんあってわかりません とりあえず僕は当てたいデータをY、元になるデータをXで通します。

今回の adult_data はどうやらその人の属性を入れると 収入が 50k を超えるか以下かをあてるデータのようです

adult_data = pd.read_csv('adult.data',names=col) f:id:sysop:20181019205617p:plain

一番右の label が Y ですね。 そこでこの label列を分離します

y = adult_data['label']

x = adult_data.drop('label', axis=1)

Gradient boosting tree  にぶっこんでみる

とりあえずぶっこんでみます

from sklearn.ensemble import GradientBoostingClassifier

import numpy as np

import pandas as pd

clf = GradientBoostingClassifier(n_estimators=100, learning_rate=0.1,max_depth=1)

clf.fit(x, y)  ```


>could not convert string to float: ' United-States'  


GBTでは float 型しか扱えないの、ごめんね
と言われます。

さて、これを手で直していると時間もかかるのでライブラリに頼ります
結局プログラムなんてライブラリをどれだけ「知っているか」
で効率が変わるので便利なライブラリをたくさん使って、たくさん覚えましょう

http://own-search-and-study.xyz/2016/11/23/sklearn%E3%81%AEpreprocessing%E3%81%AE%E5%85%A8%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%82%92%E8%A7%A3%E8%AA%AC/

こちらの人の解説がわかりやすかったです、あざーす


### label_binarize


説明変数Xがラベルの時はこっち使う
ちなみに目的変数がラベルの時はLabelEncoder
を使う、理由は長くなるから別の機会に

col = x["native-country"].unique()

nc_df = pd.DataFrame(sp.label_binarize(x["native-country"], classes=col), columns=col)


### 他のデータもやっちゃう

*workclass

* education

*marital-status
* occupation

* relationship

* race

* sex
もやってしまいます

ただし sex は

x['sex'].unique()

array([' Male', ' Female'], dtype=object)

元データが2値しかなかったので LabelEncoder で
http://own-search-and-study.xyz/2016/11/23/sklearn%E3%81%AEpreprocessing%E3%81%AE%E5%85%A8%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E3%82%92%E8%A7%A3%E8%AA%AC/#LabelEncoder

0、1に置き換えます

ラベルを数値に変換する

train_df = x

transform_col =  ['native-country','workclass','education','marital-status','occupation','relationship','race']

for i in transform_col:     tmp_df = pd.DataFrame(sp.label_binarize(x[i], classes=x[i].unique()), columns=x[i].unique())     train_df = pd.concat([train_df, tmp_df], axis=1)

SEX の変換

le = sp.LabelEncoder()

le.fit(x['sex'].unique())

tmp_df = pd.DataFrame(le.transform(x['sex']), columns=['sex_binary'])

train_df = pd.concat([train_df, tmp_df], axis=1)

transform_col.append('sex')

変換の終わったデータを抹消する

x_train = train_df.drop(transform_col, axis=1)


### GBT してみる


ではやってみましょう

`clf.fit(x_train, y) `

>GradientBoostingClassifier(criterion='friedman_mse', init=None,
              learning_rate=0.1, loss='deviance', max_depth=1,
              max_features=None, max_leaf_nodes=None,
              min_impurity_decrease=0.0, min_impurity_split=None,
              min_samples_leaf=1, min_samples_split=2,
              min_weight_fraction_leaf=0.0, n_estimators=100,
              presort='auto', random_state=None, subsample=1.0, verbose=0,
              warm_start=False)


お???おお?なんかできた?できたっぽいぞ??


### 推測して見る

とりあえずぶっこんでみましょう


`clf.predict(x_train[:1])`

>array([' <=50K'], dtype=object)

ほー、あたってるね。
まあ、学習データ入れてるんだから、そりゃあたり率高いはずなんですけどね


`clf.predict(x_train[:10])`
こうやって 10個くらいまとめてリストDFの状態でも入れられます

array([' <=50K', ' >50K', ' <=50K', ' <=50K', ' <=50K', ' >50K', ' <=50K',        ' <=50K', ' >50K', ' >50K'], dtype=object)

んー?みにくい

for x in clf.predict(x_train[:10]):     print(x)

 <=50K  >50K  <=50K  <=50K  <=50K  >50K  <=50K  <=50K  >50K  >50K

上から10個渡して見たらこんなデータじゃね?ってきましたね

y[:10]

0     <=50K

1     <=50K

2     <=50K

3     <=50K

4     <=50K

5     <=50K

6     <=50K

7      >50K

8      >50K

9      >50K

Name: label, dtype: object

あーんー結構はずしますね。



## 学習データとテストデータ

さて、あたった外れたとか目視でやっていると大変なので
ここもライブラリに頼ります
さきほどモデル作成に使ったデータを学習とテストに分解します


`len(x_train)`

> 32561

どこらへんでわけるの?と言われるとよくわかりません
とりあえず端数でわけて、GBTに入れて見ます

x_train2 = x_train[:30000]

y_train2 = y[:30000]

x_test2 = x_train[30000:]

y_test2 = y[30000:]

clf.fit(x_train2, y_train2)

> GradientBoostingClassifier(criterion='friedman_mse', init=None,
              learning_rate=0.1, loss='deviance', max_depth=1,
              max_features=None, max_leaf_nodes=None,
              min_impurity_decrease=0.0, min_impurity_split=None,
              min_samples_leaf=1, min_samples_split=2,
              min_weight_fraction_leaf=0.0, n_estimators=100,
              presort='auto', random_state=None, subsample=1.0, verbose=0,
              warm_start=False)


できた clf の性能は score という関数で観れます

print (clf.score(x_test2, y_test2))

>0.8543537680593518

当たった確率なので
このモデルは 85% くらいであたる精度だったようですね



### マルチクラスだかマルチラベルだか

マルチラベルとマルチクラスとどういう名称が正しいのか
いまだにわかりませんが
二次元データをあてにいきます

具体的には、そうですね、データを入れると
人種とlabel を推論するモデルを作成します


Yとして label と race を分離します

adult_df = pd.read_csv('adult.data',names=col)

target_col = ['label','race']

y = adult_df[target_col]

x = adult_df.drop(target_col, axis=1)


fit してみます

clf.fit(x_train, y)

> bad input shape (32561, 2)

まあそうですよね、二次元のデータをいきなりあてるのは無理ですよね。



### マルチクラスの次元圧縮

まず bad input shape (32561, 2)にあるとおり

Yが2次元なのは無理、と言われているので、これを一次元に
次元圧縮します

そう、次元圧縮します!!
大事なことなので二回いいました
かっこいいですよね、次元圧縮

ま、難しい言葉使っておきながら
一番頭の悪い方法でいきます


`y['data'] = y['label'] + ',' + y['race']`

はいできた!!!!
え?足しただけだろ?
はい、そうです、カンマセパレートで足しただけです



`clf.fit(x_train, y['data']) `

> GradientBoostingClassifier(criterion='friedman_mse', init=None,
              learning_rate=0.1, loss='deviance', max_depth=1,
              max_features=None, max_leaf_nodes=None,
              min_impurity_decrease=0.0, min_impurity_split=None,
              min_samples_leaf=1, min_samples_split=2,
              min_weight_fraction_leaf=0.0, n_estimators=100,
              presort='auto', random_state=None, subsample=1.0, verbose=0,
              warm_start=False)


それでもほらできた!!
先ほどと同じように、テストデータと学習データにわけて精度みてやると

clf.fit(x_train[:30000], y['data'][:30000])

print (clf.score(x_train[30000:], y['data'][30000:]))

> 0.7348691917219836


73% であたるって!結構高いね

ちなみに出力はこんな感じになります

clf.predict(x_train[30000:30010]))

[' <=50K, White' ' <=50K, White' ' <=50K, White' ' <=50K, White'  ' <=50K, White' ' <=50K, White' ' >50K, White' ' <=50K, Black'  ' <=50K, White' ' <=50K, White']




print(y['data'][30000:30010].tolist())

>[' <=50K, White', ' <=50K, Black', ' <=50K, White', ' <=50K, White', ' <=50K, White', ' <=50K, White', ' >50K, White', ' <=50K, Black', ' <=50K, White', ' <=50K, White']


おー、ここらへんは 100%あたってますね、すごいすごい




### モデル複数つくればいいやん

さて、別にGBTはモデル作成早いし、別々のモデル作ればよくね?
ということで複数モデル作って当てに行ってみます

label_clf = GradientBoostingClassifier(n_estimators=100, learning_rate=0.1,max_depth=1)

race_clf = GradientBoostingClassifier(n_estimators=100, learning_rate=0.1,max_depth=1)

label_clf.fit(x_train[:30000], y['label'][:30000])

race_clf.fit(x_train[:30000], y['race'][:30000])


`label_clf.score(x_train[30000:], y['label'][30000:])`

> 0.8543537680593518



`race_clf.score(x_train[30000:], y['race'][30000:])`

> 0.8734869191721983

さて、これをさらに並べたデータを作ってみましょう

label_pdr = label_clf.predict(x_train[30000:])

race_pdr = race_clf.predict(x_train[30000:])

pdr_df = pd.DataFrame({ 'pdr_label' : label_pdr, 'pdr_race' : race_pdr})

pdr_df['pdr'] = pdr_df['pdr_label'] + ',' + pdr_df['pdr_race']


pdr_df['pdr']がどれくらい正解したか判定したいので

y[30000:]をとりますが index があわなくて比較が難しいので添え字を初期化(reset_index)します

result_y = y[30000:].reset_index()

出てきたデータを合わせて、比較してみると

result['check'] = result['pdr']==result['data']

result['check'].value_counts()

> True     1892

> False     669


1892 個/2561個があたっていたので

0.73!!!  

あまりさっきと正解率かわらないですねw  

とりあえずこんなところになります

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

VisualStudioCode nosetest

お疲れ様です sysopjpです 掲題の設定の仕方になります

設定を開いて

f:id:sysop:20181019205447p:plain

ユーザー設定に

python.unitTest.nosetestsEnabled: true

python.unitTest.noseTestArgs を追加

f:id:sysop:20181019205450p:plain プロジェクトフォルダの tests/ 以下にテスト用ファイルを配置

f:id:sysop:20181019205455p:plain

testコード f:id:sysop:20181019205459p:plain ソースコード f:id:sysop:20181019205503p:plain

開いているフォルダ直下の tests ディレクトリを探すので相対位置に注意

f:id:sysop:20181019205506p:plain

きちんと認識されるとテストファイルにRunTest が勝手に現れます。

また Command+P のコマンドパレットから実行することもできます f:id:sysop:20181019205510p:plain

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!!

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