駆け出しエンジニアの作業ノート

駆け出しエンジニアが作業ノート風にまとめるページ(関係無い事もしばしば)

【サポーターズCoLab勉強会】実務で使う自然言語処理をするに行ってきました

2月27日に【サポーターズCoLab勉強会】実務で使う自然言語処理をするがあったので、行ってきました。

 

supporterzcolab.com

www.slideshare.net

github.com

 

まず、自分の認識として、先端のはやり技術とビジネス最前線で使える技術には落差があるのは改めて再認識出来たと感じています。

 

参考になった部分としては、キーワード索引の重要性だと思います。日本語を形態素分析すると、どうしても助詞や助動詞が形態素数を計測すると上位に来てしまいます。そうなると、形態素から文章の内容を類推する事が難しくなってしまいます。そういった意味では重要な手法だと思いました。

 

懇親会では、機械学習エンジニアのあるべき姿についての話になりました。機械学習のコンペとしてKaggleが世界的に有名です。

www.kaggle.com

Kaggle: Your Home for Data Science

しかし、Kaggleの上位ランカーと会うと意外な事実があるとの事でした。実は、一部だと思うのですが、用いた手法に関して中身を理解していないという事でした。結局中身を説明出来なければその先に話が発展しないというものでした。近頃、Kaggleの成績を採用の指標として用いている企業があると聞きましたが、このようなデメリットがあることが理解出来ました。

 

機械学習で用いられる数学は大変高度なものですが、この中身を理解することによってエンジニアとしての中身をより向上出来ると確信した時間でした。

第25回 Pythonもくもく会に行ってきました

2月24日に「第25回 Pythonもくもく会」に行ってきました。

 

mokupy.connpass.com

 

1回参加申し込みをしたのですが、都合が付かなくなったので、今回初めて参加しました。名前とする事をホワイトボードに記載して、自己紹介する形式でスタートしました。Python限定のため、機械学習の方が多いと思いましたが、Djangoの方が多く、ビックリしました。昼食時には色々と情報交換が出来ました。都合により、昼食後離脱してしまいましたが、今後も定期的に参加しようと思います。

API Meetup Tokyo #24 に行ってきました

2月23日に「API Meetup Tokyo #24 〜スマートスピーカーAPI連携〜」という勉強会があり参加してきました。会場は高円寺にあるヴァル研究所でした。

 

api-meetup.doorkeeper.jp

 

ヴァル研究所といえば、「駅すぱあと」で有名な会社であり、折しも勉強会の前日に誕生30周年を迎えたとの事でした。実は私は路線図機能が無かったWin95の時代より駅すぱあとを使用しており、一度訪問したい企業の1つでもありました。

 

駅すぱあと

駅すぱあと

  • Val Laboratory Corporation
  • ナビゲーション
  • 無料
駅すぱあと(Windows)2017年12月

駅すぱあと(Windows)2017年12月

 

 

社内には91年以降の時刻表がずらりと、本棚に収納されていたり、会議室の名称が「つばさ」や「こまち」といった新幹線の名称になっているなどのこだわりがありました。

 

内容ですが、LINEの方よりClovaに関して開発者向けの新機能についてお話しがありました。ただ、詳細については正式発表を待って欲しいとの事でしたので、記載については見送らせて頂きます。

 

懇親会では、ヴァル研究所の方とお話ししました。駅すぱあとの開発秘話を伺いました。初期の頃はPCの性能がそこまで良くなかった為、いかにメモリを消費しないで書くかに留意をしたそうです。しかし、今ではかえってコードの可読性が下がるというデメリットになってしまっているようです。貴重なお話しを伺えました。今後も折りを見て、色々と足を運んでみたいと思います。

プレイリスト生成の検証終了

コードのtry文を移動させたところ、きちんと動作して最後までたどり着いたので記載させて頂きます。

 

import psycopg2
import psycopg2.extras
from gensim.models import word2vec

host_name =
port_number =
dbname =
rolename =
passwd =

def track_search():
conn = psycopg2.connect(database=dbname, host=host_name, port=port_number, user=rolename, password=passwd)
cur = conn.cursor()
cur.execute("SELECT DISTINCT artist, song FROM track_data")
track_list = cur.fetchall()
conn.close()
return track_list

def call_model():
track_list = track_search()
high_score = 0
high_score_track = ""
search_track = ""
for i in range(len(track_list)):
track = track_list[i]
artist = track[0]
song = track[1]
input_data = artist + " - " + song
model = word2vec.Word2Vec.load("similar_song.model")
try:
data = model.most_similar(positive=[input_data])
high_score_track_data_each_song = data[0]
high_score_track_each_song = high_score_track_data_each_song[0]
high_score_each_song = high_score_track_data_each_song[1]
if high_score_each_song > high_score:
high_score = high_score_each_song
high_score_track = high_score_track_each_song
search_track = track
print("New record!")
print(search_track)
print(high_score_track)
print(high_score)
else:
continue
except KeyError:
print("pass")
continue


if __name__ == '__main__':
call_model()

 

 

結果は以下になり、前日暫定で出した数値を上回りました。

 

 ('Teresa Cristina e Grupo Semente', 'A Borboleta e o Passarinho')
KRD8 - 蒼いピストル ~らいらら第二章~
0.5622042417526245

 

これは、「Teresa Cristina e Grupo Semente」の「A Borboleta e o Passarinho」に最も近い曲として「KRD8」の「蒼いピストル ~らいらら第二章~」が抽出され類似度の数値は全学習データのうち最も高いという事になります。

 

O Mundo É Meu Lugar - Ao Vivo

O Mundo É Meu Lugar - Ao Vivo

 
Dream Rainbow ?次のステージへ一緒に行こう!?

Dream Rainbow ?次のステージへ一緒に行こう!?

 

 相変わらず、ジャンルの垣根を越えています… なお、それ以外の結果は以下の通りです。

[('KRD8 - 蒼いピストル ~らいらら第二章~', 0.5622042417526245), ('Jax Jones - Instruction', 0.4197536110877991), ('miwa - サヨナラ', 0.39838463068008423), ('Detlef Keller - Way 5', 0.3839055299758911), ("Ike Quebec - I've Got a Crush On You", 0.38365036249160767), ("Marty Paich - What's new?", 0.35652440786361694), ('a flood of circle - 春の嵐', 0.3534770607948303), ("Gigi Gryce - Nica's Tempo", 0.3506496250629425), ('Martha Argerich - Fantasiestücke, Op 12: Warum?', 0.34342825412750244), ('Wiener Philharmoniker - Smetana: Má Vlast, JB1:112 - 2. Vltava', 0.3430880308151245)]
 

 上記の結果を出したコードは以下を参照して下さい。

 

 

psyduck-take-it-easy.hatenablog.com

 

 

Instruction [feat. Demi Lovato & Stefflon Don] [Explicit]

Instruction [feat. Demi Lovato & Stefflon Don] [Explicit]

 
サヨナラ

サヨナラ

  • miwa
  • J-Pop
  • ¥250
  • provided courtesy of iTunes
Way 5

Way 5

 
I've Got a Crush On You

I've Got a Crush On You

  • provided courtesy of iTunes
What's New?

What's New?

  • マーティ・ペイチ
  • ジャズ
  • ¥150
  • provided courtesy of iTunes
春の嵐

春の嵐

  • provided courtesy of iTunes
Nica's Tempo

Nica's Tempo

  • ジジ・グライス
  • ジャズ
  • ¥250
  • provided courtesy of iTunes
Fantasiestücke, Op. 12: Fantasiestücke, Op. 12: III. Warum?

Fantasiestücke, Op. 12: Fantasiestücke, Op. 12: III. Warum?

 
スメタナ:交響詩「わが祖国」全曲、他

スメタナ:交響詩「わが祖国」全曲、他

 

 

 

 

Word2Vecを用いたプレイリスト生成の結果報告

Word2Vecを用いたプレイリスト学習の結果が出たのでご報告します。検証用に、以下のコードを書きました。

 

import psycopg2
import psycopg2.extras
from gensim.models import word2vec

host_name =
port_number =
dbname =
rolename =
passwd =

def track_search():
conn = psycopg2.connect(database=dbname, host=host_name, port=port_number, user=rolename, password=passwd)
cur = conn.cursor()
cur.execute("SELECT DISTINCT artist, song FROM track_data")
track_list = cur.fetchall()
conn.close()
return track_list

def call_model():
track_list = track_search()
high_score = 0
high_score_track = ""
search_track = ""
try:
for i in range(len(track_list)):
track = track_list[i]
artist = track[0]
song = track[1]
input_data = artist + " - " + song
model = word2vec.Word2Vec.load("similar_song.model")
data = model.most_similar(positive=[input_data])
high_score_track_data_each_song = data[0]
high_score_track_each_song = high_score_track_data_each_song[0]
high_score_each_song = high_score_track_data_each_song[1]
if high_score_each_song > high_score:
high_score = high_score_each_song
high_score_track = high_score_track_each_song
search_track = track
print("New record!")
print(search_track)
print(high_score_track)
print(high_score)
else:
continue
except KeyError:
print("pass")
pass


if __name__ == '__main__':
call_model()

 

 

途中で、エラーが起きてしまい暫定の最終結果は以下のようになりました。

 

('Yo-Yo Ma', 'The Swan from Carnival of the Animals')
Sonny Rollins - I Feel a Song Coming On
0.5421106815338135 

 

これは、「Yo-Yo Ma」の「The Swan from Carnival of the Animals」を呼び出した所、「Sonny Rollins」の「I Feel a Song Coming On」が最も近いという事になります。また、数値は全モデルの中で最も高くなりました。(暫定)

 

The Swan from Carnival of the Animals

The Swan from Carnival of the Animals

  • provided courtesy of iTunes

ヨーヨーマ氏は世界的に有名なチェリストで、今回はサン・サーンス作曲の「動物の謝肉祭」より「白鳥」が全学習データのうち最も高い値を示しました。この曲と類似度が高いとされたのは、アメリカのジャズサックス奏者ソニー・ロリンズ氏の「I Feel a Song Coming On」でした。

 

I Feel a Song Coming On

I Feel a Song Coming On

  • provided courtesy of iTunes

 

では、「Yo-Yo Ma」の「The Swan from Carnival of the Animals」を以下のコードに入れて詳しく見てみます。

 

from gensim.models import word2vec

artist = input("アーティスト名を入力して下さい")
song = input("曲名を入力して下さい")
input_data = artist + " - " + song
model = word2vec.Word2Vec.load("similar_song.model")
data = model.most_similar(positive=[input_data])
print(data)

 

 

結果は、以下のようになりました。

 

[('Sonny Rollins - I Feel a Song Coming On', 0.5421106815338135), ("Philippe Lavil - Elle Préfère L'Amour En Mer", 0.40646299719810486), ('Claudine Longet - What Have They Done To My Song, Ma', 0.39044189453125), ('Wes Montgomery - Airegin', 0.3878239393234253), ('Sambrasa Trio - Nem O Mar Sabia', 0.3471757769584656), ('Art Pepper - Tin Tin Deo', 0.3459215760231018), ('Caetano Veloso - Carolina', 0.3435187041759491), ('新山詩織 - 絶対', 0.34327659010887146), ('マルタ・アルゲリッチ - Chopin: Mazurka No.37 In A Flat Op.59 No.2', 0.3389737606048584), ('Zagreb Guitar Quartet - Prelude (BWV 541)', 0.33820152282714844)]
 

 

最初の曲は既に、紹介したのでほかの曲はリンクのみ貼っておきます。

 

Elle préfère l'amour en mer

Elle préfère l'amour en mer

  • Philippe Lavil
  • フレンチポップ
  • ¥200
  • provided courtesy of iTunes
傷ついた小鳥

傷ついた小鳥

  • provided courtesy of iTunes
Airegin

Airegin

  • provided courtesy of iTunes
Sambrasa Trio Em Som Maior

Sambrasa Trio Em Som Maior

 
Tin Tin Deo

Tin Tin Deo

  • provided courtesy of iTunes
Carolina

Carolina

  • provided courtesy of iTunes
絶対

絶対

  • provided courtesy of iTunes

Zagreb Guitar Quartet

  • クラシック

 

クラシック音楽もあれば、それ以外の楽曲も混ざっており何とも言い難い状況です。最も、Word2Vecが成功した場合には数値が悪くても0.6以上を示しているので学習量を増やして対応してみようと考えています。

 

Word2Vecを使ったプレイリスト生成実験

少し日が空いてしまいましたが、学習は継続しています。プレイリスト生成についてですが、Word2Vecを用いたモデル構築を行うことにしました。

 

文章の分かち書きの手法を応用し、Last.fmの書式にならい「アーティスト名 - 曲名」を単語とし、Last.fmの類似度データを使って、類似度が高いアイテムの集合をプレイリストとみなして、学習させることにしました。

 

次のようなコードを書いてみました。

 

 

import psycopg2
import psycopg2.extras
from gensim.models import word2vec

host_name =
port_number =
dbname =
rolename =
passwd =

def track_search():
conn = psycopg2.connect(database=dbname, host=host_name, port=port_number, user=rolename, password=passwd)
cur = conn.cursor()
cur.execute("SELECT DISTINCT artist, song FROM track_data")
track_list = cur.fetchall()
conn.close()
return track_list

def similar_artist_search():
conn = psycopg2.connect(database=dbname, host=host_name, port=port_number, user=rolename, password=passwd)
cur = conn.cursor()
track_list = track_search()
model_dev = []
for i in range(len(track_list)):
track = track_list[i]
print(track)
cur.execute("SELECT to_artist, to_song FROM similar_track WHERE from_artist = %s AND from_song = %s AND match_index > 0.01", track)
similar_track_list = cur.fetchall()
similar_track_list.append(track)
print(similar_track_list)
similar_group = []
for j in range(len(similar_track_list)):
track = similar_track_list[j]
artist = track[0]
song = track[1]
artist_song = artist + " - " + song
print(artist_song)
similar_group.append(artist_song)
print(similar_group)
model_dev.append(similar_group)
print(model_dev)
model = word2vec.Word2Vec(model_dev, size=100, min_count=1, window=5, iter=3)
model.save("similar_song.model")


if __name__ == '__main__':
similar_artist_search()

 

途中中断もあり、まだ終わっていませんがモデル構築が終了次第、結果をお知らせしようと思います。

アイテムベースの協調フィルタリング

以下の本を購入して、協調フィルタリングの勉強をしています。

 

 

集合知プログラミング

集合知プログラミング

 

 

ユーザーベースでの推薦だとユーザー数が増えるほど計算が膨大となる一方で、アイテムベースの協調フィルタリングでは、アイテム間の類似度計算のメンテナンスが大変なぶんレコメンドが容易になると書かれていました。

 

Last.fmに話を置き換えると、既に楽曲の類似度についてはAPIで提供されており、それを使えば良いという方向に話が落ち着きます。ただ、Last.fmというサービス自体が元々イギリス発祥で有る事から、日本でメジャー楽曲でも楽曲間類似度が計算されていない楽曲が多数存在します。そのため、現段階での自分の中での課題は、楽曲間類似度が計算されていない楽曲同士をどのように結び付けるかです。なお、自分が楽曲間類似度をもとにプレイリストを生成するプログラムは以下で公開させて頂いております。

 

github.com

 

ベイズ統計の本を読みながら検討してみます。