Generator delusi: membuat teks dalam bahasa apa pun menggunakan jaringan saraf

Hai, Habr.

Artikel ini akan sedikit berformat "Jumat", hari ini kita akan membahas NLP. Bukan NLP tentang buku mana yang dijual dengan underpass, tetapi buku yang Natural Processing sedang memproses bahasa alami. Sebagai contoh dari pemrosesan tersebut, pembuatan teks menggunakan jaringan saraf akan digunakan. Kami dapat membuat teks dalam bahasa apa pun, dari Rusia atau Inggris, hingga C ++. Hasilnya sangat menarik, Anda mungkin bisa menebak dari gambar.



Bagi mereka yang tertarik dengan apa yang terjadi, hasil dan kode sumber berada di bawah potongan.

Persiapan data


Untuk pemrosesan, kita akan menggunakan kelas khusus jaringan saraf - jaringan saraf berulang (RNN). Jaringan ini berbeda dari yang biasa selain sel yang biasa, ia memiliki sel memori. Ini memungkinkan kita untuk menganalisis data dari struktur yang lebih kompleks, dan pada kenyataannya, lebih dekat ke memori manusia, karena kita juga tidak memulai setiap pemikiran "dari awal". Untuk menulis kode, kita akan menggunakan jaringan LSTM (Memori Jangka Pendek), karena sudah didukung oleh Keras.



Masalah selanjutnya yang perlu dipecahkan adalah, pada kenyataannya, bekerja dengan teks. Dan di sini ada dua pendekatan - untuk mengirim simbol atau seluruh kata ke input. Prinsip pendekatan pertama adalah sederhana: teks dibagi menjadi blok pendek, di mana "input" adalah bagian dari teks, dan "output" adalah karakter berikutnya. Misalnya, untuk frasa terakhir, 'input adalah bagian dari teks':

input: output: ""
input: : output: ""
input: : output:""
input: : output: ""
input: : output: "".

Dan sebagainya. Dengan demikian, jaringan saraf menerima fragmen teks pada input, dan pada output karakter yang harus dibentuk.

Pendekatan kedua pada dasarnya sama, hanya seluruh kata yang digunakan, bukan kata-kata. Pertama, kamus kata dikompilasi, dan angka dimasukkan alih-alih kata pada input jaringan.

Ini, tentu saja, adalah deskripsi yang agak disederhanakan. Keras sudah memiliki contoh pembuatan teks, tetapi pertama-tama, mereka tidak dijelaskan secara mendetail, dan kedua, semua tutorial berbahasa Inggris menggunakan teks yang agak abstrak seperti Shakespeare, yang sulit dipahami oleh penduduk asli. Ya, kami sedang menguji jaringan saraf pada jaringan kami yang besar dan kuat, yang, tentu saja, akan lebih jelas dan dapat dimengerti.

Pelatihan jaringan


Sebagai teks input, saya menggunakan ... komentar Habr, ukuran file sumber adalah 1 MB (tentu saja ada lebih banyak komentar, tentu saja, tetapi saya harus menggunakan hanya satu bagian, jika tidak, jaringan saraf akan dilatih selama seminggu dan pembaca tidak akan melihat teks ini pada hari Jumat). Biarkan saya mengingatkan Anda bahwa hanya surat yang dimasukkan ke input jaringan saraf, jaringan "tidak tahu" tentang bahasa atau strukturnya. Ayo, mulai pelatihan jaringan.

5 menit pelatihan:

Sejauh ini, tidak ada yang jelas, tetapi Anda sudah dapat melihat beberapa kombinasi huruf yang dapat dikenali:

. . . Β«

15 menit pelatihan:

Hasilnya sudah terasa lebih baik:



1 jam pelatihan:

Β« Β» β€” Β« Β» Β» β€”

Untuk beberapa alasan, semua teks ternyata tanpa titik dan tanpa huruf kapital, mungkin pemrosesan utf-8 tidak dilakukan dengan benar. Namun secara keseluruhan, ini mengesankan. Dengan menganalisis dan mengingat hanya kode simbol, program ini benar-benar "secara mandiri" mempelajari kata-kata Rusia, dan dapat menghasilkan teks yang terlihat cukup dapat dipercaya.

Yang tidak kalah menariknya adalah kenyataan bahwa program menghafal gaya teks dengan cukup baik. Dalam contoh berikut, teks beberapa undang-undang digunakan sebagai alat bantu mengajar. Waktu pelatihan jaringan 5 menit.

"" , , , , , , , ,

Dan di sini, penjelasan medis untuk obat-obatan digunakan sebagai set input. Waktu pelatihan jaringan 5 menit.



, ,

Di sini kita melihat hampir seluruh frasa. Ini disebabkan oleh fakta bahwa teks aslinya pendek, dan jaringan saraf sebenarnya "menghafal" beberapa frasa secara keseluruhan. Efek ini disebut "pelatihan ulang," dan harus dihindari. Idealnya, Anda perlu menguji jaringan saraf pada set data besar, tetapi pelatihan dalam hal ini bisa memakan waktu berjam-jam, dan sayangnya saya tidak memiliki komputer super.

Contoh menyenangkan menggunakan jaringan seperti itu adalah pembuatan nama. Setelah mengunggah daftar nama pria dan wanita ke file, saya mendapat opsi baru yang cukup menarik yang akan sangat cocok untuk novel fiksi ilmiah: Rlar, Laaa, Aria, Arera, Aelia, Ninran, Air. Sesuatu di dalamnya merasakan gaya Efremov dan Nebula Andromeda ...

C ++


Yang menarik adalah bahwa pada umumnya, jaringan saraf seperti mengingat. Langkah selanjutnya adalah memeriksa bagaimana program menangani kode sumber. Sebagai tes, saya mengambil berbagai sumber C ++ dan menggabungkannya menjadi satu file teks.

Jujur, hasilnya lebih mengejutkan daripada dalam kasus bahasa Rusia.

5 menit pelatihan

Sial, hampir nyata C ++.

 if ( snd_pcm_state_channels = 0 ) { errortext_ = "rtapialsa::probedeviceopen: esror stream_.buffer stream!"; errortext_ = errorstream_.str(); goto unlock; } if ( stream_.mode == input && stream_.mode == output || false; if ( stream_.state == stream_stopped ) { for ( unsigned int i=0; i<stream_.nuserbuffer[i] ) { for (j=0; j<info.channels; } } } 

30 menit pelatihan

 void maxirecorder::stopstream() { for (int i = 0; i < ainchannels; i++ ) { int input=(stream, null; conternallock( pthread_cond_wate); // this should not ported to the device is a structure are is and the stream the buffer of the interleaved as and the probe the arauliored format for the the stream os and the software and the supported of the is so aa is set the directsound of allocates the reset and real the read the setup the buffer // this is the setup to the the devices. // asio will open the supported by the supported buffer are asioned structure. // this should not have to setup the counting and the proper in the position we mast it alw the aftware configuration. // this is the the stream and probe the supported be audio for sched/ond changed to this the sample rate it in the counting the fres // mecorend. windevoppart( null, 0, &phase ); possint=>buffersize( 1, bufferlist); } } } ///********************************************* void maxirecorder::abortdevice( device ) { if (cout << aindeff( thread_cont_start); for (int i = 0; i < sample_rates[0]) { if (count == int) { std::cout << "checksing of convernion allocation handler (" << device << ")."; errortext_ = errorstream_.str(); return failure; } } } if ( stream_.userbuffer[i] ) { errortext_ = "rtapicore::probedeviceopen: system error (" << geterrorcode( result ) << ") getting stream configuration info state."; error( rterror::warning ); return; } if ( stream_.mode == output || stream_.mode == duplex ) { callbackinfo *info = (const char *) callback( stream_.userbuffer[1], stream_.convertinfo[0] ); return info; } // setup buffer callback for conversion on do any the supported be audio bet that al alinums be of support of the supported buffer // the buffer size a stream and buffers. info.name = dsdevices[ device ]; return 0; } 

Seperti yang Anda lihat, program telah "belajar" untuk menulis seluruh fungsi. Pada saat yang sama, itu sepenuhnya "manusiawi" memisahkan fungsi dengan komentar dengan tanda bintang, memberikan komentar dalam kode, dan semua itu. Saya ingin belajar bahasa pemrograman baru dengan kecepatan seperti itu ... Tentu saja, ada kesalahan dalam kode, dan tentu saja, itu tidak akan dikompilasi. Dan omong-omong, saya tidak memformat kode, program ini juga belajar untuk menempatkan tanda kurung dan lekukan "sendiri".

Tentu saja, program-program ini tidak memiliki makna utama - artinya , dan karenanya terlihat tidak nyata, seolah-olah ditulis dalam mimpi, atau tidak ditulis oleh orang yang benar-benar sehat. Meskipun demikian, hasilnya mengesankan. Dan mungkin studi yang lebih dalam tentang pembuatan teks yang berbeda akan membantu untuk lebih memahami beberapa penyakit mental pasien yang sebenarnya. Ngomong-ngomong, seperti yang disarankan dalam komentar, penyakit mental di mana seseorang berbicara dalam teks yang berhubungan dengan tata bahasa tetapi sama sekali tidak berarti ( skizofasia ) memang ada.

Kesimpulan


Jaringan saraf rekreasional dianggap sangat menjanjikan, dan ini memang merupakan langkah maju yang besar dibandingkan dengan jaringan "biasa" seperti MLP, yang tidak memiliki memori. Memang, kemampuan jaringan saraf untuk menyimpan dan memproses struktur yang cukup kompleks sangat mengesankan. Setelah tes-tes ini saya pertama kali berpikir bahwa Ilon Mask mungkin benar dalam sesuatu ketika saya menulis bahwa AI di masa depan bisa menjadi "risiko terbesar bagi umat manusia" - bahkan jika jaringan saraf sederhana dapat dengan mudah mengingat dan mereproduksi pola yang agak rumit, apa yang bisa dilakukan oleh jaringan miliaran komponen? Tetapi di sisi lain, jangan lupa bahwa jaringan saraf kita tidak dapat berpikir , itu pada dasarnya hanya secara mekanis mengingat urutan karakter, tidak memahami maknanya. Ini adalah poin penting - bahkan jika Anda melatih jaringan saraf pada superkomputer dan kumpulan data besar, paling baik ia akan belajar menghasilkan kalimat yang tata bahasanya 100% benar, tetapi sama sekali tidak berarti.

Tetapi tidak akan dihapus dalam filosofi, artikel itu masih lebih banyak untuk praktisi. Bagi mereka yang ingin bereksperimen sendiri, kode sumber dengan Python 3.7 ada di bawah spoiler. Kode ini adalah kompilasi dari berbagai proyek github, dan bukan contoh kode terbaik, tetapi tampaknya melakukan tugasnya.

Menggunakan program tidak memerlukan keterampilan pemrograman, cukup untuk mengetahui cara menginstal Python. Contoh mulai dari baris perintah:
- Membuat dan melatih model dan pembuatan teks:
python. \ keras_textgen.py --text = text_habr.txt --epochs = 10 --out_len = 4000
- Hanya pembuatan teks tanpa pelatihan model:
python. \ keras_textgen.py --text = text_habr.txt --epochs = 10 --out_len = 4000 --hasilkan

keras_textgen.py
 import os # Force CPU os.environ["CUDA_VISIBLE_DEVICES"] = "-1" os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' # 0 = all messages are logged, 3 - INFO, WARNING, and ERROR messages are not printed from keras.callbacks import LambdaCallback from keras.models import Sequential from keras.layers import Dense, Dropout, Embedding, LSTM, TimeDistributed from keras.optimizers import RMSprop from keras.utils.data_utils import get_file import keras from collections import Counter import pickle import numpy as np import random import sys import time import io import re import argparse # Transforms text to vectors of integer numbers representing in text tokens and back. Handles word and character level tokenization. class Vectorizer: def __init__(self, text, word_tokens, pristine_input, pristine_output): self.word_tokens = word_tokens self._pristine_input = pristine_input self._pristine_output = pristine_output tokens = self._tokenize(text) # print('corpus length:', len(tokens)) token_counts = Counter(tokens) # Sort so most common tokens come first in our vocabulary tokens = [x[0] for x in token_counts.most_common()] self._token_indices = {x: i for i, x in enumerate(tokens)} self._indices_token = {i: x for i, x in enumerate(tokens)} self.vocab_size = len(tokens) print('Vocab size:', self.vocab_size) def _tokenize(self, text): if not self._pristine_input: text = text.lower() if self.word_tokens: if self._pristine_input: return text.split() return Vectorizer.word_tokenize(text) return text def _detokenize(self, tokens): if self.word_tokens: if self._pristine_output: return ' '.join(tokens) return Vectorizer.word_detokenize(tokens) return ''.join(tokens) def vectorize(self, text): """Transforms text to a vector of integers""" tokens = self._tokenize(text) indices = [] for token in tokens: if token in self._token_indices: indices.append(self._token_indices[token]) else: print('Ignoring unrecognized token:', token) return np.array(indices, dtype=np.int32) def unvectorize(self, vector): """Transforms a vector of integers back to text""" tokens = [self._indices_token[index] for index in vector] return self._detokenize(tokens) @staticmethod def word_detokenize(tokens): # A heuristic attempt to undo the Penn Treebank tokenization above. Pass the # --pristine-output flag if no attempt at detokenizing is desired. regexes = [ # Newlines (re.compile(r'[ ]?\\n[ ]?'), r'\n'), # Contractions (re.compile(r"\b(can)\s(not)\b"), r'\1\2'), (re.compile(r"\b(d)\s('ye)\b"), r'\1\2'), (re.compile(r"\b(gim)\s(me)\b"), r'\1\2'), (re.compile(r"\b(gon)\s(na)\b"), r'\1\2'), (re.compile(r"\b(got)\s(ta)\b"), r'\1\2'), (re.compile(r"\b(lem)\s(me)\b"), r'\1\2'), (re.compile(r"\b(mor)\s('n)\b"), r'\1\2'), (re.compile(r"\b(wan)\s(na)\b"), r'\1\2'), # Ending quotes (re.compile(r"([^' ]) ('ll|'re|'ve|n't)\b"), r"\1\2"), (re.compile(r"([^' ]) ('s|'m|'d)\b"), r"\1\2"), (re.compile(r'[ ]?”'), r'"'), # Double dashes (re.compile(r'[ ]?--[ ]?'), r'--'), # Parens and brackets (re.compile(r'([\[\(\{\<]) '), r'\1'), (re.compile(r' ([\]\)\}\>])'), r'\1'), (re.compile(r'([\]\)\}\>]) ([:;,.])'), r'\1\2'), # Punctuation (re.compile(r"([^']) ' "), r"\1' "), (re.compile(r' ([?!\.])'), r'\1'), (re.compile(r'([^\.])\s(\.)([\]\)}>"\']*)\s*$'), r'\1\2\3'), (re.compile(r'([#$]) '), r'\1'), (re.compile(r' ([;%:,])'), r'\1'), # Starting quotes (re.compile(r'(β€œ)[ ]?'), r'"') ] text = ' '.join(tokens) for regexp, substitution in regexes: text = regexp.sub(substitution, text) return text.strip() @staticmethod def word_tokenize(text): # Basic word tokenizer based on the Penn Treebank tokenization script, but # setup to handle multiple sentences. Newline aware, ie newlines are # replaced with a specific token. You may want to consider using a more robust # tokenizer as a preprocessing step, and using the --pristine-input flag. regexes = [ # Starting quotes (re.compile(r'(\s)"'), r'\1 β€œ '), (re.compile(r'([ (\[{<])"'), r'\1 β€œ '), # Punctuation (re.compile(r'([:,])([^\d])'), r' \1 \2'), (re.compile(r'([:,])$'), r' \1 '), (re.compile(r'\.\.\.'), r' ... '), (re.compile(r'([;@#$%&])'), r' \1 '), (re.compile(r'([?!\.])'), r' \1 '), (re.compile(r"([^'])' "), r"\1 ' "), # Parens and brackets (re.compile(r'([\]\[\(\)\{\}\<\>])'), r' \1 '), # Double dashes (re.compile(r'--'), r' -- '), # Ending quotes (re.compile(r'"'), r' ” '), (re.compile(r"([^' ])('s|'m|'d) "), r"\1 \2 "), (re.compile(r"([^' ])('ll|'re|'ve|n't) "), r"\1 \2 "), # Contractions (re.compile(r"\b(can)(not)\b"), r' \1 \2 '), (re.compile(r"\b(d)('ye)\b"), r' \1 \2 '), (re.compile(r"\b(gim)(me)\b"), r' \1 \2 '), (re.compile(r"\b(gon)(na)\b"), r' \1 \2 '), (re.compile(r"\b(got)(ta)\b"), r' \1 \2 '), (re.compile(r"\b(lem)(me)\b"), r' \1 \2 '), (re.compile(r"\b(mor)('n)\b"), r' \1 \2 '), (re.compile(r"\b(wan)(na)\b"), r' \1 \2 '), # Newlines (re.compile(r'\n'), r' \\n ') ] text = " " + text + " " for regexp, substitution in regexes: text = regexp.sub(substitution, text) return text.split() def _create_sequences(vector, seq_length, seq_step): # Take strips of our vector at seq_step intervals up to our seq_length # and cut those strips into seq_length sequences passes = [] for offset in range(0, seq_length, seq_step): pass_samples = vector[offset:] num_pass_samples = pass_samples.size // seq_length pass_samples = np.resize(pass_samples, (num_pass_samples, seq_length)) passes.append(pass_samples) # Stack our sequences together. This will technically leave a few "breaks" # in our sequence chain where we've looped over are entire dataset and # return to the start, but with large datasets this should be neglegable return np.concatenate(passes) def shape_for_stateful_rnn(data, batch_size, seq_length, seq_step): """ Reformat our data vector into input and target sequences to feed into our RNN. Tricky with stateful RNNs. """ # Our target sequences are simply one timestep ahead of our input sequences. # eg with an input vector "wherefore"... # targets: herefore # predicts ^ ^ ^ ^ ^ ^ ^ ^ # inputs: wherefor inputs = data[:-1] targets = data[1:] # We split our long vectors into semi-redundant seq_length sequences inputs = _create_sequences(inputs, seq_length, seq_step) targets = _create_sequences(targets, seq_length, seq_step) # Make sure our sequences line up across batches for stateful RNNs inputs = _batch_sort_for_stateful_rnn(inputs, batch_size) targets = _batch_sort_for_stateful_rnn(targets, batch_size) # Our target data needs an extra axis to work with the sparse categorical # crossentropy loss function targets = targets[:, :, np.newaxis] return inputs, targets def _batch_sort_for_stateful_rnn(sequences, batch_size): # Now the tricky part, we need to reformat our data so the first # sequence in the nth batch picks up exactly where the first sequence # in the (n - 1)th batch left off, as the RNN cell state will not be # reset between batches in the stateful model. num_batches = sequences.shape[0] // batch_size num_samples = num_batches * batch_size reshuffled = np.zeros((num_samples, sequences.shape[1]), dtype=np.int32) for batch_index in range(batch_size): # Take a slice of num_batches consecutive samples slice_start = batch_index * num_batches slice_end = slice_start + num_batches index_slice = sequences[slice_start:slice_end, :] # Spread it across each of our batches in the same index position reshuffled[batch_index::batch_size, :] = index_slice return reshuffled def load_data(data_file, word_tokens, pristine_input, pristine_output, batch_size, seq_length=50, seq_step=25): global vectorizer try: with open(data_file, encoding='utf-8') as input_file: text = input_file.read() except FileNotFoundError: print("No input.txt in data_dir") sys.exit(1) skip_validate = True # try: # with open(os.path.join(data_dir, 'validate.txt'), encoding='utf-8') as validate_file: # text_val = validate_file.read() # skip_validate = False # except FileNotFoundError: # pass # Validation text optional # Find some good default seed string in our source text. # self.seeds = find_random_seeds(text) # Include our validation texts with our vectorizer all_text = text if skip_validate else '\n'.join([text, text_val]) vectorizer = Vectorizer(all_text, word_tokens, pristine_input, pristine_output) data = vectorizer.vectorize(text) x, y = shape_for_stateful_rnn(data, batch_size, seq_length, seq_step) print("Word_tokens:", word_tokens) print('x.shape:', x.shape) print('y.shape:', y.shape) if skip_validate: return x, y, None, None, vectorizer data_val = vectorizer.vectorize(text_val) x_val, y_val = shape_for_stateful_rnn(data_val, batch_size, seq_length, seq_step) print('x_val.shape:', x_val.shape) print('y_val.shape:', y_val.shape) return x, y, x_val, y_val, vectorizer def make_model(batch_size, vocab_size, embedding_size=64, rnn_size=128, num_layers=2): # Conversely if your data is large (more than about 2MB), feel confident to increase rnn_size and train a bigger model (see details of training below). # It will work significantly better. For example with 6MB you can easily go up to rnn_size 300 or even more. model = Sequential() model.add(Embedding(vocab_size, embedding_size, batch_input_shape=(batch_size, None))) for layer in range(num_layers): model.add(LSTM(rnn_size, stateful=True, return_sequences=True)) model.add(Dropout(0.2)) model.add(TimeDistributed(Dense(vocab_size, activation='softmax'))) model.compile(loss='sparse_categorical_crossentropy', optimizer='rmsprop', metrics=['accuracy']) return model def train(model, x, y, x_val, y_val, batch_size, num_epochs): print('Training...') # print("Shape:", x.shape, y.shape) # print(num_epochs, batch_size, x[0], y[0]) train_start = time.time() validation_data = (x_val, y_val) if (x_val is not None) else None callbacks = None model.fit(x, y, validation_data=validation_data, batch_size=batch_size, shuffle=False, epochs=num_epochs, verbose=1, callbacks=callbacks) # self.update_sample_model_weights() train_end = time.time() print('Training time', train_end - train_start) def sample_preds(preds, temperature=1.0): """ Samples an unnormalized array of probabilities. Use temperature to flatten/amplify the probabilities. """ preds = np.asarray(preds).astype(np.float64) # Add a tiny positive number to avoid invalid log(0) preds += np.finfo(np.float64).tiny preds = np.log(preds) / temperature exp_preds = np.exp(preds) preds = exp_preds / np.sum(exp_preds) probas = np.random.multinomial(1, preds, 1) return np.argmax(probas) def generate(model, vectorizer, seed, length=100, diversity=0.5): seed_vector = vectorizer.vectorize(seed) # Feed in seed string print("Seed:", seed, end=' ' if vectorizer.word_tokens else '') model.reset_states() preds = None for char_index in np.nditer(seed_vector): preds = model.predict(np.array([[char_index]]), verbose=0) sampled_indices = [] # np.array([], dtype=np.int32) # Sample the model one token at a time for i in range(length): char_index = 0 if preds is not None: char_index = sample_preds(preds[0][0], diversity) sampled_indices.append(char_index) # = np.append(sampled_indices, char_index) preds = model.predict(np.array([[char_index]]), verbose=0) sample = vectorizer.unvectorize(sampled_indices) return sample if __name__ == "__main__": batch_size = 32 # Batch size for each train num_epochs = 10 # Number of epochs of training out_len = 200 # Length of the output phrase seq_length = 50 # 50 # Determines, how long phrases will be used for training use_words = False # Use words instead of characters (slower speed, bigger vocabulary) data_file = "text_habr.txt" # Source text file seed = "A" # Initial symbol of the text parser = argparse.ArgumentParser() parser.add_argument("-t", "--text", action="store", required=False, dest="text", help="Input text file") parser.add_argument("-e", "--epochs", action="store", required=False, dest="epochs", help="Number of training epochs") parser.add_argument("-p", "--phrase_len", action="store", required=False, dest="phrase_len", help="Phrase analyse length") parser.add_argument("-o", "--out_len", action="store", required=False, dest="out_len", help="Output text length") parser.add_argument("-g", "--generate", action="store_true", required=False, dest='generate', help="Generate output only without training") args = parser.parse_args() if args.text is not None: data_file = args.text if args.epochs is not None: num_epochs = int(args.epochs) if args.phrase_len is not None: seq_length = int(args.phrase_len) if args.out_len is not None: out_len = int(args.out_len) # Load text data pristine_input, pristine_output = False, False x, y, x_val, y_val, vectorizer = load_data(data_file, use_words, pristine_input, pristine_output, batch_size, seq_length) model_file = data_file.lower().replace('.txt', '.h5') if args.generate is False: # Make model model = make_model(batch_size, vectorizer.vocab_size) # Train model train(model, x, y, x_val, y_val, batch_size, num_epochs) # Save model to file model.save(filepath=model_file) model = keras.models.load_model(model_file) predict_model = make_model(1, vectorizer.vocab_size) predict_model.set_weights(model.get_weights()) # Generate phrases res = generate(predict_model, vectorizer, seed=seed, length=out_len) print(res) 


Saya pikir itu menjadi generator teks yang sangat funky , yang berguna untuk menulis artikel tentang Habr . Yang sangat menarik adalah pengujian pada teks besar dan sejumlah besar iterasi pelatihan, jika ada yang memiliki akses ke komputer cepat, akan menarik untuk melihat hasilnya.

Jika ada yang ingin mempelajari topik lebih detail, deskripsi yang baik tentang menggunakan RNN dengan contoh-contoh terperinci dapat ditemukan di http://karpathy.imtqy.com/2015/05/21/rnn-effectiveness/ .

PS: Dan akhirnya, beberapa ayat;) Menarik untuk dicatat bahwa bukan saya yang melakukan pemformatan teks atau bahkan menambahkan bintang, "itu saya sendiri." Langkah selanjutnya menarik untuk memeriksa kemungkinan menggambar dan menyusun musik. Saya pikir jaringan saraf cukup menjanjikan di sini.

xxx

bagi sebagian orang, ditangkap dalam cookie - semuanya beruntung di pengadilan roti.
dan di bawah malam dari tamaki
di bawah lilin naik gunung.

xxx

segera putra mons di petachas di trem
cahaya yang tak kasatmata berbau sukacita
itu sebabnya saya mengetuk tumbuh bersama
Anda tidak akan muak dengan hal yang tidak dikenal.

hati untuk memetik ogora terhuyung,
tidak terlalu tua dari sereal yang dimakan,
Saya menjaga jembatan ke bola untuk mencuri.

dengan cara yang sama Darina di Doba,
Saya mendengar di hati saya salju di tangan saya.
kami bernyanyi putih berapa banyak dumina lembut
Aku berbalik volot binatang buas bijih.

xxx

dokter hewan menyalib dengan mantra
dan tumpah di bawah yang terlupakan.
dan Anda, put, seperti dengan cabang-cabang kuba
bersinar di dalamnya.
o bersenang-senang di zakoto
dengan penerbangan susu.

oh kamu mawar, cahaya
cloud light di tangan:
dan berguling di fajar
apa kabar, penunggang kuda saya!

dia melayani di malam hari, bukan ke tulang,
pada malam hari di Tanya lampu biru
seperti semacam kesedihan.

Dan beberapa ayat terakhir dalam belajar dengan mode kata. Di sini sajak menghilang, tetapi beberapa makna muncul (?).

dan kamu, dari nyala api
bintang-bintang.
berbicara dengan individu yang jauh.

khawatir kamu rus ,, kamu ,, besok.
"Hujan merpati,
dan rumah bagi para pembunuh,
untuk putri puteri
wajahnya.

xxx

oh gembala, lambaikan kamar
di hutan di musim semi.

Saya akan pergi melalui jantung rumah ke kolam,
dan tikus giat
Nizhny Novgorod lonceng.

tapi jangan takut, angin pagi,
dengan jalan, dengan tongkat besi,
dan berpikir dengan tiram
berlabuh di sebuah kolam
di rakit miskin.

Source: https://habr.com/ru/post/id470035/


All Articles