stMind

about Tech, Computer vision and Machine learning

NLP for arsenal.com is difficult

スポナビライブの画面を開いたら、バギーズ戦の配信開始まで「1日と...」って明日かよー。

www.arsenal.com

最近というか、今年に入ってarsenal.comが変わった。試合毎に記事がまとまって見れるようになって、例えば上の vs Chelseaの記事は11本分がスクロールして見れるようになっている。スマホ対応ってことなんかな。

https://www.ostmodern.co.uk/projects/arsenal/arsenal-com/www.ostmodern.co.uk

2013年に以前のサイトから大規模なre-designがあって、その年と次の年はBest Website Awardをもらったとか。初めて知りましたよ。Ostmodernってデザイン会社が担当したみたい。 デザインは良くなったかもしれないけど、スクレイピングしてゴニョゴニョとかやりにくくなったような... 監督の発言だけを取り出したいんだけど、ある記事では使えるけど、別の記事では同じやり方は使えないとか。

明日の試合が終わったら、またちょっと試してみるかな。

Learning by Associationの論文を軽く読む

[1706.00909] Learning by Association - A versatile semi-supervised training method for neural networks

f:id:satojkovic:20170729175925p:plain (画像は論文より引用)

CVPR2017で発表された論文の一つ。ミュンヘン工科大学Googleの共著。 図にあるように、ラベルあり(A)とラベルなし(B)の画像が含まれるデータセットからCNNを学習する半教師あり学習のフレームワークの提案。

Associationというアイデアを導入。ラベルありの画像のembeddingと、ラベル無しの画像のembeddingを使って、図の赤矢印に示すように遷移後、異なるクラスになるとロスが発生する。

  • Walker loss
    • embeddingのdot productをsoftmaxとったものを遷移確率と考えて、A→B→Aとround tripした時の確率が以下の一様確率分布になるようにするロス
    • あるクラスのサンプルが、遷移して戻ってきた時に同じクラスのサンプルである確率は、1 /(Aの中でそのクラスのサンプルの総数)で、それ以外のクラスの場合は0
  • Visit loss
    • 全てのラベル無しサンプルに遷移するようにするロス
    • 1 / |B| の一様確率分布
  • Classification loss
    • 分類結果に対するロス
    • Walker lossとVisit lossだけでも収束する

MNISTとSVHN (Street View House Number)を使って評価。SVHNでラベルありサンプル500個のときにstate of the art。

CNNによるテキスト分類で学習済みword2vec(fastText)を使う

CNNとテキスト分類で検索すると、一番最初に出てくる[WildMLのチュートリアル]。

チュートリアルではembedding layerも含めて学習するようになっていますが、embeddingのところはFacebookが公開しているfastTextの学習済みword2vecで置き換えてやってみました。

github.com

変えたところは大きく3つの部分。

1. vocabとword_vecをfastTextからロード

英語の学習済みword2vecは6GBあって、gensimを使ってロードするのですが、毎回ロードしてると時間がかかってしまうので(20分近くかかる)、事前にvocabularyとword vectorsを別々のファイルに保存しておいて、そのファイルから読み込むようにしました。 後は、オリジナルと同じようにvocabulary indexの作成と、入力文中の単語をindexに変換しました。

print('Load pre-trained word vectors')
with open('fasttext_vocab_en.dat', 'rb') as fr:
    vocab = pickle.load(fr)
embedding = np.load('fasttext_embedding_en.npy')

pretrain = vocab_processor.fit(vocab.keys())
x = np.array(list(vocab_processor.transform(x_text)))

2. Embedding layerはfastTextをfeed

オリジナルでは、ランダムな値で初期化したWをembedding_lookupのparamとして、feedされる入力テキストの単語をベクトルにしていくのですが、Wは0で初期化して、placeholderとして受け取ったfastTextのword vectorsを代入して単語ベクトルに置き換えていきました。

W_ = tf.Variable(
    tf.constant(0.0, shape=[vocab_size, embedding_size]),
                trainable=False,
                name='W')
self.embedding_placeholder = tf.placeholder(
    tf.float32, [vocab_size, embedding_size],
    name='pre_trained')
W = tf.assign(W_, self.embedding_placeholder)

3. 学習

最後は、embeddingをfeed_dictで与えて学習をしました。

feed_dict = {
    cnn.input_x: x_batch,
    cnn.input_y: y_batch,
    cnn.dropout_keep_prob: FLAGS.dropout_keep_prob,
    cnn.embedding_placeholder: embedding
}

ロスとAccはこんな感じで進みました。

# The logs around step 1000 are as follows.
...
2017-07-08T13:12:27.329179: step 990, loss 0.178512, acc 0.953125
2017-07-08T13:12:28.902815: step 991, loss 0.133091, acc 0.984375
2017-07-08T13:12:30.473521: step 992, loss 0.148561, acc 0.984375
2017-07-08T13:12:32.041047: step 993, loss 0.21213, acc 0.90625
2017-07-08T13:12:33.617257: step 994, loss 0.230192, acc 0.9375
2017-07-08T13:12:35.223648: step 995, loss 0.222954, acc 0.9375
2017-07-08T13:12:36.822623: step 996, loss 0.161116, acc 0.96875
2017-07-08T13:12:38.437168: step 997, loss 0.224385, acc 0.921875
2017-07-08T13:12:40.073519: step 998, loss 0.258734, acc 0.921875
2017-07-08T13:12:41.649018: step 999, loss 0.207504, acc 0.953125
2017-07-08T13:12:43.215527: step 1000, loss 0.211571, acc 0.921875

Evaluation:
2017-07-08T13:12:44.823491: step 1000, loss 0.647888, acc 0.681

学習のロスは十分下がっていますが、Testのロスはそれに比べるとあまり下がっていきませんでした。過学習している様子なので、チューニングが必要そうです。

まとめ

CNNでテキスト分類するチュートリアルを、fastTextでやってみました。まとめてしまえばそれほど多くの変更はなかったのですが、いろいろ調べるのに1週間強はかかっていると思います。何かを身につけるのに簡単な道はないですね。

Try word2vec in 5 minutes

Task

word2vecを使ったテキスト分類の問題(質問文?回答文?)をやってみます。

Steps

  1. datasetの入手
  2. pre-trained modelの入手
  3. datasetとpre-trained modelのロード
  4. 学習
  5. 評価

1. datasetの入手

まずはデータセットが必要ですが、UCSD(カリフォルニア大学サンディエゴ校)の研究グループが、WWW2016で公開したAmazon question/answer dataを使います。

Amazon question/answer data

jsonの中身は、質問文、回答文の他に質問のタイプ(yes/noかopen-endedか)などが含まれていますが、ここでは質問文(questin)、回答文(answer)を使っていきます。

{'questionType': 'yes/no', 'asin': 'B00004U9JP', 'answerTime': 'Jun 27, 2014', 'unixTime': 1403852400, 'question': 'I have a 9 year old Badger 1 that needs replacing, will this Badger 1 install just like the original one?', 'answerType': '?', 'answer': 'I replaced my old one with this without a hitch.'}

2. pre-trained modelの入手

Google Newsのデータセットで学習されたmodelを使います。300万語の300次元ベクトルが含まれたmodelになっていて、3.4GBほどありますのでダウンロードには少し時間がかかります。下のページに、GoogleNews-vectors-negative300.bin.gzのリンクがあります。

https://code.google.com/archive/p/word2vec/

3. datasetとpre-trained modelのロード

pre-trained modelのロードはgensimを使えば簡単です。

# load pre-trained word2vec model
googlenews_w2v = gensim.models.KeyedVectors.load_word2vec_format('GoogleNews-vectors-negative300.bin', binary=True)

datasetの方はjson.loadを使いたい所ですが、シングルクォーテーションが使われていて、JSONDecodeErrorになってしまいます。仕方がないので、ast.literal_evalを使います。

# load datasets
# you cannot use json.load because this json file is invalid format...(using single quote)

questions = []
answers = []
with open('qa_Appliances.json', 'r') as f:
    for line in f:
        js = ast.literal_eval(line)
        questions.append(js['question'])
        answers.append(js['answer'])

参考。 stackoverflow.com

4. 学習

次は、学習です。 最初に、データセットを学習用とテスト用に分割します。

# Split dataset into train and test set
qa_texts = np.array(questions + answers)
qa_labels = np.zeros(len(qa_texts), dtype=np.int)
qa_labels[len(questions):] = 1  # question: 0, answer: 1

qa_idx = np.random.permutation(len(qa_texts))
qa_texts = qa_texts[qa_idx]
qa_labels = qa_labels[qa_idx]

X_train, X_test, y_train, y_test = train_test_split(qa_texts, qa_labels)

特徴量ベクトルの抽出は、シンプルに分類したいテキストに含まれる全単語のベクトルの平均を使うことにします。このアイデアは、下記のブログを参考にしました。また、識別器はRandomForestを使います。

nadbordrozd.github.io

# Simple word embedding feature by averaging word vectors for all words in a text
# ref: http://nadbordrozd.github.io/blog/2016/05/20/text-classification-with-word2vec/#comment-3233012354
class MeanEmbeddingVectorizer(object):
    def __init__(self, word2vec, dim):
        self.word2vec = word2vec
        self.dim = dim
        
    def fit(self, X, y):
        return self
    
    def transform(self, X):
        return np.array([
            np.mean([self.word2vec[w] for w in words if w in self.word2vec] or [np.zeros(self.dim)], axis=0)
            for words in X
        ])
# Train a model
rf_amazon_qa = Pipeline([
    ('word2vec', MeanEmbeddingVectorizer(googlenews_w2v, googlenews_w2v.vector_size)), 
    ('randomforest', RandomForestClassifier(n_estimators=200))])
rf_amazon_qa.fit(X_train, y_train)

5. 評価

最後に、テストデータに関して評価をします。結果は、8割弱の精度となりました。

# Evaluation
y_pred = rf_amazon_qa.predict(X_test)
print(classification_report(y_test, y_pred))
            precision    recall  f1-score   support

          0       0.77      0.81      0.79      2263
          1       0.80      0.76      0.78      2243

avg / total       0.78      0.78      0.78      4506

まとめ

色々調べてたら、とても5分では終わりませんでしたが、一旦わかってしまえば、再現するには5分程度で簡単に出来るのではないかと思います!全体のipynbは、下記にありますので参考まで。

github.com

アーセンベンゲル補完計画、始めました

先月末、ベンゲル監督が二年間の契約延長を発表しました。

www.arsenal.com

今シーズンは、就任以来初じゃないかと思うほどの不振が続いて、契約満了を迎える今シーズンで本当に辞めてしまうかもしれないと思いました。 とりあえず、契約更新は喜ばしいです。 契約更新したとはいえ、いつまでも続けられるわけではない。システム重視で、選手個人の創造性が制約される現代サッカーにおいて、 アタッキングサードでの攻撃には最大限の自由を与えるベンゲルスタイルと、選手は買うものではなく育てるものという哲学は ぜひとも後世に残したい。というわけで「補完計画」始めることにしました。

記者会見のQAからchar-rnnでベンゲル語録を学習

まずは、char-rnnを使って、単語レベルでベンゲル語録を学習し、ベンゲル監督らしい表現の生成に挑戦することとしました。

github.com

データセットは、アーセナル公式のニュースページから取得しました。char-rnnのREADMEによると、2MB以上のテキストデータを 推奨していたので、過去3年くらいのニュースを対象に学習データを作りましたが、結果をみると2MBだと、再現しているとは言い難いですね…

rnn_sizeを128で実行した結果。前後の文脈を考慮するにはサイズが小さいかもしれません。選手名やクラブ名は再現出来てたりはします。

pleing or any other game . is not a great situation . I could get on Saturday . That is what more than that a decision for the lead but as indipphit is that we didn’t stop . I haven got past and let. Nach there are not quickly as the 250 per cent it didn’t take this alent win , to perform , there were worked when he will play a talent achievement and I think overall they made a positive player , I hunnled a humatict inflacke in the game . The players are going to be played as well . You never know whether watching you old and he seemed the ball and when I started very well . We would have Ozil all his game . Once I think , we had quite about twick the keeper we should have not easy at the time in mone big aspects of our game , you could have right until the end of the season . I go for Sagna and Ozil beat Welbeck , we do not live that training after five , I just sait that someone . Cotgion was able to keep toam . We played the five years because we are in a player was ‘ win the league in their good squad well and we played with Olivier is always the day , I also lose us at home and overall I played well . We saw that he was his little to find it , I am surprising is something tellveted to see the new bysical is training . Giroud just very good confirmally . It was a responsiby in the club but let’s just not inflam knowred . On the sched is to the bench comfortably . Sometimes I wanted to do that . We have a big respect for us , he played at half-time and showed that they are disappointed and power or to do . I was success away to Emirates in the way it is a great game and who is great , but it’s a desperate things respects at Tottenham , to go out everybody and it was a very strong test for us and when you don’t improve our young players who is back there happy quich. Hents in the Premier League came on and Man City and we are going . He issunds it finished because we got back to his feet played a little bad . now he had chances away from home they do , t

次は、rnn_sizeを256にして実行した結果。多少のフレーズは生成されるようになった気がします。が、ベンゲル監督の言葉というよりは単にニュースっぽい。というのは、学習データセットで、ベンゲル監督の言葉以外の部分を含んでしまったかも?

oints then you have to keep some demans and they are in where . I had some uncertainties about how can we gain them losing that in the decisive those clubs where we may streak about [ the Liverpool team, I don’t see what the [ampers if you don’t want to just explating , you do not take our characters away . Ospina , the ] hardest physically straight away . has a strange game for the nervous guy ! is not the only thing we can doctict at all that in every day threat . We need to keep this resulting . In the second half the way we want to get a little bit with Chelsea and or the efurition to be a part of it, From South Anegation in the end it was important to him something that makes it on the way that every game and at the end we gave the penalty desire to do it . leader in training , he really not managed to go into the future supporters . , I don’t know whatos.. Alexis Sanchez has been [ Danny Welbeck ] , no matter how export about it . is a fantastic exappoint on six of our defensive players and you see some teams you all are on a visit one and I am confident that Stoke harm for you that about it in the squad last year but I don’t think I cannot completely ready many teams because it was good , and wherea…Buchmestants and finally played well , they were sort of guys like Stoke, we are confident that we ’ll be enough to bring . They were one of the better side today , that’s what we want to do . Szczesny , December 13Gerbracyna Believis , Alex Oxlade-Chamberlain 2-1 Republic or PolandWojciech Szczesny played the full 90 minutes and calm helped Craik Premier League attacled at Rocalem . Consick or £24 ( or 18 ) to know ( will period because he ’s the right movement and into the top close this matchesterscinal because when he hasn’t enjoyed it . ..That ’s a really good cost or not . But after that Theo’s passigh , there was now behind many times . We won all player oncesively fans pressuress .

補完計画の今後

もう少し学習データセットを増やして、rnn_sizeも大きくして試してみたい。 ベンゲル監督の哲学をいつまでも残すために…

MacとLinuxでディレクトリ内ファイルリストを取得する時の挙動が違う?

以前作ったDeep Learningを使ったブランドロゴ認識だけど、ありがたいことに使ってくれる方がいて、githubにissueが来ました。

github.com

27クラスのロゴ画像をそれぞれ学習用、テスト用に分けてpickle化するスクリプトでエラーになるということらしい。Issueにあがってるエラーログを見ると、Macで実行したときと、ファイルリストを取得した結果が違っている。OSXで実行した時は、各ロゴのtestとtrainが交互で、かつソートされているので、パスのリストであるtrain_test_dirsっていう変数から、train_test_dirs[0::2]でtestのリストだけをpickleにして、train_test_dirs[1::2]でtrainのリストだけをpickleにするような処理をしていた。要は各フォルダがtest→trainという順番になっていることを想定していた。(フォルダパスをリストにするだけなのに、実際のフォルダ構成を調べて処理しなくてもよいのだけど)

train_datasets = maybe_pickle(train_test_dirs[1::2])  # trainをpickle化
test_datasets = maybe_pickle(train_test_dirs[0::2])  # testをpickle化

OSXでのリストはこんな感じ。

Adidas/test
Adidas/train
Apple/test
Apple/train
BMW/test
BMW/train
(以下略)

一方で、どのDistributionかはわからないけど、Linuxで実行したらしき結果はこんな感じ。

Texaco/train
Texaco/test
Starbucks/train
Starbucks/test
Mini/train
Mini/test
(以下略)

ソートされてないし、trainとtestの順序が逆になっている。とりあえず、リストをスライスするときに、最初がtrainで次がtestになるように、

train_datasets = maybe_pickle(train_test_dirs[0::2])  # 最初(0)がtrain
test_datasets = maybe_pickle(train_test_dirs[1::2])  # 次(1)がtest

と変更してもらったら、エラーは出なくなったようだ。ちなみに、centosだとエラーだったけど、debianにしたら動いた、という方もいた。

結局

StackOverflowに回答あるみたいだけど、MacLinuxというか、FileSystemによって順番は違っていて、順番を固定した処理がしたければos.listdirでリストを取得した後に明示的にソートしておくということか。stackoverflow.com

研究を売れ

研究を売れ!―ソニーコンピュータサイエンス研究所のしたたかな技術経営

研究を売れ!―ソニーコンピュータサイエンス研究所のしたたかな技術経営

ソニーコンピュータサイエンス研究所(CSL)の研究成果を実用化する研究営業組織、テクノロジープロモーションオフィス(TPO)の設立、活動内容とその手法に関する本です。

企業における研究開発の理想

企業に所属する研究者、開発者の立場から見て、研究開発の理想形とは何かと考えると、一つには次のような流れではないだろうか。

  1. 研究者の思いに基づいて研究が始まる
  2. トップカンファレンスに採択されるなど、研究が外部で認められる
  3. 社内の事業部に移管され、製品やサービスに実装される
  4. 製品やサービスが公開され、広く世の中で使われる

例えば、Jamie Shottonさん達のRandom Forestを使った姿勢推定の研究が、CVPR2010のベストペーパーになって、ゲームデバイスとして発売、2013年のデータですが全世界で2400万台も出荷されたKinect。改めて思うに、こういう研究が出来れば言うことないですね!

現実、そして研究営業を行うTPO

しかし、現実にはこんな風にうまくいく研究開発はなかなかない。書籍によると、研究から具体的な商品に結びついた成功事例は1万件に1件くらいじゃないかということなんで、ほとんどがうまくいかない!というのは実感としてわかるなぁと思うところです。実際、研究を事業にする際には、研究をしている部隊ごと事業部門に移管したり、研究している技術だけを移管したりすることが一般的に行われますが、いずれの場合でも移管をいかに効果的に行うかが課題となっていて、そこで、CSLの研究成果を実用に結びつけるための研究営業をメインに行う組織であるTPOが設立されたそうです。

試行錯誤と教訓

書籍では、実際の研究営業のやり方について、様々な事例を通して語られています。

  • 他の企業とのコラボ
  • 外部の人に使ってもらう
  • 社内の他部門との繋がりを大事にする
  • スピンアウトして事業をする会社を立ち上げる
  • 出張デモ
  • デモを実際に見てくれた人にだけ送るメルマガ

これらを読んでみると、よく言われている技術移管のための取り組みを愚直に実践しているのだなというのがわかりましたし、王道はないというのもその通りだなと思いました。結局、地道に続けていくしかないんですよね。こういった取り組みを繰り返し行なって環境など様々な条件が揃った時、書籍内の言葉で言うと時間と空間を超えて実用化に適したタイミングにハマった時に、CybercodeやPOBoxなどの成功事例が出て来るのだと思います。著者の方が、この研究営業を10年続けて得られた教訓、ぜひ書籍を見て内容を把握してほしいですが、項目だけ引用しておきます。

  • 全ては研究を出すタイミングにかかっている
  • 必要なコネはなんでも使え
  • 組織に対する先入観をもってはいけない
  • 顧客に対しては、ほぼ伝らない、という前提で努力すべし
  • メンタルを鍛えろ
  • 前例のないやり方を試せ
  • 一分一秒でも早く動くべし
  • 技術を移管した後も追い続けるべし
  • 単なる研究営業ではなく、研究プロデュースを目指すべし
  • 常に研究所のための営業であることを自覚せよ

さいごに

CSLほどの基礎研究ではないですが、応用研究に近い立場で長く仕事をしている身として、どういう考えで、どのフェーズに貢献すべきかというのは常に思っているところだったので、そのものズバリな書籍で非常に参考になりました。繰り返しになりますが、自分の思いとしては、KinectのJamie Shottonのように研究を立ち上げて、それを論文にして、さらに製品化にも関わって、という最初から最後まで中心で関わるというのが理想ではあるんですけどね。自分一人ではなく、チームでこれを目指せばいいよなと、読み終えた後に感じることが出来たので、これから少しずつ行動していきたいですね。