Я и ChatGPT написали нейросеть. Она предназначена для генерации текста по символам, то есть модель будет обучаться не только генерировать слова, она будет понимать знаки препинания и переходить на следующие строки.

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

Написание кода проходило в 3 этапа

  1. Создание модели

  2. Обучение на текстовых данных

  3. Генерация текста

Создание модели

ChatGPT сгенерировал простую модель с Embedding, LSTM, и Dense слоями со 128 нейронами в каждом, поэтому она мне показалась очень простой. Я добавил Bidimensional для двунаправленности, GlobalMaxPooling1D для свёрточного сжатия в одномерный массив, Flatten для перехода от свёрточных слоев к полносвязному слою и дополнительный слой Dense.

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding, Bidirectional, LSTM, Dense, Flatten, GlobalMaxPooling1D
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
import numpy as np

# Определим функцию для создания модели
def create_model(total_words, max_sequence_len):
    model = Sequential()
    model.add(Embedding(total_words, 1000, input_length=max_sequence_len-1))
    model.add(Bidirectional(LSTM(1000, return_sequences=True)))
    model.add(GlobalMaxPooling1D()) # Добавлено мной
    model.add(Flatten()) # Добавлено мной
    model.add(Dense(1000, activation='relu')) # Добавлено мной
    model.add(Dense(total_words, activation='softmax'))
    model.compile(loss='categorical_crossentropy', optimizer='adam')
    return model

Обучение на текстовых данных

ChatGPT написал простой метод обучения ИИ модели ни 10 эпохах. Это хорошо, но мы не знаем, когда нейросеть обучится. Может быть нейросети хватит и 3-х эпох, а может она за 200 не справится? Я представляю вам мой метод обучения, основанный на обучении до тех пор, пока модель не достигнет определённой точности при обучении.

# Создание и обучение модели моим методом
model = create_model(total_chars, max_sequence_len)
accuracy = 0
epochs = 0
while accuracy < 0.7: # Обучаем модель, пока она не достигнет определённого уровня точности.
    model.fit(xs, ys, epochs=1, verbose=1)
    loss, accuracy = model.evaluate(xs, ys, verbose=0)
    epochs += 1

Довольно необычно, не так ли? Обучение будет длиться столько, сколько нужно. В строке перед циклом можно поменять значение от 0 до 1. В зависимости от того, что вам нужно.

Генерация текста

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

# Генерация текста
def generate_text(seed_text, next_chars, model, max_sequence_len):
    generated_text = seed_text
    for _ in range(next_chars):
        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)[0]
        predicted = np.argmax(predicted_probs)
        output_char = tokenizer.index_word.get(predicted, "")
        seed_text += output_char
        generated_text += output_char

    return generated_text

# Генерация текста с использованием модели
while True: # Я просто зациклил эту часть, чтобы вам не пришлось снова и снова запускать код
    seed_text = input("Вы: ")
    next_chars = 500
    generated_text = generate_text(seed_text, next_chars, model, max_sequence_len)
    print(generated_text)

Итоговый код программы выглядит так:

import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Embedding, Bidirectional, LSTM, Dense, Flatten, GlobalMaxPooling1D
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
import numpy as np

# Определим функцию для создания модели
def create_model(total_words, max_sequence_len):
    model = Sequential()
    model.add(Embedding(total_words, 1000, input_length=max_sequence_len-1))
    model.add(Bidirectional(LSTM(1000, return_sequences=True)))
    model.add(GlobalMaxPooling1D())
    model.add(Flatten())
    model.add(Dense(1000, activation='relu'))
    model.add(Dense(total_words, activation='softmax'))
    model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
    return model

# Обучающие данные (нужно заполнить данными)
TextData = """
"""

# Подготовка данных
tokenizer = Tokenizer(char_level=True)
tokenizer.fit_on_texts(TextData)
total_chars = len(tokenizer.word_index) + 1
max_sequence_len = 50

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)

# Создание и обучение модели
model = create_model(total_chars, max_sequence_len)
accuracy = 0
epochs = 0
while accuracy < 0.7:
    model.fit(xs, ys, epochs=1, verbose=1)
    loss, accuracy = model.evaluate(xs, ys, verbose=0)
    epochs += 1

# сохранение обученной модели
model.save('TextGenerator3000.h5')

# Генерация текста
def generate_text(seed_text, next_chars, model, max_sequence_len):
    generated_text = seed_text
    for _ in range(next_chars):
        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)[0]
        predicted = np.argmax(predicted_probs)
        output_char = tokenizer.index_word.get(predicted, "")
        seed_text += output_char
        generated_text += output_char

    return generated_text

# Генерация текста с использованием модели
while True:
    seed_text = input("Вы: ")
    next_chars = 500
    generated_text = generate_text(seed_text, next_chars, model, max_sequence_len)
    print(generated_text)

Вы можете просто скопировать код выше и запустить где нибудь. Не забудьте скачать библиотеки Tensorflow и NumPy, если запускаете в PyCharm.

На этом я заканчиваю свой первый блог. Если появятся вопросы, пишите в комментариях!

Комментарии (16)


  1. rsashka
    01.06.2024 07:22
    +1

    Черт побери, вы выпустили джина из бутылки! :-)


  1. Dynasaur
    01.06.2024 07:22
    +1

    простите, а где тут задаётся корпус данных, на котором проводится обучение? Видимо, вот тут:

    # Обучающие данные (нужно заполнить данными)
    TextData = """
    """

    можете для примера привести несколько вариантов заполнения?


    1. TheScienceVictor200 Автор
      01.06.2024 07:22
      +1

      TextData="""Привет, я нейросеть, написанная TheScienceVictor200."""

      Вы можете использовать любую другую информацию, например статьи, книги и прочее, если есть вычислительные ресурсы.

      Так же длина текста должна быть больше 50 символов, иначе будет ошибка.


      1. Dynasaur
        01.06.2024 07:22

        Что, прямо весь текст книги вставить в кавычки?


        1. TheScienceVictor200 Автор
          01.06.2024 07:22
          +1

          Зависит от того, что вам нужно. Но я не рекомендую этого делать, если вы не хотите несколько суток ждать, пока модель обучится. Лучше попробуй сначала обучить её на небольших текстах, длиной более 50, но менее 1000 символов для эксперимента. Если есть вычислительные ресурсы, можете обучать на книгах. Я свою обучал на диалоге меня и ChatGPT.


  1. vasan
    01.06.2024 07:22
    +1

    Эх, как бы этот код на C++ портировать, чтобы подцепить к одному интересному проекту...???


    1. TheScienceVictor200 Автор
      01.06.2024 07:22

      Попробуй запустить код на PyCharm, установив нужные библиотеки. Изменить нужно лишь эту часть кода:

      # Генерация текста с использованием модели
      while True:
          seed_text = input("Вы: ")
          next_chars = 500
          generated_text = generate_text(seed_text, next_chars, model, max_sequence_len)
          print(generated_text)

      Конечно, не изучал C++, но вместо seed_text = input("Вы: ") вы можете использовать ввод текста в окне C++, который будет отправлять текстовый файл Question.txt , как запрос, а после на выходе вместо print(generated_text) будет отправляться текстовый файл Answer.txt с ответом, который будет прочитан кодом на C++


      1. vasan
        01.06.2024 07:22

        Да у меня имеется JetBrains PyCharm Community Edition 2017.2.1 x64, несколько лет назад изучал работу некоторых программ на Python, однако всё сводилось к банальному разбору кода, в последствии вручную переписывания на С++. Хотя пожалуй попробую использовать онлайн конвертер https://www.codeconvert.ai/python-to-c++-converter


  1. Steparist
    01.06.2024 07:22
    +1

    Неделю назад начал писать что-то похожее на Character Ai. Чем-то похоже на вашу нейронку, но я промпты кодировал в one-hot векторы, которые потом давал на вход сети. Сейчас обучаю, пока до генерации текста не дошло)


    1. TheScienceVictor200 Автор
      01.06.2024 07:22
      +1

      Продолжай в том же духе. У тебя всё получится!


      1. Steparist
        01.06.2024 07:22

        Спасибо, надеюсь, у тебя тоже! Приятно видеть таких людей на Хабре


  1. Atlas_com
    01.06.2024 07:22
    +2

    Всё классно, но теперь бы знать что загрузить для обучения(


    1. TheScienceVictor200 Автор
      01.06.2024 07:22

      Можно использовать вообще любой текст

      Пример:

      TextData="""Привет! Я нейросеть от TheScienceVictor200.
      Я могу быть обучен на тексте, длиной более 50 символов!"""


  1. TheScienceVictor200 Автор
    01.06.2024 07:22

    В TextData введите любой текст, длиной более 50 символов

    Пример:

    TextData = """Привет! Я нейросеть то TheScienceVictor200
    Я могу быть обучен вообще на любых текстах, например статьях.""

    Но помните! Вам потребуется большие вычислительные ресурсы, если вы хотите обучить её на реально гигантском объёме данных, например на книге.


  1. Fichan
    01.06.2024 07:22

    Здравствуйте! Большое спасибо за Ваш труд. Но я столкнулась с небольшим непонимание. После обучения, там где должен выводиться текст, мне выводятся строчки 1/1 [==============================] - 0s 450ms/step и повтор моего input. Что не так?


    1. TheScienceVictor200 Автор
      01.06.2024 07:22

      Если вы обучили нейросеть очень плохо, например при одной эпохе и малом тексте, она будет сомневаться, что сгенерировать, неопределённые символы не генерируются и на выходе получаем тот же входной текст. Просто обучи её по дольше и на более высокую точность.

      Строчки 1/1 [==============================] - 0s 450ms/step просто говорят, что нейросеть сгенерировала символ.

      Вы можете бесплатно протестировать нейросеть в Google Collab, где тебе дадут большие мощности по сравнению с твоим компьютером, так как 450ms — это долго.