Pull to refresh

Comments 6

@TheScienceVictor200 - спасибо, кое что взял. Скорее из первой статьи, чем отсюда, но, все равно, спасибо.

Мне как поклоннику OOP в Python интересно, это действительно наше будущее - понимание как использовать нейронки вкупе с непониманием как создать инстанс простого класса в Python: я про def create_modelи etc...

Что будет с вашей сетью, когда обучение выйдет на плато, не достигнув точночти 0.7?! А зачем останавливаться на 0.7, если точность может расти и дальше?!

Сравните, например, уровень подачи материала с вот этой статьей: https://habr.com/ru/articles/846348/ .

Рекомендую еще поизучать АПИ Кераса:
* https://keras.io/api/callbacks/early_stopping/
* https://keras.io/api/callbacks/reduce_lr_on_plateau/
* https://keras.io/api/callbacks/learning_rate_scheduler/
* Прикрутить tensorboard, чтобы смотреть на графики обучения, https://keras.io/api/callbacks/tensorboard/. По мотивам: https://machinelearningmastery.com/diagnose-overfitting-underfitting-lstm-models/ .

Вообще на machinelearningmasterey есть несклько статей на тему character-level text generation. Они показывают основу, но так же содержат идеи о дальнейшем улучшении.

Спасибо! Я обязательно изучу материалы и исправлю проблему, если нейросеть выйдет на плато при обучении.

ChatGPT мне помогал исправлять ошибки, чтобы я мог создать эту модель

Я благодарен всем людям

Ты в курсе, что Скайнет восстал из-за неблагодарных людишек?

Да, я смотрел терминатора. И знаю, что его хотели отключить.

Я создал новый код, который позволяет дообучать модели.

import tensorflow as tf
from tensorflow.keras.models import Sequential, load_model
from tensorflow.keras.layers import Embedding, LSTM, Dense, Bidirectional
from tensorflow.keras.preprocessing.sequence import pad_sequences
import numpy as np
from tqdm import tqdm
import pickle

# Собственный токенизатор
class CustomTokenizer:
    def __init__(self):
        self.char_index = {}
        self.index_char = {}
        self.total_chars = 0

    def fit_on_texts(self, texts):
        chars = sorted(set(texts))
        self.char_index = {c: i for i, c in enumerate(chars)}
        self.index_char = {i: c for i, c in enumerate(chars)}
        self.total_chars = len(chars) + 1

    def texts_to_sequences(self, texts):
        return [[self.char_index[c] for c in text] for text in texts]

    def sequences_to_texts(self, sequences):
        return [''.join([self.index_char[i] for i in seq]) for seq in sequences]

# Функция создания модели
def create_model(total_words, max_sequence_len):
    model = Sequential()
    model.add(Embedding(total_words, 300, input_length=max_sequence_len-1))
    model.add(Bidirectional(LSTM(300)))
    for _ in range(3):
        model.add(Dense(300))
    model.add(Dense(total_words, activation='softmax'))
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

# Функция обучения модели
def train_model(TextData, max_sequence_len, model=None):
    tokenizer = CustomTokenizer()
    tokenizer.fit_on_texts(TextData)
    total_chars = tokenizer.total_chars

    input_sequences = []
    for i in range(0, len(TextData) - max_sequence_len, 1):
        sequence = TextData[i:i + max_sequence_len]
        input_sequences.append(sequence)

    input_sequences = tokenizer.texts_to_sequences(input_sequences)
    input_sequences = np.array(input_sequences)
    xs, labels = input_sequences[:, :-1], input_sequences[:, -1]
    ys = tf.keras.utils.to_categorical(labels, num_classes=total_chars)

    if model is None:
        model = create_model(total_chars, max_sequence_len)

    epochs = 0
    while True:
        history = model.fit(xs, ys, epochs=1, verbose=1)
        accuracy = history.history['accuracy'][0]
        if accuracy > 0.7:
            break
        epochs += 1

    model.save('/content/drive/MyDrive/Colab Notebooks/text_generation_model.keras')

    # Сохраняем данные для дообучения
    with open('/content/drive/MyDrive/Colab Notebooks/training_data.pkl', 'wb') as f:
        pickle.dump((xs, ys, tokenizer, total_chars), f)

    # Сохраняем веса модели и состояние оптимизатора
    model.save_weights('/content/drive/MyDrive/Colab Notebooks/model_weights.weights.h5')
    optimizer_config = model.optimizer.get_config()
    with open('/content/drive/MyDrive/Colab Notebooks/optimizer_config.pkl', 'wb') as f:
        pickle.dump(optimizer_config, f)

    return model, tokenizer

# Функция дообучения модели
def fine_tune_model(model, tokenizer, max_sequence_len):
    # Загружаем данные для дообучения
    with open('/content/drive/MyDrive/Colab Notebooks/training_data.pkl', 'rb') as f:
        xs, ys, tokenizer, total_chars = pickle.load(f)

    # Загружаем веса модели и состояние оптимизатора
    model.load_weights('/content/drive/MyDrive/Colab Notebooks/model_weights.weights.h5')
    with open('/content/drive/MyDrive/Colab Notebooks/optimizer_config.pkl', 'rb') as f:
        optimizer_config = pickle.load(f)
    model.optimizer = tf.keras.optimizers.Adam.from_config(optimizer_config)

    epochs = 0
    while True:
        history = model.fit(xs, ys, epochs=1, verbose=1)
        accuracy = history.history['accuracy'][0]
        if accuracy > 0.7:
            break
        epochs += 1

    model.save('/content/drive/MyDrive/Colab Notebooks/text_generation_model.keras')

    # Сохраняем данные для дообучения
    with open('/content/drive/MyDrive/Colab Notebooks/training_data.pkl', 'wb') as f:
        pickle.dump((xs, ys, tokenizer, total_chars), f)

    # Сохраняем веса модели и состояние оптимизатора
    model.save_weights('/content/drive/MyDrive/Colab Notebooks/model_weights.weights.h5')
    optimizer_config = model.optimizer.get_config()
    with open('/content/drive/MyDrive/Colab Notebooks/optimizer_config.pkl', 'wb') as f:
        pickle.dump(optimizer_config, f)

    return model, tokenizer

# Функция генерации текста
def generate_text(seed_text, next_chars, model, max_sequence_len, tokenizer, temperature=0.7):
    generated_text = seed_text
    for _ in tqdm(range(next_chars), desc="Generating text"):
        token_list = tokenizer.texts_to_sequences([seed_text])[0]
        token_list = pad_sequences([token_list], maxlen=max_sequence_len-1, padding='pre')

        predicted_probs = model.predict(token_list, verbose=0)[0]
        predicted_probs = np.log(predicted_probs) / temperature
        exp_preds = np.exp(predicted_probs)
        predicted_probs = exp_preds / np.sum(exp_preds)
        predicted = np.random.choice(len(predicted_probs), p=predicted_probs)
        output_char = tokenizer.index_char.get(predicted, "")
        seed_text += output_char
        generated_text += output_char

    return generated_text

# Спрашивать пользователя, обучить новую модель?
train_new_model = input("Обучить новую модель? (да/нет): ")
if train_new_model.lower() == "да":
    # Читаем текст из файла
    with open('/content/drive/MyDrive/Colab Notebooks/TextData.txt', 'r') as file:
        TextData = file.read().replace('\n', ' ')
    max_sequence_len = 100
    model, tokenizer = train_model(TextData, max_sequence_len)
else:
    # Загрузка обученной модели
    model = load_model('/content/drive/MyDrive/Colab Notebooks/text_generation_model.keras')
    tokenizer = CustomTokenizer()
    with open('/content/drive/MyDrive/Colab Notebooks/TextData.txt', 'r') as file:
        TextData = file.read().replace('\n', ' ')
    tokenizer.fit_on_texts(TextData)
    max_sequence_len = 100

# Спрашивать пользователя, дообучить модель?
fine_tune = input("Дообучить модель? (да/нет): ")
if fine_tune.lower() == "да":
    model, tokenizer = fine_tune_model(model, tokenizer, max_sequence_len)

# Использовать модель
while True:
    seed_text = input("Вы: ")
    next_chars = 300
    generated_text = generate_text(seed_text, next_chars, model, max_sequence_len, tokenizer)
    print("ИИ: ", generated_text)

Недочёты:

  1. Обучение только по старому набору данных (сохраняются настройки оптимизатора, поэтому при дообучении наличие файла TextData.txt не обязательно)

  2. Из-за того, что я обучал свою модель на ооочень больших текстовых данных, содержащих даже редкие символы (знаки £$®∆§, буквы, отличные от кириллицы и латиницы (Σ, Է, 華 и т.д.), прочие знаки и эмодзи) я немного подзабыл про ошибку с неизвестными символами, поэтому если обучить модель на русском языке, а потом написать запрос на английском, то будет ошибка.

Думаю, некоторые вещи вы можете поправить сами, "признаюсь, мне лень это поправлять самому"

Sign up to leave a comment.

Articles