Merge pull request 'alexandrov_dmitrii_lab_7 is ready' (#78) from alexandrov_dmitrii_lab_7 into main
Reviewed-on: http://student.git.athene.tech/Alexey/IIS_2023_1/pulls/78
This commit is contained in:
commit
8bd93ee83e
2795
alexandrov_dmitrii_lab_7/data.txt
Normal file
2795
alexandrov_dmitrii_lab_7/data.txt
Normal file
File diff suppressed because it is too large
Load Diff
96
alexandrov_dmitrii_lab_7/lab7.py
Normal file
96
alexandrov_dmitrii_lab_7/lab7.py
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
import numpy as np
|
||||||
|
from keras_preprocessing.sequence import pad_sequences
|
||||||
|
from keras_preprocessing.text import Tokenizer
|
||||||
|
from keras.models import Sequential
|
||||||
|
from keras.layers import Dense, LSTM, Embedding, Dropout
|
||||||
|
from keras.callbacks import ModelCheckpoint
|
||||||
|
|
||||||
|
|
||||||
|
def recreate_model(predictors, labels, model, filepath, epoch_num):
|
||||||
|
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
|
||||||
|
append_epochs(predictors, labels, model, epoch_num)
|
||||||
|
|
||||||
|
|
||||||
|
def append_epochs(predictors, labels, model, filepath, epoch_num):
|
||||||
|
checkpoint = ModelCheckpoint(filepath, monitor='loss', verbose=1, save_best_only=True, mode='min')
|
||||||
|
desired_callbacks = [checkpoint]
|
||||||
|
model.fit(predictors, labels, epochs=epoch_num, verbose=1, callbacks=desired_callbacks)
|
||||||
|
|
||||||
|
|
||||||
|
def generate_text(tokenizer, seed_text, next_words, model, max_seq_length):
|
||||||
|
for _ in range(next_words):
|
||||||
|
token_list = tokenizer.texts_to_sequences([seed_text])[0]
|
||||||
|
token_list = pad_sequences([token_list], maxlen=max_seq_length - 1, padding='pre')
|
||||||
|
predicted = np.argmax(model.predict(token_list), axis=-1)
|
||||||
|
output_word = ""
|
||||||
|
for word, index in tokenizer.word_index.items():
|
||||||
|
if index == predicted:
|
||||||
|
output_word = word
|
||||||
|
break
|
||||||
|
seed_text += " " + output_word
|
||||||
|
return seed_text
|
||||||
|
|
||||||
|
|
||||||
|
def start():
|
||||||
|
flag = -1
|
||||||
|
while flag < 1 or flag > 2:
|
||||||
|
flag = int(input("Select model and text (1 - eng, 2 - ru): "))
|
||||||
|
|
||||||
|
if flag == 1:
|
||||||
|
file = open("data.txt").read()
|
||||||
|
filepath = "model_eng.hdf5"
|
||||||
|
elif flag == 2:
|
||||||
|
file = open("rus_data.txt").read()
|
||||||
|
filepath = "model_rus.hdf5"
|
||||||
|
else:
|
||||||
|
exit(1)
|
||||||
|
|
||||||
|
tokenizer = Tokenizer()
|
||||||
|
tokenizer.fit_on_texts([file])
|
||||||
|
words_count = len(tokenizer.word_index) + 1
|
||||||
|
|
||||||
|
input_sequences = []
|
||||||
|
for line in file.split('\n'):
|
||||||
|
token_list = tokenizer.texts_to_sequences([line])[0]
|
||||||
|
for i in range(1, len(token_list)):
|
||||||
|
n_gram_sequence = token_list[:i + 1]
|
||||||
|
input_sequences.append(n_gram_sequence)
|
||||||
|
|
||||||
|
max_seq_length = max([len(x) for x in input_sequences])
|
||||||
|
input_sequences = pad_sequences(input_sequences, maxlen=max_seq_length, padding='pre')
|
||||||
|
|
||||||
|
predictors, labels = input_sequences[:, :-1], input_sequences[:, -1]
|
||||||
|
|
||||||
|
model = Sequential()
|
||||||
|
model.add(Embedding(words_count, 100, input_length=max_seq_length - 1))
|
||||||
|
model.add(LSTM(150))
|
||||||
|
model.add(Dropout(0.15))
|
||||||
|
model.add(Dense(words_count, activation='softmax'))
|
||||||
|
|
||||||
|
flag = input("Do you want to recreate the model ? (print yes): ")
|
||||||
|
if flag == 'yes':
|
||||||
|
flag = input("Are you sure? (print yes): ")
|
||||||
|
if flag == 'yes':
|
||||||
|
num = int(input("Select number of epoch: "))
|
||||||
|
if 0 < num < 100:
|
||||||
|
recreate_model(predictors, labels, model, filepath, num)
|
||||||
|
|
||||||
|
model.load_weights(filepath)
|
||||||
|
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
|
||||||
|
|
||||||
|
flag = input("Do you want to train the model ? (print yes): ")
|
||||||
|
if flag == 'yes':
|
||||||
|
flag = input("Are you sure? (print yes): ")
|
||||||
|
if flag == 'yes':
|
||||||
|
num = int(input("Select number of epoch: "))
|
||||||
|
if 0 < num < 100:
|
||||||
|
append_epochs(predictors, labels, model, filepath, num)
|
||||||
|
|
||||||
|
flag = 'y'
|
||||||
|
while flag == 'y':
|
||||||
|
seed = input("Enter seed: ")
|
||||||
|
print(generate_text(tokenizer, seed, 25, model, max_seq_length))
|
||||||
|
flag = input("Continue? (print \'y\'): ")
|
||||||
|
|
||||||
|
|
||||||
|
start()
|
BIN
alexandrov_dmitrii_lab_7/model_eng.hdf5
Normal file
BIN
alexandrov_dmitrii_lab_7/model_eng.hdf5
Normal file
Binary file not shown.
BIN
alexandrov_dmitrii_lab_7/model_rus.hdf5
Normal file
BIN
alexandrov_dmitrii_lab_7/model_rus.hdf5
Normal file
Binary file not shown.
49
alexandrov_dmitrii_lab_7/readme.md
Normal file
49
alexandrov_dmitrii_lab_7/readme.md
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
### Задание
|
||||||
|
Выбрать художественный текст(четные варианты – русскоязычный, нечетные – англоязычный)и обучить на нем рекуррентную нейронную сеть для решения задачи генерации. Подобрать архитектуру и параметры так, чтобы приблизиться к максимально осмысленному результату. Далее разбиться на пары четный-нечетный вариант, обменяться разработанными сетями и проверить, как архитектура товарища справляется с вашим текстом.
|
||||||
|
|
||||||
|
Вариант 1: первостепенно - английский текст. Кооперироваться, впрочем, не с кем.
|
||||||
|
|
||||||
|
### Запуск программы
|
||||||
|
Файл lab7.py содержит и запускает программу, аргументов и настройки ~~вроде~~ не требует.
|
||||||
|
|
||||||
|
### Описание программы
|
||||||
|
Программа представляет собой консольное приложение-инструмент для работы с моделями. Она может создавать и обучать однородные модели для разных текстов.
|
||||||
|
В файлах хранятся два текста: англоязычный data.txt (Остров сокровищ) и русскоязычный rus_data.txt (Хоббит). Также там хранятся две сохранённые обученные модели:
|
||||||
|
* model_eng - модель, обученная на английском тексте. На текущий момент 27 эпох обучения.
|
||||||
|
* model_rus - модель, обученная на русском тексте. На текущий момент 12 эпох обучения.
|
||||||
|
Обучение проходило 1 день.
|
||||||
|
|
||||||
|
В программе необходимо выбрать загружаемый текст и соответствующую модель, в данный момент подключается русскоязычная модель.
|
||||||
|
|
||||||
|
Программа содержит методы пересоздания модели и дообучения модели (передаётся модель и количество эпох дообучения). Оба метода отключены и могут быть подключены обратно при необходимости.
|
||||||
|
|
||||||
|
После возможных пересоздания и дообучения моделей программа запрашивает текст-кодовое слово, которое модели будет необходимо продолжить, сгенерировав свой текст.
|
||||||
|
|
||||||
|
Сама модель имеет следующую архитектуру:
|
||||||
|
* слой, преобразующий слова в векторы плотности, Embedding с входом, равным числу слов, с выходом 100, и с длиной ввода, равной длине максимального слова.
|
||||||
|
* слой с блоками долгой краткосрочной памятью, составляющая рекуррентную сеть, LSTM со 150 блоками.
|
||||||
|
* слой, задающий степень разрыва нейронных связей между соседними слоями, Dropout с процентом разрыва 15.
|
||||||
|
* слой вычисления взвешенных сумм Dense с числом нейронов, равным числу слов в тексте и функцией активации 'softmax'
|
||||||
|
|
||||||
|
### Результаты тестирования
|
||||||
|
По результатам дневного обучения можно сказать следующее:
|
||||||
|
|
||||||
|
Модель успешно генерирует бессмысленные последовательности слов, которые либо состоят из обрывков фраз, либо случайно (но достаточно часто) складываются в осмысленные словосочетания, но не более.
|
||||||
|
|
||||||
|
Примеры генераций (первое слово - код генерации):
|
||||||
|
|
||||||
|
Модель, обученная на 'Острове сокровищ', 27 эпох обучения:
|
||||||
|
>ship that he said with the buccaneers a gentleman and neither can read and figure but what is it anyway ah 'deposed' that's it is a
|
||||||
|
>
|
||||||
|
>chest said the doctor touching the black spot mind by the arm who is the ship there's long john now you are the first that were
|
||||||
|
>
|
||||||
|
>silver said the doctor if you can get the treasure you can find the ship there's been a man that has lost his score out he
|
||||||
|
|
||||||
|
Модель, обученная на 'Хоббите', 12 эпох обучения:
|
||||||
|
>дракон и тут они услыхали про смога он понял что он стал видел и разозлился как слоны у гэндальфа хороши но все это было бы он
|
||||||
|
>
|
||||||
|
>поле он не мог сообразить что он делал то в живых и слышал бильбо как раз доедал пуще прежнего а бильбо все таки уж не мог
|
||||||
|
>
|
||||||
|
>паук направился к нему толстому из свертков они добрались до рассвета и даже дальше не останавливаясь а именно что гоблины обидело бильбо они не мог ничего
|
||||||
|
|
||||||
|
Итого: Даже такая простая модель с таким малым количеством эпох обучения может иногда сгенерировать нечто осмысленное. Однако для генерации нормального текста необходимо длительное обучение и более сложная модель, из нескольких слоёв LSTM и Dropout после них, что, однако, потребовало бы вычислительные мощности, которых у меня нет в наличии. Иначе следует взять очень маленький текст.
|
6838
alexandrov_dmitrii_lab_7/rus_data.txt
Normal file
6838
alexandrov_dmitrii_lab_7/rus_data.txt
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user