stMind

about Tech, Computer vision and Machine learning

Sentiment AnalysisをGloveで行う

前回の続き。

前回はEmbedding layerも含めて学習したが、学習済みのGloveを使う。

最初に、glove.6B.100d.txt(wordとembeddingを行単位で記述)をロードして、embedding_indexを作る。次に、imdb_reviewsデータセットのwordに対して、対応するgloveのembeddingを格納したembedding_matrixを作成。後は、modelの記述において、Embedding layerのweightsにembedding_matrixを与えて、学習しないようにTrainable=FalseとすればOK。

    embedding_index = {}
    with open('glove.6B.100d.txt') as f:
        for line in f:
            values = line.split()
            word = values[0]
            coefs = np.asarray(values[1:], dtype='float32')
            embedding_index[word] = coefs

    embedding_matrix = np.zeros((vocab_size + 1, embedding_dim))
    for word, i in word_index.items():
        embedding_vector = embedding_index.get(word)
        if embedding_vector is not None:
            embedding_matrix[i] = embedding_vector

    # Glove is used for embedding layer.
    model = tf.keras.Sequential([
        tf.keras.layers.Embedding(vocab_size + 1, embedding_dim, input_length=max_length, weights=[embedding_matrix], trainable=False),
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(6, activation='relu'),
        tf.keras.layers.Dense(1, activation='sigmoid')
    ])

CourseraのNLP in tensorflowを見てSentiment Analysisが容易に出来ると知る

www.coursera.org

tensorflow_datasetに用意されているimdb_reviewsデータセットを取得して、kerasのTokenizerを使って前処理して、Modelを書いて、学習。

これをテンプレートとして使えば、EmbeddingはBERTに変えたり、imdb_reviewsを自分で作ったデータセットにしたりして、拡張していけそう。

import tensorflow_datasets as tfds
import numpy as np

from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
import tensorflow as tf

if __name__ == "__main__":
    # 1. Load imdb dataset
    imdb, info = tfds.load('imdb_reviews', with_info=True, as_supervised=True)

    # 2. Split imdb dataset into train / test data
    train_data, test_data = imdb['train'], imdb['test']

    # 3. Prepare sentences and labels
    training_sentences = []
    training_labels = []

    testing_sentences = []
    testing_labels = []

    for s, l in train_data:
        training_sentences.append(str(s.numpy()))
        training_labels.append(l.numpy())

    for s, l in test_data:
        testing_sentences.append(str(s.numpy()))
        testing_labels.append(l.numpy())

    training_labels = np.array(training_labels)
    testing_labels = np.array(testing_labels)

    # 4. Hyperparameters
    vocab_size = 10000
    embedding_dim = 16
    max_length = 120
    trunc_type = 'post'
    oov_token = '<OOV>'

    # 5. Tokenize
    tokenizer = Tokenizer(num_words=vocab_size, oov_token=oov_token)
    tokenizer.fit_on_texts(training_sentences)
    word_index = tokenizer.word_index
    sequences = tokenizer.texts_to_sequences(training_sentences)
    padded = pad_sequences(sequences, maxlen=max_length, truncating=trunc_type)

    testing_sequences = tokenizer.texts_to_sequences(testing_sentences)
    testing_padded = pad_sequences(testing_sequences, maxlen=max_length, truncating=trunc_type)

    # 6. Defining model
    model = tf.keras.Sequential([
        tf.keras.layers.Embedding(vocab_size, embedding_dim, input_length=max_length),
        tf.keras.layers.Flatten(),
        tf.keras.layers.Dense(6, activation='relu'),
        tf.keras.layers.Dense(1, activation='sigmoid')
    ])

    # 7. Compile and training
    model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])
    model.summary()

    num_epochs = 10
    model.fit(padded, training_labels, epochs=num_epochs, validation_data=(testing_padded, testing_labels))
Model: "sequential_1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
embedding_1 (Embedding)      (None, 120, 16)           160000    
_________________________________________________________________
flatten_1 (Flatten)          (None, 1920)              0         
_________________________________________________________________
dense_2 (Dense)              (None, 6)                 11526     
_________________________________________________________________
dense_3 (Dense)              (None, 1)                 7         
=================================================================
Total params: 171,533
Trainable params: 171,533
Non-trainable params: 0
_________________________________________________________________
Epoch 1/10
782/782 [==============================] - 4s 5ms/step - loss: 0.5723 - accuracy: 0.7062 - val_loss: 0.4707 - val_accuracy: 0.8163
Epoch 2/10
782/782 [==============================] - 4s 5ms/step - loss: 0.3454 - accuracy: 0.8918 - val_loss: 0.4481 - val_accuracy: 0.8147
Epoch 3/10
782/782 [==============================] - 4s 5ms/step - loss: 0.1946 - accuracy: 0.9558 - val_loss: 0.5217 - val_accuracy: 0.8035
Epoch 4/10
782/782 [==============================] - 4s 5ms/step - loss: 0.1172 - accuracy: 0.9798 - val_loss: 0.5584 - val_accuracy: 0.8052
Epoch 5/10
782/782 [==============================] - 4s 5ms/step - loss: 0.0851 - accuracy: 0.9852 - val_loss: 0.6381 - val_accuracy: 0.8047
Epoch 6/10
782/782 [==============================] - 4s 5ms/step - loss: 0.0707 - accuracy: 0.9869 - val_loss: 0.6734 - val_accuracy: 0.8055
Epoch 7/10
782/782 [==============================] - 4s 5ms/step - loss: 0.0643 - accuracy: 0.9872 - val_loss: 0.7113 - val_accuracy: 0.8036
Epoch 8/10
782/782 [==============================] - 4s 5ms/step - loss: 0.0598 - accuracy: 0.9879 - val_loss: 0.7544 - val_accuracy: 0.8028
Epoch 9/10
782/782 [==============================] - 4s 5ms/step - loss: 0.0568 - accuracy: 0.9883 - val_loss: 0.7722 - val_accuracy: 0.8052
Epoch 10/10
782/782 [==============================] - 4s 5ms/step - loss: 0.0558 - accuracy: 0.9884 - val_loss: 0.8033 - val_accuracy: 0.8050

github.com

Tensorflowレポジトリのコミット数ランキングを表示するワンライナー

  1. git logコマンドのfomatオプションでauthor nameを出力
  2. sort
  3. uniq -cで連続する行数をカウント、重複行は削除
  4. sort -nrで降順にソート
  5. headで先頭から10件表示
$ git log --format='%an' | sort | uniq -c | sort -nr | head 
21995 A. Unique TensorFlower
3476 TensorFlower Gardener
1229 Yong Tang
1155 Shanqing Cai
1154 Derek Murray
1055 Gunhan Gulsoy
1046 Benoit Steiner
1036 Vijay Vasudevan
 865 River Riddle
 794 Martin Wicke

tensorflowのレポジトリをローカルに持ってない場合は、Github APIを使ってコミット履歴を取ってくる。(Pageを解釈するのはちょっと難しかったので置いといて...)

  1. wgetでcommitsをJSONで受け取る
  2. jqでjsonのauthor nameを抽出
  3. 上で実行した2以降の処理をする
$ wget -O - -q https://api.github.com/repos/tensorflow/tensorflow/commits?per_page=100 | jq '.[] | .commit.author.name' | sort | uniq -c | sort -nr | head
  16 "A. Unique TensorFlower"
   8 "TensorFlower Gardener"
   5 "Gunhan Gulsoy"
   4 "Yujing Zhang"
   3 "Zhenyu Tan"
   3 "Peter Hawkins"
   3 "Andy Ly"
   2 "tg-at-google"
   2 "Thomas O'Malley"
   2 "T.J. Alumbaugh"

以下のブログにインスパイアされてやってみました。

prithu.xyz

画像からの料理名推定

blog.stratospark.com

2017年なので少し前になりますが、画像から料理名を推定するプロジェクト。

InceptionV3のImageNet pre-trainedのモデルをFine tuningして、Food 101データセットで82.03% @ Top-1の精度が出たようです。

Food 101は、名前の通り101クラスで、各クラス1000画像含まれているので、メモリ上に展開すると80GB程度になるらしい。96GBのメモリを積んだマシンを使ったらしいが、これは富豪アプローチですね...

Data augmentationは、KerasのImageDataGeneratorで、 rotation_range、width_shift_range、height_shift_range、horizontal_flip、zoom_range、channel_shift_rangeあたりが使われてます。

学習は初期トライアルではAdamやAdaGradで試してたが、最終的にはSGDで学習。

ここから精度を上げるのは反復トライアルが必要な難しいタスクになりそうですが、スタート地点のBaselineとして使える気がします。

Baidu researchが作ったテキストからビデオを作成する技術

blog.deeplearning.ai

deeplearning.aiが発行しているnewsletterにあったVidPress。

URLを入力とすると、最初にWebページの内容を解析して、関連する記事も収集(解析には、Ernieというモデルが使われているよう)。 その後、テキストサマリを作成、サマリに関する合成音声を作成するのと、サマリに合う映像クリップを収集して、最後に映像と音声をアラインメントして出力する。

65%のユーザは、VidPressが作成したビデオを最後まで視聴したが、人が作成したビデオは途中で視聴をやめることが多かったという結果が得られたらしい。

これが未来のサッカー観戦か!Zoomでバーチャルスタンド

www.bbc.com

これからの時代のサッカー観戦はこうなるのかもしれない!

デンマークで行われたリーグ戦、当然ながら現地にファンはいないのだけど、スタジアムに設置された巨大スクリーンにはZoomにログインしたファンの姿が!!(動画は下のURLから)

https://www.espn.com/soccer/danish-sas-ligaen/story/4103225/danish-superliga-returns-in-front-of-supporters-on-zoom

40x2.8mのスクリーンに約200人のファンが映し出され、合計で1万人のファンがリアルタイムに観戦したようです。リモートとはいえ、選手はファンのリアクションが感じられるし、ファンも現地にいるような感覚になれるし、とても良い仕組みだと思う。

プレミアリーグも6月17日に再開されるようだし、感染拡大を予防しつつ、新しい体験を提供する仕組みづくりに取り組んでほしいなと思う。

Scene text detection/recognitionのためのTotal text dataset

GitHub - cs-chan/Total-Text-Dataset: Total Text Dataset. It consists of 1555 images with more than 3 different text orientations: Horizontal, Multi-Oriented, and Curved, one of a kind.

coco-textに対して40分の1くらいの画像数ですが、curved textのground truthを含むTotal-Text-Dataset。

アノテーションデータは、ここからダウンロード出来ます。 また、画像はこちらからダウンロード出来ます。

アノテーションはmatファイルで、下記のフォーマットで提供されています。

  • Column 1-2 = X-coordinate
  • Column 3-4 = Y-coordinate
  • Column 5 = Text
  • Column 6 = Orientation (c=curve; h=horizontal; m=multi-oriented; #=dont care)

画像に表示して確認してみました。下記のコードをipythonなどで実行すれば、別の画像にも同じように出来るはずです。

In [1]: import cv2

In [2]: import scipy.io as sio

In [3]: import numpy as np

In [4]: data = sio.loadmat('gt_img13.mat')

In [5]: img = cv2.imread('img13.jpg')

In [6]: for i in range(data['gt'].shape[0]):
   ...:     points = np.array([(x, y) for x, y in zip(data['gt'][i][1][0], data['gt'][i][3][0])], dtype=np.int32)
   ...:     cv2.polylines(img, [points], isClosed=True, color=(0, 255, 0), thickness=3)
   ...:     

In [7]: cv2.imshow('TEST', img)

In [8]: cv2.waitKey(0)

In [9]: cv2.destroyAllWindows()

f:id:satojkovic:20200528221125j:plain