Ich habe in Richtung auf das exakt gleiche Ziel hinarbeiten, und bekam es einfach zu arbeiten. Sie haben viele der richtigen Modifikationen hier, aber ich denke, Sie haben ein paar Schritte verpasst.
Zuerst müssen Sie zum Generieren von Text eine andere Version des Modells erstellen, die nur einen einzigen Zeitschritt darstellt. Der Grund ist, dass wir jede Ausgabe y abtasten müssen, bevor wir sie in den nächsten Schritt des Modells einspeisen können. Ich tat dies, indem sie eine neue Konfiguration zu machen, die setzen num_steps
und batch_size
beide gleich 1.
class SmallGenConfig(object):
"""Small config. for generation"""
init_scale = 0.1
learning_rate = 1.0
max_grad_norm = 5
num_layers = 2
num_steps = 1 # this is the main difference
hidden_size = 200
max_epoch = 4
max_max_epoch = 13
keep_prob = 1.0
lr_decay = 0.5
batch_size = 1
vocab_size = 10000
ich auch eine Wahrscheinlichkeit auf das Modell mit diesen Zeilen hinzugefügt:
self._output_probs = tf.nn.softmax(logits)
und
@property
def output_probs(self):
return self._output_probs
Dann gibt es ein paar Unterschiede in meiner generate_text()
Funktion. Der erste ist, dass ich gespeicherte Modellparameter von der Festplatte mit dem Objekt tf.train.Saver()
lade. Beachten Sie, dass wir dies tun, nachdem Sie das PTBModel mit der neuen Konfiguration von oben instanziiert haben.
def generate_text(train_path, model_path, num_sentences):
gen_config = SmallGenConfig()
with tf.Graph().as_default(), tf.Session() as session:
initializer = tf.random_uniform_initializer(-gen_config.init_scale,
gen_config.init_scale)
with tf.variable_scope("model", reuse=None, initializer=initializer):
m = PTBModel(is_training=False, config=gen_config)
# Restore variables from disk.
saver = tf.train.Saver()
saver.restore(session, model_path)
print("Model restored from file " + model_path)
Der zweite Unterschied ist, dass ich die Lookup-Tabelle von ids zu Wortketten (ich hatte diese Funktion zu schreiben, den Code unten).
words = reader.get_vocab(train_path)
habe ich den Anfangszustand die gleiche Art und Weise bis Sie tun, aber dann habe ich die Anfangs Token in einer anderen Art und Weise auf. Ich möchte den "Satzende" -Token verwenden, damit ich meinen Satz mit den richtigen Wortarten starten kann. Ich schaute durch den Wortindex und fand heraus, dass <eos>
zufällig Index 2 (deterministisch) hat, also habe ich das nur hart-codiert. Schließlich wickle ich es in eine 1x1 Numpy Matrix, so dass es der richtige Typ für die Modelleingaben ist.
state = m.initial_state.eval()
x = 2 # the id for '<eos>' from the training set
input = np.matrix([[x]]) # a 2D numpy matrix
Schließlich ist hier der Teil, wo wir Sätze generieren.Beachten Sie, dass wir session.run()
mitteilen, um die output_probs
und die final_state
zu berechnen. Und wir geben ihm den Input und den Zustand. In der ersten Iteration ist der Eingang <eos>
und der Zustand ist initial_state
, aber bei nachfolgenden Iterationen geben wir als Eingabe unsere letzte abgetastete Ausgabe an, und wir übergeben den Zustand von der letzten Iteration her. Beachten Sie auch, dass wir die words
-Liste verwenden, um die Wortzeichenfolge aus dem Ausgabe-Index nachzuschlagen.
text = ""
count = 0
while count < num_sentences:
output_probs, state = session.run([m.output_probs, m.final_state],
{m.input_data: input,
m.initial_state: state})
x = sample(output_probs[0], 0.9)
if words[x]=="<eos>":
text += ".\n\n"
count += 1
else:
text += " " + words[x]
# now feed this new word as input into the next iteration
input = np.matrix([[x]])
Dann müssen wir nur den Text drucken, den wir gesammelt haben.
print(text)
return
Das ist es für die generate_text()
Funktion.
Schließlich, lassen Sie mich Ihnen die Funktionsdefinition für get_vocab()
, die ich in reader.py eingegeben.
def get_vocab(filename):
data = _read_words(filename)
counter = collections.Counter(data)
count_pairs = sorted(counter.items(), key=lambda x: (-x[1], x[0]))
words, _ = list(zip(*count_pairs))
return words
Das letzte, was Sie tun müssen, ist in der Lage sein, das Modell es nach dem Training zu speichern, die
save_path = saver.save(session, "/tmp/model.ckpt")
wie
aussieht Und das ist das Modell, das Sie von der Festplatte später geladen werden beim Generieren Text.
Es gab ein weiteres Problem: Ich fand, dass manchmal die Wahrscheinlichkeitsverteilung, die durch die Tensorflow softmax Funktion erzeugt wurde, nicht genau zu 1.0 summierte. Wenn die Summe größer als 1.0 war, gibt np.random.multinomial()
einen Fehler aus. So hatte ich meine eigene Sampling-Funktion zu schreiben, die wie dieser
def sample(a, temperature=1.0):
a = np.log(a)/temperature
a = np.exp(a)/np.sum(np.exp(a))
r = random.random() # range: [0,1)
total = 0.0
for i in range(len(a)):
total += a[i]
if total>r:
return i
return len(a)-1
sieht Wenn Sie das alles zusammen, das kleine Modell konnte mir ein paar coole Sätze erzeugen. Viel Glück.