Neulich ging ich als Moderator zu TensorFlow Study Group. Die Leute um mich herum fragten mich, ob ich nichts über den Inhalt der Lernsitzung schreiben würde, aber ich hatte Angst vor der Anzahl der Leute Ankündigung, dass niemand glücklich sein würde ), Also werde ich stattdessen das tote Material verbrauchen, das ich ursprünglich verwenden wollte.
Was Sie tun möchten, ist sehr einfach, wie der Titel schon sagt. Wenn Sie den Namen des Pokémon eingeben, möchte ich, dass Sie den Rassenwert und die typähnliche Sache sehen. Es fühlt sich so an, als würde ich etwas ausprobieren, was bei Twitter-Diagnostikern oft der Fall ist.
Wir haben den Pokemon-Namen Zeichen für Zeichen zerlegt und die Anzahl der Vorkommen jedes Zeichens und 2 Gramm als Merkmalsmenge verwendet. Zum Beispiel im Fall von Dedenne:
{
De: 2,Nieder: 1,Ne: 1,
Dede: 1,Den: 1,Nne: 1
}
Das Erstellen von n-Gramm-Funktionen selbst ist mühsam, aber die Verwendung von scikit-learns Vectorizer 2, 3 Sie können n-Gramm-Funktionen erstellen, während Sie detaillierte Einstellungen in Zeilen vornehmen. Sie können problemlos einen Vektorisierer speichern, in dem alle erforderlichen Informationen gespeichert sind. Daher wird Ultra Super Miracle empfohlen. Wenn Sie keine Tugend sammeln müssen, um sich auf die nächste Welt vorzubereiten, oder wenn besondere Umstände vorliegen, sollten Sie sie auf jeden Fall nutzen.
Die Ausgabe ist etwas umständlich und muss grob in die folgenden drei Ausgaben unterteilt werden.
Sie können für jedes Modell ein Modell erstellen und Vorhersagen treffen, aber die Flexibilität, alles zusammen zu packen, ist die Stärke des neuronalen Netzes (ich persönlich denke, das ist es). Deshalb habe ich versucht, alles in einem Netzwerk zusammenzufassen. T. Mit anderen Worten, das ist es.
Die Anzahl der Einheiten in der letzten Ebene beträgt 6 + 18 + 19. Der Teil, der dem Rennwert entspricht, wurde so ausgegeben, wie er war, und der Verlust wurde durch den quadratischen Fehler definiert. Die Ausgabe entspricht 18 oder 19 Typen, von denen jeder in Softmax verschoben wird, und der Verlust wird durch jede Kreuzentropie definiert. Die endgültige Zielfunktion ist die gewichtete Addition dieser Verluste.
~~ Es handelt sich nicht um vertrauliche Daten. Wenn Sie also Ihr Bestes geben, werden Sie zusammenkommen. Bitte geben Sie Ihr Bestes. ~~ Nur die verwendeten Daten wurden mit dem Code (https://github.com/sfujiwara/pn2bs) [auf GitHub hochgeladen].
# -*- coding: utf-8 -*-
import numpy as np
import pandas as pd
import tensorflow as tf
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.externals import joblib
from sklearn.feature_extraction import DictVectorizer
def inference(x_placeholder, n_in, n_hidden1, n_hidden2):
"""
Description
-----------
Forward step which build graph.
Parameters
----------
x_placeholder: Placeholder for feature vectors
n_in: Number of units in input layer which is dimension of feature
n_hidden1: Number of units in hidden layer 1
n_hidden2: Number of units in hidden layer 2
Returns
-------
y_bs: Output tensor of predicted values for base stats
y_type1: Output tensor of predicted values for type 1
y_type2: Output tensor of predicted values for type 2
"""
# Hidden1
with tf.name_scope('hidden1') as scope:
weights = tf.Variable(
tf.truncated_normal([n_in, n_hidden1]),
name='weights'
)
biases = tf.Variable(tf.zeros([n_hidden1]))
hidden1 = tf.nn.sigmoid(tf.matmul(x_placeholder, weights) + biases)
# Hidden2
with tf.name_scope('hidden2') as scope:
weights = tf.Variable(
tf.truncated_normal([n_hidden1, n_hidden2]),
name='weights'
)
biases = tf.Variable(tf.zeros([n_hidden2]))
hidden2 = tf.nn.sigmoid(tf.matmul(hidden1, weights) + biases)
# Output layer for base stats
with tf.name_scope('output_base_stats') as scope:
weights = tf.Variable(
tf.truncated_normal([n_hidden2, 6]),
name='weights'
)
biases = tf.Variable(tf.zeros([6]))
y_bs = tf.matmul(hidden2, weights) + biases
# Output layer for type1
with tf.name_scope('output_type1') as scope:
weights = tf.Variable(
tf.truncated_normal([n_hidden2, 18]),
name='weights'
)
biases = tf.Variable(tf.zeros([18]))
# y_type1 = tf.nn.softmax(tf.matmul(hidden2, weights) + biases)
y_type1 = tf.matmul(hidden2, weights) + biases
# Output layer for type2
with tf.name_scope('output_type2') as scope:
weights = tf.Variable(
tf.truncated_normal([n_hidden2, 19]),
name='weights'
)
biases = tf.Variable(tf.zeros([19]))
y_type2 = tf.matmul(hidden2, weights) + biases
# y_type2 = tf.nn.softmax(tf.matmul(hidden2, weights) + biases)
return [y_bs, y_type1, y_type2]
def build_loss_bs(y_bs, t_ph_bs):
"""
Parameters
----------
y_bs: Output tensor of predicted values for base stats
t_ph_bs: Placeholder for base stats
Returns
-------
Loss tensor which includes placeholder of features and labels
"""
loss_bs = tf.reduce_mean(tf.nn.l2_loss(t_ph_bs - y_bs), name='LossBaseStats')
return loss_bs
def build_loss_type1(y_type1, t_ph_type1):
"""
Parameters
----------
y_type1: Output tensor of predicted values for base stats
t_ph_type1: Placeholder for base stats
Returns
-------
Loss tensor which includes placeholder of features and labels
"""
loss_type1 = tf.reduce_mean(
tf.nn.softmax_cross_entropy_with_logits(y_type1, t_ph_type1),
name='LossType1'
)
return loss_type1
def build_loss_type2(y_type2, t_ph_type2):
"""
Parameters
----------
y_type2: Output tensor of predicted values for base stats
t_ph_type2: Placeholder for base stats
Returns
-------
Loss tensor which includes placeholder of features and labels
"""
loss_type2 = tf.reduce_mean(
tf.nn.softmax_cross_entropy_with_logits(y_type2, t_ph_type2),
name='LossType2'
)
return loss_type2
def build_optimizer(loss, step_size):
"""
Parameters
----------
loss: Tensor of objective value to be minimized
step_size: Step size for gradient descent
Returns
-------
Operation of optimization
"""
optimizer = tf.train.GradientDescentOptimizer(step_size)
global_step = tf.Variable(0, name='global_step', trainable=False)
train_op = optimizer.minimize(loss, global_step=global_step)
return train_op
if __name__ == '__main__':
# Set seed
tf.set_random_seed(0)
# Load data set and extract features
df = pd.read_csv('data/poke_selected.csv')
# Fill nulls in type2
df.loc[df.type2.isnull(), 'type2'] = 'Nichts'
# Vectorize pokemon name
pokename_vectorizer = CountVectorizer(analyzer='char', min_df=1, ngram_range=(1, 2))
x = pokename_vectorizer.fit_transform(list(df['name_jp'])).toarray()
t_bs = np.array(df[['hp', 'attack', 'block', 'contact', 'defense', 'speed']])
# Vectorize pokemon type1
poketype1_vectorizer = DictVectorizer(sparse=False)
d = df[['type1']].to_dict('record')
t_type1 = poketype1_vectorizer.fit_transform(d)
# Vectorize pokemon type2
poketype2_vectorizer = DictVectorizer(sparse=False)
d = df[['type2']].to_dict('record')
t_type2 = poketype2_vectorizer.fit_transform(d)
# Placeholders
x_ph = tf.placeholder(dtype=tf.float32)
t_ph_bs = tf.placeholder(dtype=tf.float32)
t_ph_type1 = tf.placeholder(dtype=tf.float32)
t_ph_type2 = tf.placeholder(dtype=tf.float32)
# build graph, loss, and optimizer
y_bs, y_type1, y_type2 = inference(x_ph, n_in=1403, n_hidden1=512, n_hidden2=256)
loss_bs = build_loss_bs(y_bs, t_ph_bs)
loss_type1 = build_loss_type1(y_type1, t_ph_type1)
loss_type2 = build_loss_type2(y_type2, t_ph_type2)
loss = tf.add_n([1e-4 * loss_bs, loss_type1, loss_type2], name='ObjectiveFunction')
optim = build_optimizer(loss, 1e-1)
# Create session
sess = tf.Session()
# Initialize variables
init = tf.initialize_all_variables()
sess.run(init)
# Create summary writer and saver
summary_writer = tf.train.SummaryWriter('log', graph_def=sess.graph_def)
tf.scalar_summary(loss.op.name, loss)
tf.scalar_summary(loss_bs.op.name, loss_bs)
tf.scalar_summary(loss_type1.op.name, loss_type1)
tf.scalar_summary(loss_type2.op.name, loss_type2)
summary_op = tf.merge_all_summaries()
saver = tf.train.Saver()
# Run optimization
for i in range(1500):
# Choose indices for mini batch update
ind = np.random.choice(802, 802)
batch_xs = x[ind]
batch_ts_bs = t_bs[ind]
batch_ts_type1 = t_type1[ind]
batch_ts_type2 = t_type2[ind]
# Create feed dict
fd = {
x_ph: batch_xs,
t_ph_bs: batch_ts_bs,
t_ph_type1: batch_ts_type1,
t_ph_type2: batch_ts_type2
}
# Run optimizer and update variables
sess.run(optim, feed_dict=fd)
# Show information and write summary in every n steps
if i % 100 == 99:
# Show num of epoch
print 'Epoch:', i + 1, 'Mini-Batch Loss:', sess.run(loss, feed_dict=fd)
# Write summary and save checkpoint
summary_str = sess.run(summary_op, feed_dict=fd)
summary_writer.add_summary(summary_str, i)
name_model_file = 'model_lmd1e-4_epoch_' + str(i+1) + '.ckpt'
save_path = saver.save(sess, 'model/tensorflow/'+name_model_file)
else:
name_model_file = 'model_lmd1e-4_epoch_' + str(i+1) + '.ckpt'
save_path = saver.save(sess, 'model/tensorflow/'+name_model_file)
# Show example
poke_name = 'Donner'
v = pokename_vectorizer.transform([poke_name]).toarray()
pred_bs = sess.run(y_bs, feed_dict={x_ph: v})
pred_type1 = np.argmax(sess.run(y_type1, feed_dict={x_ph: v}))
pred_type2 = np.argmax(sess.run(y_type2, feed_dict={x_ph: v}))
print poke_name
print pred_bs
print pred_type1, pred_type2
print poketype1_vectorizer.get_feature_names()[pred_type1]
print poketype2_vectorizer.get_feature_names()[pred_type2]
# Save vectorizer of scikit-learn
joblib.dump(pokename_vectorizer, 'model/sklearn/pokemon-name-vectorizer')
joblib.dump(poketype1_vectorizer, 'model/sklearn/pokemon-type1-vectorizer')
joblib.dump(poketype2_vectorizer, 'model/sklearn/pokemon-type2-vectorizer')
Das bedeutet nicht, dass das Material ernsthaft abgestimmt ist, weil es ein Material ist. Deshalb habe ich mir TensorBoard angesehen, um festzustellen, ob der Verlust beim Mindesttyp und der Verlust beim Rennwert in ausgewogener Weise verringert wurden.
Laden wir das Modell und spielen wir so damit.
# -*- coding: utf-8 -*-
import numpy as np
import pandas as pd
import tensorflow as tf
from sklearn.externals import joblib
import pn2bs
# Placeholder
x_ph = tf.placeholder(dtype=tf.float32)
t_ph = tf.placeholder(dtype=tf.float32)
y_bs, y_type1, y_type2 = pn2bs.inference(x_ph, n_in=1403, n_hidden1=512, n_hidden2=256)
# Create session
sess = tf.Session()
# Load TensorFlow model
saver = tf.train.Saver()
saver.restore(sess, "model/tensorflow/model_lmd1e-4_epoch_1500.ckpt")
# Load vectorizer of scikit-learn
pokename_vectorizer = joblib.load("model/sklearn/pokemon-name-vectorizer")
poketype1_vectorizer = joblib.load("model/sklearn/pokemon-type1-vectorizer")
poketype2_vectorizer = joblib.load("model/sklearn/pokemon-type2-vectorizer")
poke_name = 'Gonzales'
v = pokename_vectorizer.transform([poke_name]).toarray()
pred_bs = sess.run(y_bs, feed_dict={x_ph: v})
pred_type1 = np.argmax(sess.run(y_type1, feed_dict={x_ph: v}))
pred_type2 = np.argmax(sess.run(y_type2, feed_dict={x_ph: v}))
result = {
'name' : poke_name,
'hp' : pred_bs[0][0],
'attack' : pred_bs[0][1],
'block' : pred_bs[0][2],
'contact': pred_bs[0][3],
'defense': pred_bs[0][4],
'speed' : pred_bs[0][5],
'type1' : poketype1_vectorizer.get_feature_names()[pred_type1],
'type2' : poketype2_vectorizer.get_feature_names()[pred_type2],
}
print result['name']
print result['hp']
print result['attack']
print result['block']
print result['contact']
print result['defense']
print result['speed']
print result['type1']
print result['type2']
Ein Beispiel für das Ergebnis. Es gibt nichts Besonderes zu sagen, aber bitte raten Sie etwas über jeden.
Name | H | A | B | C | D | S | Type 1 | Type 2 |
---|---|---|---|---|---|---|---|---|
Tensolfluss | 92 | 102 | 84 | 85 | 65 | 73 | Fee | böse |
Mega Pikachu | 74 | 80 | 50 | 97 | 85 | 80 | Elektrisch | Nichts |
Gonzales | 81 | 103 | 107 | 86 | 103 | 65 | Drachen | Elektrisch |
Mega Gonzales | 100 | 137 | 131 | 118 | 117 | 103 | Drachen | böse |
Ich fand die Flexibilität der Modellierung großartig, weil das neuronale Netz der Taube mit aller Kraft die guten Eigenschaften der Konvexität und Funktionen wegwirft. Wenn Sie beispielsweise versuchen, dasselbe mit SVM zu tun, werden Sie sich zunächst nicht mehr fragen, was zu tun ist, wenn Sie nach mehrdimensionalen Ausgaben wie Rennwerten gefragt werden, und sogar das Klassifizierungsproblem in Bezug auf Typen gemeinsam lösen. An dem Tag, an dem mir gesagt wurde, ich sollte schlafen und Schlaf sagen. Wenn es jedoch darum geht, die 2 Outs im unteren Bereich des 9. Innings dem neuronalen Netz zu überlassen, fühlt es sich wie hmm an. so ähnlich.
2016-01-26
Es tut mir ein wenig leid, dass ich es nicht in einem Zustand veröffentlicht habe, in dem ich es richtig ausprobieren kann, obwohl es Leute gibt, die es immer noch von Zeit zu Zeit auf Lager haben. Deshalb habe ich etwas gepostet, das [auf GitHub] funktioniert (https: / /github.com/sfujiwara/pn2bs). Ich dachte, es wäre cool, eine Radarkarte mit Google Charts oder etwas entsprechend dem eingegebenen Namen zu erstellen, aber ich wollte den Bot darauf treffen lassen, also habe ich daraus eine Web-API gemacht.
Ich denke, dass es wahrscheinlich herauskommen wird, wenn ich versuche, es zu verwenden. Wenn ich es also zuerst gestehe, wenn ich ein vorhandenes Pokemon einsetze, wird es verdorren, wenn der Status völlig anders ist als der tatsächliche, also habe ich absichtlich ein Modell übernommen, das überlernt zu sein scheint.
Recommended Posts