Yado_tech

旅館+ITとはなんぞ

Google Colaboratory できゅうりを選別する。

f:id:devilmakelie:20180817174629p:plain

最近少しずつ趣味でディープラーニングを勉強しているのでそのアウトプットとして2年ほど前に話題になったキュウリを仕訳してみます。

モチベーション:写経だけじゃなくてもう少し踏み込んだところで機械学習をしたかった。

jupyter notebookでゼロから作るディープラーニングを写経していたのですが、思った以上に学習に時間がかかることがわかりめちゃくちゃだるくなったため、 似たようなサービスであるGoogle Colaboratoryを利用してディープラーニングやってみます。

まだまだ勉強中につき深いことはわかりませんが、なんとなくでも実装できないかしら?と思ってやってみた。結果としてできたけどふわっとしてる

わかったこと:

  • Google Colaboratoryの使い方がわからなかったため、めちゃくちゃつまづいた。
  • さらにきゅうりの画像の読み込み方はさっぱりわからなかった。
  • 前処理が教科書だとざっくりとkeras.dataset使えとかなんとか書いてあるけど、きゅうりの場合それがそもそもわからなかった。 そこでゼロから作るディープラーニングMNISTのやつをちゃんと読んだ。 冗談かもしれないがそれでもわからなかったのでさらにcifar-10のやつやQiitaなどを読んだ。そしてほぼ丸々パクった。

わからなかったことがわかったこと:

  • 途中の変数のnb_train_samplesが何なのかわからない。
  • CNNのsequentialの実装だがこれはたぶんだけどいろいろ流儀というかモデルの作り方があるみたいだ。今回は畳み込み層が2層と結合層が1層の畳み込みニューラルネットワーク・・だよね?

以下ソース

#まずはファイルをアップロードする。

from google.colab import files
uploaded = files.upload()

アップロードするのはGithubからダウンロードしたやつ

ダイアログボックスが出るのでアップロードする。

f:id:devilmakelie:20180817173720p:plain

ファイルの解凍

#ファイルを解凍する。
!tar -zxvf cucumber-9-python.tar.gz

解凍できているみたいだ。

f:id:devilmakelie:20180817173922p:plain

#解凍したファイルを読み込む
#
def unpickle(f):
    import pickle
    fo = open(f, 'rb')
    d = pickle.load(fo,encoding = 'latin-1')
    fo.close()
    return d
  
#訓練データを読み込む

nb_train_samples = 2475
x_train = np.zeros((nb_train_samples, 3, 32, 32), dtype='uint8')
y_train = np.zeros((nb_train_samples,), dtype='uint8')

for i in range(1,5):  
  fpath ='data_batch_' + str(i)
  batch_dict = unpickle(fpath)
  data = batch_dict['data']
  labels = batch_dict['labels']
  x_train[(i-1)*495:i*495, :, :, :] = data.reshape(495, 3, 32, 32)
  y_train[(i-1)*495:i*495] = labels

#教師データを読み込む

data =  unpickle("test_batch")
x_test = data['data'].reshape(495,3,32,32)
y_test = data['labels']

次にデータを3つにわける

#処理したデータを3個に分割する。

from sklearn.model_selection import train_test_split
x_train1,x_valid,y_train1,y_valid = train_test_split(x_train,y_train,test_size = 0.175)

次はモデルの設計図となるSequentialをデザインする。ここでCNNかRNNかNNかとかそういったいろいろが決まる。

#Sequentialの実装。ほぼコピペ。元画像がMNISTだと28*28*1だがきゅうりの場合は32*32*3なのでそれにあわせて書き換える。
#あと出力層はMNISTの場合10だがきゅうりの場合は9だとかなんとか

from keras.models import Sequential
from keras.layers import Dense,Dropout,Flatten
from keras.layers import Conv2D , MaxPooling2D
import keras

model = Sequential()
model.add(Conv2D(32,kernel_size = (3,3),activation = 'relu' , input_shape=(32,32,3)))
model.add(Conv2D(64,(3,3),activation = 'relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0,25))
model.add(Flatten())
model.add(Dense(128,activation='relu'))
model.add(Dropout(0,5))
model.add(Dense(9,activation = 'softmax'))

データをきれいにする。

#データの正則化。なぜやるのかよくわからない。

x_train = x_train.reshape(x_train.shape[0],32,32,3)
x_valid = x_valid.reshape(x_valid.shape[0],32,32,3)
x_test = x_test.reshape(x_test.shape[0],32,32,3)

x_train = x_train.astype('float32')
x_valid = x_valid.astype('float32')
x_test = x_test.astype('float32')

x_train /= 255
x_valid /= 255
x_test /= 255

y_train = keras.utils.to_categorical(y_train,9)
y_valid = keras.utils.to_categorical(y_valid,9)
y_test = keras.utils.to_categorical(y_test,9)

最後に学習とデータの確認。 なんかわからんけど出来ているようだ。

#学習させる。

from keras.optimizers import RMSprop

model.compile(loss='categorical_crossentropy',
             optimizer = RMSprop(),
             metrics=['accuracy'])

history = model.fit(x_train,y_train,
                   batch_size = 120,
                   epochs=10,
                   verbose=1,
                   validation_data = (x_valid,y_valid))

f:id:devilmakelie:20180817174425p:plain

https://colab.research.google.com/drive/1o7gosgj5NytGGAXvjHxlnuXjW9bxk5E2

パクリ元:

spotifyとLast.fmを接続する

f:id:devilmakelie:20180805180340p:plain

 

Last.fm知っていますか?様々なアプリやソフトウェアから音楽を再生すると専用のソフトをインストールすることで自分の音楽遍歴を見返すことができるWebサービスです。

 

Spotifyでももちろん聞いた曲履歴をLast.fmに登録することが可能で、設定さえきちんとすれば勝手にたまっていくので重宝して使っていたのですが、Spotifyアプリ内からは5月のアップデートからLast.fmの方に登録出来てなかったみたい

 

なんで?とは思ったものの、調べてみるとどうやらそもそもLast.fmというサービス自体知らない方からの問い合わせが多かったらしく、アプリ内でのLast.fmのログインを廃止したとのことでした。

 

ではLast.fmにはもう登録できなくなったかというとそうでもなく、今度はLast.fm側からの登録が必要となりましたので、それを解説していきます。

 

1.まずはLast.fmにログインし、「設定」ページを開きます。

 

f:id:devilmakelie:20180805181152p:plain

ページは右上の自分のアイコンをクリックしたら出てきます。

 

2.設定内のアプリケーションをクリックします。

f:id:devilmakelie:20180805181238p:plain

一番右のタブです。

 

3.アプリケーション内の「SpotifyでScrobble」の右の「接続」をクリック

 

f:id:devilmakelie:20180805181303p:plain

 

4.Spotifyの画面に代わりますのでログイン後、接続してください。

 

f:id:devilmakelie:20180805181505p:plain

 

以上です。ちょっと面倒になりましたが変わらず出来たので安心でした。

PythonでResasAPIにアクセスする

イデアソンがあるみたいなので・・

resas.go.jp

さくっとPythonでrequests使って問い合わせてみた。

ここを参考にした。
www.kmiura.net

都道府県表示させるやつよりも少しふみこもうとしたらわからんかったのでメモ

import requests
import json

def resas_api_request():
    api_key = "【API_KEY】"
    url = "https://opendata.resas-portal.go.jp/"
    
    url += "api/v1/cities"
    
    head = {
        "Content-Type":"application/json",
        "X-API-KEY":api_key
    }
    
    payload = {'prefCode':1}
    
    req = requests.get(url,headers=head,params=payload)
    
    print(req)
    json_obj = json.loads(req._content.decode('utf-8'))
    print(json_obj)
    
    return

resas_api_request()

みんなで分析しようぜ

ベイズ統計学

 

 

 なんとなく買ってみて読んでいるが、ベイズ更新のやり方だけでも十分に旅館の計数管理には役に立ちそうな気がする。

 

たとえば宴会の原価を推定するのにベイズ更新を使えば月ごとに結構正確な原価率が推定できるんじゃなかろうかとか

 

まぁ原価率なんて実際に使用額/売上で算出できるので力技でもいいけど、計画立てるときにはもう少しふわっとしているしね

 

確率も原価も同じ%だから勘違いしそうになるていうか、ベイズ更新的な手法だとどのような形になるのだろうか?

 

同じように計画をベイズ的に解くには?なんか色々興味が湧いてきます。

React周りの必要なモジュール

React

  •  react-dom

Redux

  • react-redux
  • redux-thunk

 

React-router

  • react-router-dom
  • react-router-redux
  • history

このあたりの使い方はちゃんと押さえておく。

 

あとはreduxのreducerでどこまでの処理を書くかってところが知りたい。

 

 これほんとわかりやすかった。

React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで (NEXT ONE)

React入門 React・Reduxの導入からサーバサイドレンダリングによるUXの向上まで (NEXT ONE)

 

 

web extensions書き直した。

どうにも昨日作ったweb extensionがきもちわるいかったので書き直した。

popup.jsでどうこうするやつはスコープの生き死にがわかりづらかった。

てことで現在はpopup.jsではなくbackground scriptsで管理するようにした。

f:id:devilmakelie:20180430235606p:plain

async/awaitとfetchAPIを使って書き直した。

非同期はわかりづらいけど最終的には各スクリプトにイベントリスナを追加する形で受ければ上手くいった。
イベントリスナで受けるのは思い付きだったけどうまくいった。よかった。

popup.js

//background scriptにリクエストを送る。
browser.runtime.sendMessage({text:''},function(response){
  document.getElementById('title').innerText = `you have selected ${response.artist}`
})

//background script からリクエストが来たらその通りにレンダリングする。
browser.runtime.onMessage.addListener(function(request,sender,sendResponse){
  console.log(request)
  render(request)
  sendResponse({text:'message received'})
})

function render(request){
  const similar_artist = request.state.similar_artist
  console.log(similar_artist)
  document.getElementById('title').innerText = `you have selected ${request.artist}`
  let html = ''
  for (key in similar_artist){
    html += `<br /><div><img src = ${similar_artist[key].image[1]['#text']}>${similar_artist[key].name}</div>`
  }
  document.getElementById('artist').innerHTML=html
}

background.js

//初期値の設定、選んだアーティストと似ているアーティスト

console.log('background start!')

//まずはAPIを叩くFunctionを作る。asyncなやつ
async function getSimilarArtist(artist) {
  var state = {
    artist_name: artist,
    status: "none",
    similar_artist: "",
  }
  const api_key = '6365215872671c325787a220ef38ae1c'
  var url = `http://ws.audioscrobbler.com/2.0/?method=artist.getsimilar&artist=${artist}&api_key=${api_key}&limit=10&format=json`
  fetch(url).then(async(response) =>  {
    var results = await response.json()
    state.status = "fetched"
    state.similar_artist = results.similarartists.artist
    //console.log(state)
    //最後にmessageをpopupに送る
    browser.runtime.sendMessage({
      artist: artist,
      state: state
    })
  })
}

browser.runtime.onMessage.addListener(function(request, sender, sendResponse) {
  //現在のタブを取得する
  browser.tabs.query({
    currentWindow: true,
    active: true
  }, function(tab) {
    browser.tabs.sendMessage(tab[0].id, {
      text: ''
    }).then(function(response) {
      getSimilarArtist(response.str)
    })

  })
})

content-script.js

//単純にメッセージが来たらそこにレスポンスを返すだけ
browser.runtime.onMessage.addListener(function(msg,sender,sendResponse){
    title = document.title
    str = document.getSelection().toString()
    console.log(str)
    sendResponse({title:title,str:str})
})

web extensions 作ってみた。


how to use lastfm extension

これ以上web extensions勉強しても知見が得られそうにないので実際に作ってみた。

generator-web-extension使用。

インストール方法はコチラ

やりたいことはボタン押したら選択範囲を検知してその選択範囲がアーティストならlast.fmAPIを利用して

似たアーティストを返すというもの。

ソースはこっち

github.com

やっぱ実際に書いてみるのが非常にわかりやすくてよかった。

つまづいたところ、というかなおしたいところ

popup.js

import LastFM from 'last-fm'

browser.tabs.query({
    currentWindow: true,
    active: true
}, function (tab) {
    browser.tabs.sendMessage(tab[0].id, {
        text: ''
    }).then(function (response) {
            const title = response.title
            const str = response.str
            document.getElementById('title').innerText = `you have selected ${str}`
            searchSimilarArtist(str)

        }

    )
})

function searchSimilarArtist(artist) {
    //authentificate
    const auth = new LastFM('6365215872671c325787a220ef38ae1c')
    // for debug:console.log(artist)
    //return artist similar to given name
    const data = {
        isFound: false,
        result: "ea"
    }
    auth.artistSimilar({
        name: artist
    }, (err, data) => {
        if (err) {
            data.isFound = false
            data.result = err
            console.log(data)
        } else {
            data.isFound = true
            data.result = data
            //for debug:console.log(data)
            let html = ""
            for (var i = 0; i < 10; i++) {
                html += `<br /><div>${data.artist[i].name}</div>`
            }
            console.log(html)
            document.getElementById('artist').innerHTML = html
        }
    })
}

この中のfunction searchSimilarArtistのauth.artistSimilar関数のコールバック処理

ここで全部分けてるからそれを別の処理に移したいのだけどlet html ~の部分をdataをreturn するまでのfunction にして以降にdataをレンダリングfunctionに切り分けたいのだがうまくいかない。

dead objectがどうのって怒られた。

多分非同期的にプログラムが進んでてdataが返ってくる前に次に進んじゃっているのが原因のはず。

うまくレンダリングできるようにならないかな。

これからやりたいこと:

  • これをreduxのフローに沿って書き直してみたい。
  • うまくフローに乗せれたら次は色々(アーティストの画像とか)も表示できるようにしたい。

さてうまくいくかな