チャットボット作製記録 20180218

チャットボット作製記録
02 /18 2018
停止したと思っていましたが、まだ生きていました!


20180218_1.jpg



跡形もなく消えていると思っていたので、びっくりしました。
ちなみに、ボットの編集を行うアカウントは死んでいるみたいです。



20180218_2.jpg


いつまで動くか分かりませんが、やっぱり動いているところをみると嬉しいですね。
しかしながら、まるで作製したチャットボットが人質にされているみたいだ・・・。

今日はここまでです。
スポンサーサイト

Tensorflowのチュートリアル備忘録 2018/02/15

Tensorflowのチュートリアル
02 /15 2018
チュートリアルの中身が変わってしまったので、ホームに保存してあった以前のコードを記述しておきます。

・ 2017年11月12日付の記事、Getting Started With TensorFlow のコード。

import tensorflow as tf
# Model parameters
W = tf.Variable([.3], dtype=tf.float32)
b = tf.Variable([-.3], dtype=tf.float32)
# Model input and output
x = tf.placeholder(tf.float32)
linear_model = W * x + b
y = tf.placeholder(tf.float32)
# loss
loss = tf.reduce_sum(tf.square(linear_model - y)) # sum of the squares
# optimizer
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
# training data
x_train = [1, 2, 3, 4]
y_train = [0, -1, -2, -3]
# training loop
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init) # reset values to wrong
for i in range(1000):
    sess.run(train, {x: x_train, y: y_train})
# evaluate training accuracy
curr_W, curr_b, curr_loss = sess.run([W, b, loss], {x: x_train, y: y_train})
print("W: %s b: %s loss: %s"%(curr_W, curr_b, curr_loss))



・ 2017年11月12日付の記事、tf.estimatorに関するコード、その1。

import tensorflow as tf
# NumPy is often used to load, manipulate and preprocess data.
import numpy as np
# Declare list of features. We only have one numeric feature. There are many
# other types of columns that are more complicated and useful.
feature_columns = [tf.feature_column.numeric_column("x", shape=[1])]
# An estimator is the front end to invoke training (fitting) and evaluation
# (inference). There are many predefined types like linear regression,
# linear classification, and many neural network classifiers and regressors.
# The following code provides an estimator that does linear regression.
estimator = tf.estimator.LinearRegressor(feature_columns=feature_columns)
# TensorFlow provides many helper methods to read and set up data sets.
# Here we use two data sets: one for training and one for evaluation
# We have to tell the function how many batches
# of data (num_epochs) we want and how big each batch should be.
x_train = np.array([1., 2., 3., 4.])
y_train = np.array([0., -1., -2., -3.])
x_eval = np.array([2., 5., 8., 1.])
y_eval = np.array([-1.01, -4.1, -7, 0.])
input_fn = tf.estimator.inputs.numpy_input_fn(
    {"x": x_train}, y_train, batch_size=4, num_epochs=None, shuffle=True)
train_input_fn = tf.estimator.inputs.numpy_input_fn(
    {"x": x_train}, y_train, batch_size=4, num_epochs=1000, shuffle=False)
eval_input_fn = tf.estimator.inputs.numpy_input_fn(
    {"x": x_eval}, y_eval, batch_size=4, num_epochs=1000, shuffle=False)
# We can invoke 1000 training steps by invoking the  method and passing the
# training data set.
estimator.train(input_fn=input_fn, steps=1000)
# Here we evaluate how well our model did.
train_metrics = estimator.evaluate(input_fn=train_input_fn)
eval_metrics = estimator.evaluate(input_fn=eval_input_fn)
print("train metrics: %r"% train_metrics)
print("eval metrics: %r"% eval_metrics)



・ 2017年11月12日付の記事、A custom modelに関するコード。

import numpy as np
import tensorflow as tf
# Declare list of features, we only have one real-valued feature
def model_fn(features, labels, mode):
  # Build a linear model and predict values
  W = tf.get_variable("W", [1], dtype=tf.float64)
  b = tf.get_variable("b", [1], dtype=tf.float64)
  y = W * features['x'] + b
  # Loss sub-graph
  loss = tf.reduce_sum(tf.square(y - labels))
  # Training sub-graph
  global_step = tf.train.get_global_step()
  optimizer = tf.train.GradientDescentOptimizer(0.01)
  train = tf.group(optimizer.minimize(loss),
                   tf.assign_add(global_step, 1))
  # EstimatorSpec connects subgraphs we built to the
  # appropriate functionality.
  return tf.estimator.EstimatorSpec(
      mode=mode,
      predictions=y,
      loss=loss,
      train_op=train)
estimator = tf.estimator.Estimator(model_fn=model_fn)
# define our data sets
x_train = np.array([1., 2., 3., 4.])
y_train = np.array([0., -1., -2., -3.])
x_eval = np.array([2., 5., 8., 1.])
y_eval = np.array([-1.01, -4.1, -7, 0.])
input_fn = tf.estimator.inputs.numpy_input_fn(
    {"x": x_train}, y_train, batch_size=4, num_epochs=None, shuffle=True)
train_input_fn = tf.estimator.inputs.numpy_input_fn(
    {"x": x_train}, y_train, batch_size=4, num_epochs=1000, shuffle=False)
eval_input_fn = tf.estimator.inputs.numpy_input_fn(
    {"x": x_eval}, y_eval, batch_size=4, num_epochs=1000, shuffle=False)
# train
estimator.train(input_fn=input_fn, steps=1000)
# Here we evaluate how well our model did.
train_metrics = estimator.evaluate(input_fn=train_input_fn)
eval_metrics = estimator.evaluate(input_fn=eval_input_fn)
print("train metrics: %r"% train_metrics)
print("eval metrics: %r"% eval_metrics)



・ MNIST For ML Beginners に関するコード。

# Copyright 2015 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""A very simple MNIST classifier.
See extensive documentation at
https://www.tensorflow.org/get_started/mnist/beginners
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import sys
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
FLAGS = None
def main(_):
  # Import data
  mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True)
  # Create the model
  x = tf.placeholder(tf.float32, [None, 784])
  W = tf.Variable(tf.zeros([784, 10]))
  b = tf.Variable(tf.zeros([10]))
  y = tf.matmul(x, W) + b
  # Define loss and optimizer
  y_ = tf.placeholder(tf.float32, [None, 10])
  # The raw formulation of cross-entropy,
  #
  #   tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(tf.nn.softmax(y)),
  #                                 reduction_indices=[1]))
  #
  # can be numerically unstable.
  #
  # So here we use tf.nn.softmax_cross_entropy_with_logits on the raw
  # outputs of 'y', and then average across the batch.
  cross_entropy = tf.reduce_mean(
      tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))
  train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
  sess = tf.InteractiveSession()
  tf.global_variables_initializer().run()
  # Train
  for _ in range(1000):
    batch_xs, batch_ys = mnist.train.next_batch(100)
    sess.run(train_step, feed_dict={x: batch_xs, y_: batch_ys})
  # Test trained model
  correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
  accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
  print(sess.run(accuracy, feed_dict={x: mnist.test.images,
                                      y_: mnist.test.labels}))
if __name__ == '__main__':
  parser = argparse.ArgumentParser()
  parser.add_argument('--data_dir', type=str, default='/tmp/tensorflow/mnist/input_data',
                      help='Directory for storing input data')
  FLAGS, unparsed = parser.parse_known_args()
  tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)



・ Deep MNIST for Experts に関するコード。

# Copyright 2015 The TensorFlow Authors. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ==============================================================================
"""A deep MNIST classifier using convolutional layers.
See extensive documentation at
https://www.tensorflow.org/get_started/mnist/pros
"""
# Disable linter warnings to maintain consistency with tutorial.
# pylint: disable=invalid-name
# pylint: disable=g-bad-import-order
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import argparse
import sys
import tempfile
from tensorflow.examples.tutorials.mnist import input_data
import tensorflow as tf
FLAGS = None
def deepnn(x):
  """deepnn builds the graph for a deep net for classifying digits.
  Args:
    x: an input tensor with the dimensions (N_examples, 784), where 784 is the
    number of pixels in a standard MNIST image.
  Returns:
    A tuple (y, keep_prob). y is a tensor of shape (N_examples, 10), with values
    equal to the logits of classifying the digit into one of 10 classes (the
    digits 0-9). keep_prob is a scalar placeholder for the probability of
    dropout.
  """
  # Reshape to use within a convolutional neural net.
  # Last dimension is for "features" - there is only one here, since images are
  # grayscale -- it would be 3 for an RGB image, 4 for RGBA, etc.
  with tf.name_scope('reshape'):
    x_image = tf.reshape(x, [-1, 28, 28, 1])
  # First convolutional layer - maps one grayscale image to 32 feature maps.
  with tf.name_scope('conv1'):
    W_conv1 = weight_variable([5, 5, 1, 32])
    b_conv1 = bias_variable([32])
    h_conv1 = tf.nn.relu(conv2d(x_image, W_conv1) + b_conv1)
  # Pooling layer - downsamples by 2X.
  with tf.name_scope('pool1'):
    h_pool1 = max_pool_2x2(h_conv1)
  # Second convolutional layer -- maps 32 feature maps to 64.
  with tf.name_scope('conv2'):
    W_conv2 = weight_variable([5, 5, 32, 64])
    b_conv2 = bias_variable([64])
    h_conv2 = tf.nn.relu(conv2d(h_pool1, W_conv2) + b_conv2)
  # Second pooling layer.
  with tf.name_scope('pool2'):
    h_pool2 = max_pool_2x2(h_conv2)
  # Fully connected layer 1 -- after 2 round of downsampling, our 28x28 image
  # is down to 7x7x64 feature maps -- maps this to 1024 features.
  with tf.name_scope('fc1'):
    W_fc1 = weight_variable([7 * 7 * 64, 1024])
    b_fc1 = bias_variable([1024])
    h_pool2_flat = tf.reshape(h_pool2, [-1, 7*7*64])
    h_fc1 = tf.nn.relu(tf.matmul(h_pool2_flat, W_fc1) + b_fc1)
  # Dropout - controls the complexity of the model, prevents co-adaptation of
  # features.
  with tf.name_scope('dropout'):
    keep_prob = tf.placeholder(tf.float32)
    h_fc1_drop = tf.nn.dropout(h_fc1, keep_prob)
  # Map the 1024 features to 10 classes, one for each digit
  with tf.name_scope('fc2'):
    W_fc2 = weight_variable([1024, 10])
    b_fc2 = bias_variable([10])
    y_conv = tf.matmul(h_fc1_drop, W_fc2) + b_fc2
  return y_conv, keep_prob
def conv2d(x, W):
  """conv2d returns a 2d convolution layer with full stride."""
  return tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='SAME')
def max_pool_2x2(x):
  """max_pool_2x2 downsamples a feature map by 2X."""
  return tf.nn.max_pool(x, ksize=[1, 2, 2, 1],
                        strides=[1, 2, 2, 1], padding='SAME')
def weight_variable(shape):
  """weight_variable generates a weight variable of a given shape."""
  initial = tf.truncated_normal(shape, stddev=0.1)
  return tf.Variable(initial)
def bias_variable(shape):
  """bias_variable generates a bias variable of a given shape."""
  initial = tf.constant(0.1, shape=shape)
  return tf.Variable(initial)
def main(_):
  # Import data
  mnist = input_data.read_data_sets(FLAGS.data_dir, one_hot=True)
  # Create the model
  x = tf.placeholder(tf.float32, [None, 784])
  # Define loss and optimizer
  y_ = tf.placeholder(tf.float32, [None, 10])
  # Build the graph for the deep net
  y_conv, keep_prob = deepnn(x)
  with tf.name_scope('loss'):
    cross_entropy = tf.nn.softmax_cross_entropy_with_logits(labels=y_,
                                                            logits=y_conv)
  cross_entropy = tf.reduce_mean(cross_entropy)
  with tf.name_scope('adam_optimizer'):
    train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)
  with tf.name_scope('accuracy'):
    correct_prediction = tf.equal(tf.argmax(y_conv, 1), tf.argmax(y_, 1))
    correct_prediction = tf.cast(correct_prediction, tf.float32)
  accuracy = tf.reduce_mean(correct_prediction)
  graph_location = tempfile.mkdtemp()
  print('Saving graph to: %s' % graph_location)
  train_writer = tf.summary.FileWriter(graph_location)
  train_writer.add_graph(tf.get_default_graph())
  with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for i in range(20000):
#    for i in range(2000):
      batch = mnist.train.next_batch(50)
      if i % 100 == 0:
        train_accuracy = accuracy.eval(feed_dict={
            x: batch[0], y_: batch[1], keep_prob: 1.0})
        print('step %d, training accuracy %g' % (i, train_accuracy))
      train_step.run(feed_dict={x: batch[0], y_: batch[1], keep_prob: 0.5})
    print('test accuracy %g' % accuracy.eval(feed_dict={
        x: mnist.test.images, y_: mnist.test.labels, keep_prob: 1.0}))
if __name__ == '__main__':
  parser = argparse.ArgumentParser()
  parser.add_argument('--data_dir', type=str,
                      default='/tmp/tensorflow/mnist/input_data',
                      help='Directory for storing input data')
  FLAGS, unparsed = parser.parse_known_args()
  tf.app.run(main=main, argv=[sys.argv[0]] + unparsed)



・ tf.estimator Quickstart に関するコード

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
import os
from six.moves.urllib.request import urlopen
import numpy as np
import tensorflow as tf
import csv
# Data sets
IRIS_TRAINING = "iris_training.csv"
IRIS_TRAINING_URL = "http://download.tensorflow.org/data/iris_training.csv"
IRIS_TEST = "iris_test.csv"
IRIS_TEST_URL = "http://download.tensorflow.org/data/iris_test.csv"
trainfile = open("iris_training.csv")
#for line in csv.reader(trainfile):
#  print(line)
def main():
  # If the training and test sets aren't stored locally, download them.
  if not os.path.exists(IRIS_TRAINING):
    raw = urlopen(IRIS_TRAINING_URL).read()
    with open(IRIS_TRAINING, "wb") as f:
      f.write(raw)
  if not os.path.exists(IRIS_TEST):
    raw = urlopen(IRIS_TEST_URL).read()
    with open(IRIS_TEST, "wb") as f:
      f.write(raw)
  # Load datasets.
  training_set = tf.contrib.learn.datasets.base.load_csv_with_header(
      filename=IRIS_TRAINING,
      target_dtype=np.int,
      features_dtype=np.float32)
  test_set = tf.contrib.learn.datasets.base.load_csv_with_header(
      filename=IRIS_TEST,
      target_dtype=np.int,
      features_dtype=np.float32)
  # Specify that all features have real-value data
  feature_columns = [tf.feature_column.numeric_column("x", shape=[4])]
  # Build 3 layer DNN with 10, 20, 10 units respectively.
  classifier = tf.estimator.DNNClassifier(feature_columns=feature_columns,
                                          hidden_units=[10, 20, 10],
                                          n_classes=3,
                                          model_dir="/tmp/iris_model")
  # Define the training inputs
  train_input_fn = tf.estimator.inputs.numpy_input_fn(
      x={"x": np.array(training_set.data)},
      y=np.array(training_set.target),
      num_epochs=None,
      shuffle=True)
  # Train model.
  classifier.train(input_fn=train_input_fn, steps=2000)
  # Define the test inputs
  test_input_fn = tf.estimator.inputs.numpy_input_fn(
      x={"x": np.array(test_set.data)},
      y=np.array(test_set.target),
      num_epochs=1,
      shuffle=False)
  # Evaluate accuracy.
  accuracy_score = classifier.evaluate(input_fn=test_input_fn)["accuracy"]
  print("\nTest Accuracy: {0:f}\n".format(accuracy_score))
  # Classify two new flower samples.
  new_samples = np.array(
      [[6.4, 3.2, 4.5, 1.5],
       [5.8, 3.1, 5.0, 1.7]], dtype=np.float32)
  predict_input_fn = tf.estimator.inputs.numpy_input_fn(
      x={"x": new_samples},
      num_epochs=1,
      shuffle=False)
  predictions = list(classifier.predict(input_fn=predict_input_fn))
  predicted_classes = [p["classes"] for p in predictions]
  print(
      "New Samples, Class Predictions:    {}\n"
      .format(predicted_classes))
if __name__ == "__main__":
    main()

日本語の文章でembedding vectorを作ろう 20180206

Tensorflowで遊んでみた
02 /06 2018
とりあえず、tutorialのVector Representations of Words を読み終えたので、遊んでみることにした。(models/tutorials/embedding/word2vec.py は環境の構築が素人ではきつそうなので、後回しにします。)

今回は英語の単語ではなく、日本語の単語でembedding vectorを作ることを目的としました。

まず、チュートリアルのコード(word2vec_basic.py)で使用されたデータセット(text8)の中身を見てみる。

20180206_1.jpg


単語がずらりと並んでいる。
最初は日本語の文章を英語の文章みたく、それぞれの部分に分ける必要がありそうだ。
ということで、MeCabを導入して、日本語の文章を分けてみることから始めてみた。
MeCabはオープンソースの形態素解析ソフトウェアで日本語の文章の分割を行ってくれるらしい。
導入の際にはPython2.7にMeCabをインストール(メモ)を参考にしました。
インストール時にやることは3つで、
1.MeCabの本体のインストール
2.MeCab 用の辞書 (IPA 辞書)のインストール
3.Python用のMeCabのインストール
です。

インストールが終わってから、動作チェックで次のコマンドを入力してみる。
#mecab -O wakati

そうすると入力待ちになるので、試しに文章を入力して、エンターキーを押してみましょう。

20180206_2.jpg

見事に文章が分れています。"-O wakati"のオプションを付けると分かち書きしか表示してくれませんので、オプションを外してもう一度やってみます。

20180206_3.jpg

すると、今度は品詞や活用、読みなどの情報も含めて表示されました。(EOS = End Of Sentence)
今回は分かち書きの結果しかデータとして使用しませんが、いつかは品詞の情報なども読ませて学習させたいですね。

次にpythonで動かしてみる。
まず、読み込み用ファイルを用意します。(コード中に入力データを書いても大丈夫です。)

20180206_4.jpg


次にコードを書きます。こんな感じです。

20180206_5.jpg


pythonで実行すると、ちゃんと分かち書きができていました。

20180206_6.jpg

このコードをベースに日本語の入力データを作っていく予定です。
問題は、そのテータのもとになる日本語の文章ですかね・・・。

今日はここまでです。

Tensorflowのチュートリアル備忘録 2018/01/29

Tensorflowのチュートリアル
01 /30 2018
まだまだVector Representations of Wordsのところを読んでいきます。
今回はコード(word2vec_basic.py)の解説の続きです。

いよいよ、# Step 4: Build and train a skip-gram modelの中身に入ります。
まず、skip-gramのプログラムを動かすために必要な設定をやっておきます。
batch_size = 128
embedding_size = 128 # Dimension of the embedding vector.
skip_window = 1 # How many words to consider left and right.
num_skips = 2 # How many times to reuse an input to generate a label.
num_sampled = 64 # Number of negative examples to sample.

それぞれの変数の説明はコメントアウトに書いてある通りです。
また、実証用のデータを作る際の設定も書いておきます。
valid_size = 16 # Random set of words to evaluate similarity on.
valid_window = 100 # Only pick dev samples in the head of the distribution.
valid_examples = np.random.choice(valid_window, valid_size, replace=False)

最初の方の分布をとってきているのは、それらの言葉の出現頻度が高いからっぽい。

tensorflowの本体ともいえるグラフを作っていきます。
まずはグラフを定義した後に中身を書いていきます。
トレーニング用入力データとそのラベル、実証用データを定義します。
graph = tf.Graph()

with graph.as_default():

# Input data.
train_inputs = tf.placeholder(tf.int32, shape=[batch_size])
train_labels = tf.placeholder(tf.int32, shape=[batch_size, 1])
valid_dataset = tf.constant(valid_examples, dtype=tf.int32)

次に、モデルで使う変数の定義をしていきます。
tf.device('/cpu:0')はコードを走らせているデバイスのCPUであることを示しています。つまり、これから定義する変数はCUP上で処理を行われるということです。
embeddingベクターに関しては、-1から+1までのランダムな数値で初期化されるように定義します。
tf.nn.embedding_lookupではembeddingベクターと言葉のIDの紐づけが行われます。ここではembeddingがそのベクター、train_inputsがIDを示しています。出来上がったembedは[IDの数, embedding_size]のshapeを持ちます。つまり、バッチデータ中に含まれる言葉に対してembeddingベクターを関連付けたわけです。
with tf.device('/cpu:0'):
# Look up embeddings for inputs.
embeddings = tf.Variable(
tf.random_uniform([vocabulary_size, embedding_size], -1.0, 1.0))
embed = tf.nn.embedding_lookup(embeddings, train_inputs)


トレーニングによって最適化されるモデルの変数の定義を行っていきます。
モデルの重みとバイアスを定義していきます。重みはガウシアンの分布であり、embedding_sizeで標準化されたばらつきをもつようなものに初期化、バイアスは0に初期化されます。
nce_weights = tf.Variable(
tf.truncated_normal([vocabulary_size, embedding_size],
stddev=1.0 / math.sqrt(embedding_size)))
nce_biases = tf.Variable(tf.zeros([vocabulary_size]))


ここでモデルの定義を行います。
モデルはnoise-contrastive estimation (NCE)です。入力されたバッチデータに対してlossの平均値を計算していきます。
ここで、モデルは正しいラベルだけではなく、間違ったラベルも用いて最適化される必要があることを思い出してください。
正しいターゲットラベルは1つだけなので、それ以外の偽のターゲットラベルも自動的に入れられて最適化が行われます。
loss = tf.reduce_mean(
tf.nn.nce_loss(weights=nce_weights,
biases=nce_biases,
labels=train_labels,
inputs=embed,
num_sampled=num_sampled,
num_classes=vocabulary_size))


できあがったモデルの最適化の方法を定義します。
最適化はstochastic gradient descentで行われます。
optimizer = tf.train.GradientDescentOptimizer(1.0).minimize(loss)

トレーニング用データからのembeddingベクターと実証用データ(たぶんテスト用データだと思われる)からのembeddingベクターの関係をコサイン類似度を用いて計算します。これはベクトル同士の内積で、近ければ1、遠ければ0となります。
norm = tf.sqrt(tf.reduce_sum(tf.square(embeddings), 1, keep_dims=True))
normalized_embeddings = embeddings / norm
valid_embeddings = tf.nn.embedding_lookup(
normalized_embeddings, valid_dataset)
similarity = tf.matmul(
valid_embeddings, normalized_embeddings, transpose_b=True)


トレーニングを行う前に初期化の設定を行います。
init = tf.global_variables_initializer()



ここからは# Step 5: Begin trainingの内容です。

まず、トレーニングステップを100001回に設定します。
num_steps = 100001

.ここから計算の実行部分を書いていきます。
初期化を実行してから、トレーニングのループに入ります。
with tf.Session(graph=graph) as session:
# We must initialize all variables before we use them.
init.run()
print('Initialized')

average_loss = 0

トレーニングのループのでは、最初にバッチデータを作ります。入力用データとラベルデータのセットです。
そして、それを使ってモデルに入力する辞書データを作ります。
for step in xrange(num_steps):
batch_inputs, batch_labels = generate_batch(
batch_size, num_skips, skip_window)
feed_dict = {train_inputs: batch_inputs, train_labels: batch_labels}


トレーニングを実行します。
[optimizer, loss]はfetchと呼ばれていて、runメソッドが走った際に行われる処理、評価するための処理が入ります。
feed_dictにはrunする際に使うデータセットを入れておきます。
処理の返り値はないため、ここではlossの値だけ入れています。そのlossの値をaverage_lossに入れていきます。
_, loss_val = session.run([optimizer, loss], feed_dict=feed_dict)
average_loss += loss_val

2000回目のトレーニングの際に平均化されたlossを表示します。
10000回目のトレーニングの際には実証データに近いデータを表示させています。
similarity.eval()でコサイン類似度を計算します。
i番目の実証用データの周辺にあるembeddingベクターのうち、1番目から8番目までの近い奴をとってきて表示しています。
if step % 2000 == 0:
if step > 0:
average_loss /= 2000
# The average loss is an estimate of the loss over the last 2000 batches.
print('Average loss at step ', step, ': ', average_loss)
average_loss = 0

# Note that this is expensive (~20% slowdown if computed every 500 steps)
if step % 10000 == 0:
sim = similarity.eval()
for i in xrange(valid_size):
valid_word = reverse_dictionary[valid_examples[i]]
top_k = 8 # number of nearest neighbors
nearest = (-sim[i, :]).argsort()[1:top_k + 1]
log_str = 'Nearest to %s:' % valid_word
for k in xrange(top_k):
close_word = reverse_dictionary[nearest[k]]
log_str = '%s %s,' % (log_str, close_word)
print(log_str)


最後に二次元プロット用のembeddingを作って終了です。
final_embeddings = normalized_embeddings.eval()


あとは、プロットに関する設定と描画のコードです。必要なツールが無いときの例外処理も書いてありますね。
def plot_with_labels(low_dim_embs, labels, filename):
assert low_dim_embs.shape[0] >= len(labels), 'More labels than embeddings'
plt.figure(figsize=(18, 18)) # in inches
for i, label in enumerate(labels):
x, y = low_dim_embs[i, :]
plt.scatter(x, y)
plt.annotate(label,
xy=(x, y),
xytext=(5, 2),
textcoords='offset points',
ha='right',
va='bottom')

plt.savefig(filename)

try:
# pylint: disable=g-import-not-at-top
from sklearn.manifold import TSNE
import matplotlib.pyplot as plt

tsne = TSNE(perplexity=30, n_components=2, init='pca', n_iter=5000, method='exact')
plot_only = 500
low_dim_embs = tsne.fit_transform(final_embeddings[:plot_only, :])
labels = [reverse_dictionary[i] for i in xrange(plot_only)]
plot_with_labels(low_dim_embs, labels, os.path.join(gettempdir(), 'tsne.png'))

except ImportError as ex:
print('Please install sklearn, matplotlib, and scipy to show embeddings.')
print(ex)


コードの内容に関してはこんな感じです。
それでは実際にword2vec_basic.py を走らせてみましょう。
いつものようにpythonで走らせます。その結果がこんな感じです。

20180130_1.jpg


UNKの数が予想以上に大きいことがわかります。一番たくさんあるのは"the"で、二番目が"of"であることがわかります。
dataの一番目から十番目までのIDと言葉を表示しています。
次に8個分のターゲットとラベルを表示しています。
originatedに対してはasとanarchismがラベルとなっています。
I tensorflow/core/platfor以下がトレーニング時の情報を示しています。

最終的なembeddingベクターの情報はt-SNEによって二次元プロットで書かれます。
プロットは/tmpにtsne.pngとして保存されます。ちなみに今回走らせた結果はこんな感じです。

tsne.png


なんとなく、向きに関する言葉とか、助動詞とかが固まっているような気がしますね。

今日はここまでです。


追伸: 公式ウェブページのGetting StartやTutorialの内容ががらりと変わっていました。ここのブログの記述と合わない部分が出てくると思います。注意してください。


Tensorflowのチュートリアル備忘録 2018/0126

Tensorflowのチュートリアル
01 /27 2018
今回も引き続いてVector Representations of Words のところを読んでいきます。
The Skip-gram Modelの項の途中からですね。

まず、
(quick, the), (quick, brown), (brown, quick), (brown, fox), ...
のような入力と出力のペアとなったデータがあるとします。
次にSkip-gramアルゴリズムを用いて、"quick"という言葉から"the"を予測するとします。
さらに、ノイズの数を1として、その言葉を"sheep"とします。その言葉はある1単語の分布P(w)から選んだとします。
t回目のトレーニングステップにおける分類器は

20180126_1.png

と表現されます。
この分類器におけるパラメーター(theta) をstochastic gradient descentなどを用いて最大となるように最適化します。
これをすべてのトレーニングデータセットに対して行います。
最終的に最適化されたパラメーターで記述されたembedding vectorsはt-SNE dimensionality reduction techniqueと呼ばれる技法で二次元の情報に落とし込むことができます。
この二次元のプロットからは様々な情報を得ることができ、例に書かれているように対義語の関係や過去形と進行形の関係などがあるベクトルの向きに対応しているといったことがわかります。

ここからはコードのお話です。
コードはword2vec_basic.pyに置いてあります。
コメントアウトに丁寧に説明が書いてあるので、ありがたいです。
コードの内容に関して見ながら解説をしていきます。

最初にモジュールをimportしていますね。

# Step 1: Download the data. 以下でデータのダウンロード先のurlを設定しています。


# pylint: disable=redefined-outer-name 以下では、すでにファイルを持っているか確かめていて、さらにファイルサイズも確かめています。


# Read the data into a list of strings 以下では、zipファイルの中から文字列を読み込んで、その文字数を表示させます。


# Step 2: Build the dictionary and replace rare words with UNK token の部分では主に辞書を作っていきます。
ちなみにUNKとはunknown wordを意味しています。
まず、count というリストをつくります。count[0][0]=UNK、count[0][1]=-lとしています。
このリストにwords(文字列のリスト)を繋げます。most_common(n_words - 1)は最初からn_words - 1番目の要素をとってくるという意味です。
dict()で辞書の定義をしています。
for文で先ほど作った辞書にcount内の要素を登録していきます。
リストを作って、UNK用のカウンターも作ります。
for文で辞書の言葉に割り当てられた値を引っ張ってきます。なにも引っかからない場合は0を与えます。そして、0の場合にはUNK用カウンターを1つ増やします。最終的に値をリストに中に入れていきます。
count[0][1]にunk_countを入れます。
値とキーの位置をひっくり返した辞書もつくります。
最終的に作ってきたものを返します。
以下コード内の記述。
.
vocabulary_size = 50000


def build_dataset(words, n_words):
"""Process raw inputs into a dataset."""
count = [['UNK', -1]]
count.extend(collections.Counter(words).most_common(n_words - 1))
dictionary = dict()
for word, _ in count:
dictionary[word] = len(dictionary)
data = list()
unk_count = 0
for word in words:
index = dictionary.get(word, 0)
if index == 0: # dictionary['UNK']
unk_count += 1
data.append(index)
count[0][1] = unk_count
reversed_dictionary = dict(zip(dictionary.values(), dictionary.keys()))
return data, count, dictionary, reversed_dictionary


4つのグローバル変数(data、 count、 dictionary、 reverse_dictionary)を先ほどの関数から作ります。
dataはいわば入力された言葉に対するidみたいなものです。
countはある言葉がでてきた頻度を記録したマップみたいなものです。
dictionaryは言葉とidを関連付けた辞書みたいなものです。言葉からidを見つけます。
reverse_dictionaryは辞書みたいなものですが、上と逆です(idから言葉をみつける)。


# Step 3: Function to generate a training batch for the skip-gram model.の部分は以下の通りです。
まず、assert文で例外処理をしています。batch_sizeはnum_skipsで割り切れなければならず、num_skipsは2 * skip_window以下の数でなければなりません。
バッチとラベルを定義した後に、spanの数だけ要素を一時的に保持するbufferを用意します。
if文でdataに入っていない要素を指さないようにしています。
先ほどできたbufferにdata中のdata_index番目からdata_index + span番目までの要素を詰め込み、それに合わせてdata_indexの位置も変えていきます。

次にfor文でバッチ中に含まれるデータを処理していきます。
context_wordsには[0,2]のような数字が入ります。これは0からspanまでの内、wとskip_windowが違う値であるときにwを入れていくということをやっています。
context_wordsの中からnum_skips個の要素をランダムに取り出してwords_to_useに順番に詰め込みます。
ここのfor文ではwords_to_useの要素とそれに対する番号をcontext_wordとjに入れていきます。
バッチのデータとしてbuffer[skip_window]、つまりwに選ばれなかった奴が入ります。dataのdata_index+skip_window番目の要素に対応しています。
ラベルのデータとしてbuffer[context_word]が入ります。つまり、先ほど入れたbuffer[skip_window]の周りの奴ですね。
if文ではdata_indexがdataの要素を越える場所を指している場合に、bufferの中にdataの0からspan番目までの要素を詰め込むことをやっています。else文ではdata_indexが指すものをそのままbufferに入れています。
最後にdata_indexがdataの最後の要素を示している場合には0とするようにして、バッチとラベルを返します。
先ほどの関数を使って、batch_size=8, num_skips=2, skip_window=1のデータを作ります。
以下コード内の記述です。

def generate_batch(batch_size, num_skips, skip_window):
global data_index
assert batch_size % num_skips == 0
assert num_skips <= 2 * skip_window
batch = np.ndarray(shape=(batch_size), dtype=np.int32)
labels = np.ndarray(shape=(batch_size, 1), dtype=np.int32)
span = 2 * skip_window + 1 # [ skip_window target skip_window ]
buffer = collections.deque(maxlen=span)
if data_index + span > len(data):
data_index = 0
buffer.extend(data[data_index:data_index + span])
data_index += span
for i in range(batch_size // num_skips):
context_words = [w for w in range(span) if w != skip_window]
words_to_use = random.sample(context_words, num_skips)
for j, context_word in enumerate(words_to_use):
batch[i * num_skips + j] = buffer[skip_window]
labels[i * num_skips + j, 0] = buffer[context_word]
if data_index == len(data):
buffer[:] = data[:span]
data_index = span
else:
buffer.append(data[data_index])
data_index += 1
# Backtrack a little bit to avoid skipping words in the end of a batch
data_index = (data_index + len(data) - span) % len(data)
return batch, labels

batch, labels = generate_batch(batch_size=8, num_skips=2, skip_window=1)
for i in range(8):
print(batch[i], reverse_dictionary[batch[i]],
'->', labels[i, 0], reverse_dictionary[labels[i, 0]])


今日はここまでです。

シジミパワー

 ブログ初心者です。よろしくお願いします。

 チャットボットにこちらからアクセスできます。
 無料版のプラットホームを用いているので、会話数に制限があります。申し訳ございません。
 2月18日をもって終了する予定です。使ってくださった皆様、ありがとうございました。

 
 ふりーむにゲームを掲載させていただきました。掲載されているページへ移動する場合はここをクリックしてください。

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。