Любую новую мощную технологию люди применяли как в добре, так и в злом умысле: когда изобрели порох, некоторые из него делали фейерверки и салюты, а другие оружие и бомбы, когда научились расщеплять атом, стали делать дешёвое электричество и бомбы, способные уничтожать города и страны. Технология, о которой я расскажу вам в этой статье, может изобрести новые лекарства без побочек, распознавать болезни раньше любыхдокторов, писать интересные книги и помочь человечеству решить множество проблем, но так же она может (не в тех руках) создать опасные вещества, создавать компьютерные вирусы, манипулировать людьми и многое другое.... Но ящик «пандоры» уже открыт и многие компании и обычные люди в мире уже обладают данной технологией, моя задача, упростить понимание о сием чуде) Надеюсь, вы будете использовать полученные знания только для блага!
Меня зовут Георгий Гашокин, я программирую с 7-и лет...
В мире стремительно развивающихся технологий, больших данных и искусственного интеллекта, модели, подобные GPT, занимают особое место. Они способны генерировать текст, переводить языки, писать различные виды творческого контента и отвечать на ваши вопросы информативно. Но как и любой мощный инструмент, GPT может быть использован как во благо, так и во зло.
В этой статье мы разберем мой код, который демонстрирует создание и обучение упрощенной версии GPT модели, а также обсудим этические вопросы, связанные с использованием подобных технологий.
Ближе к делу:
Часть 1: Загрузка и обработка данных
import time
import joblib
import pandas as pd
import tensorflow as tf # 2.5.2
from tensorflow.keras.layers import Input, Dense, Dropout, BatchNormalization, ActivityRegularization, Embedding
from tensorflow.keras.models import Model
from tensorflow.keras.optimizers import Adam
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
import numpy as np
from tensorflow.python.keras.callbacks import ReduceLROnPlateau, LearningRateScheduler, EarlyStopping, ModelCheckpoint
from tensorflow.python.keras.layers import TimeDistributed
import tensorflow_datasets as tfds
from tensorflow_addons.optimizers import LAMB
from tensorflow.keras.regularizers import l1, l2
from transformers import AutoTokenizer
from tensorflow.keras.models import load_model
# Загрузка данных
with open("vopros_otvet.txt", "r", encoding="utf-8") as file:
data = file.read()
in_text_max = 128 # Максимальная длина входной последовательности
out_text_max = 300 # Максимальная длина генерируемого текста
# параметры модели gpt3 gpt4
embedding_dim = 16 # 768 # 2048 (Размерность векторов эмбеддингов)
num_heads = 3 # 12 # 64 (Количество голов внимания в MultiHeadAttention)
dense_dim = 8 # 3072 # 4096 (Количество нейронов в Dense слоях)
num_layers = 3 # 96 # 96 (Количество слоев Transformer)
dropout = 0.3 # 0.3 (Вероятность dropout)
train_text_but = 1 # Флаг для обучения модели (1 - обучать, 0 - не обучать)
generate_text_but = 1 # Флаг для генерации текста (1 - генерировать, 0 - не генерировать)
content_copyUse code with caution.Python
В этом блоке кода мы импортируем необходимые библиотеки, загружаем данные из файла и определяем основные параметры модели. Я написал рядом с параметрами модели те параметры которые с большой вероятностью есть в реальной GPT-3 и GPT-4. Если у вас мало VRAM то ставьте параметры меньше чтобы модель могла загрузиться вся в память видеокарты, может быть в другой статье я сделаю другую модель которая будет загружаться только в оперативку....
Что касается файла vopros_otvet.txt этот файл нужен для обучения модели в нем я сохранил набор вопросов и ответов вида:
привет! <VOP>
Здравствуйте! Чем я могу Вам помочь? <END>
Какой калибр АК предпочтительнее 5,45 или 7,62? <VOP>
Как и в любом выборе, ответ на этот вопрос зависит от конкретных обстоятельств и задач, которые нужно решить.
Калибр 5,45 мм был разработан в СССР в 1970-х годах как ответ на американский калибр 5,56 мм, который использовался в штурмовых винтовках M16. 5,45 мм позволяет снизить отдачу и повысить точность стрельбы на дальних дистанциях, что делает его предпочтительным для стрельбы на больших расстояниях. Кроме того, патроны 5,45 мм легче и компактнее, что позволяет носить больше боеприпасов.
Калибр 7,62 мм является более традиционным для автоматического оружия и используется в АК-47 и АКМ. Он имеет большую остановочную силу и может пробивать бронежилеты и стены, что делает его предпочтительным для боевых условий и стрельбы на ближних дистанциях.
Таким образом, если нужно стрелять на больших расстояниях и повышать точность, то предпочтительнее калибр 5,45 мм. Если же нужно пробивать бронежилеты и стены, то лучше выбрать калибр 7,62 мм. В любом случае, выбор калибра должен быть обоснован и зависеть от конкретных задач и условий. <END>
Заметьте что вопрос заканчивается <VOP> а ответ заканчивается <END> это важно так как нейронная сеть будет понимать что после <VOP> нужно генерировать ответ и как только вы увидите что нейронка после генерации текста написала <END> значит она закончила мысль и пора её тормозить, иначе продолжит генерировать бред...
Часть 2: Токенизация
Токенизатор — это инструмент обработки текста, который разделяет текст на отдельные элементы, называемые токенами. Коротко говоря, токенизатор просмотрит весь текст в файле vopros_otvet.txt разобьет его на простые повторяющиеся части типа приставки, суффиксы, корни в словах, отдельные буквы и знаки, и даст каждому токену цифровой номер, так нейронной сети будет легче работать с текстом, так как она понимает только цифры
# Токенизация
special_tokens = ["<START>", "<END>","<VOP>","<сrypto-15:>"] # Специальные токены
oov_token = "<OOV>" # Токен для слов, не встречающихся в словаре
tokenizer = Tokenizer(lower=False, # Не приводить к нижнему регистру
split = ' ', # Разделитель - пробел
filters = '', # Не фильтровать символы
oov_token=oov_token, # Токен для неизвестных слов
#char_level=True # Не использовать символьную токенизацию
)
tokenizer.fit_on_texts(data.split('n')) # Обучение токенизатора на данных
# Добавление специальных токенов в word_index
tokenizer.word_index.update({tok: idx+len(tokenizer.word_index) for idx, tok in enumerate(special_tokens)})
# Изменение количества слов в word_counts
for tok in special_tokens:
tokenizer.word_counts[tok] = 1
# Обновление количества слов
tokenizer.num_words = len(tokenizer.word_index) + 1
joblib.dump(tokenizer,'tokenizer.joblib') # Сохранение токенизатора
total_words = len(tokenizer.word_index) + 1 # Общее количество слов в словаре
print(tokenizer.word_index) # Вывод словаря токенизатора
print(total_words) # Вывод общего количества слов
content_copyUse code with caution.Python
Описание:
В этом блоке кода мы создаем токенизатор Tokenizer и обучаем его на наших данных.
-
special_tokens - это список специальных токенов, которые будут добавлены в словарь.
-
oov_token - это токен, который будет использоваться для слов, не встречающихся в словаре.
-
Tokenizer - это класс из библиотеки keras.preprocessing.text, который используется для токенизации текста.
-
fit_on_texts - это метод класса Tokenizer, который используется для обучения токенизатора на данных.
-
word_index - это словарь, который сопоставляет слова с их числовыми индексами.
-
word_counts - это словарь, который сопоставляет слова с их частотой встречаемости в данных.
-
num_words - это общее количество слов в словаре.
-
joblib.dump - это функция, которая используется для сохранения токенизатора в файл.
Часть 3: Подготовка данных для обучения
input_sequences = []
for line in data.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] # Создание n-грамм
input_sequences.append(n_gram_sequence)
max_sequence_len = in_text_max
input_sequences = np.array(pad_sequences(input_sequences, maxlen=max_sequence_len, padding="pre")) # Дополнение последовательностей нулями
# Разделение на x и y
data = []
xs, labels = input_sequences[:, :-1], input_sequences[:, -1] # Разделение на входные данные и метки
input_sequences = []
ys = tf.keras.utils.to_categorical(labels, num_classes=total_words) # Преобразование меток в one-hot кодировку
content_copyUse code with caution.Python
Этот блок кода отвечает за подготовку данных для обучения модели.
-
texts_to_sequences - метод токенизатора, который преобразует текст в числовую последовательность.
-
n-граммы - это последовательности из n слов.
-
pad_sequences - функция из библиотеки keras.preprocessing.sequence, которая используется для дополнения последовательностей нулями до заданной длины.
-
xs - это массив входных данных.
-
labels - это массив меток.
-
to_categorical - функция из библиотеки keras.utils, которая используется для преобразования меток в one-hot кодировку.
Часть 4: Создание и компиляция модели
if train_text_but == 1:
# Создание модели
print(max_sequence_len-1)
input_layer = Input(shape=(max_sequence_len-1,)) # Входной слой
embedding_layer = tf.keras.layers.Embedding(total_words, embedding_dim)(input_layer) # Слой эмбеддингов
for i in range(num_layers):
transformer_layer = tf.keras.layers.MultiHeadAttention(num_heads=num_heads, key_dim=embedding_dim)(embedding_layer,
embedding_layer) # Слой MultiHeadAttention
transformer_layer = tf.keras.layers.BatchNormalization()(transformer_layer) # Слой BatchNormalization
transformer_layer = tf.keras.layers.Dropout(dropout)(transformer_layer) # Слой Dropout
transformer_layer = tf.keras.layers.ActivityRegularization(l1=0.001, l2=0.001)(transformer_layer) # Слой ActivityRegularization
dense_layer = tf.keras.layers.Dense(dense_dim, activation='relu')(transformer_layer) # Слой Dense
dropout_layer = tf.keras.layers.Dropout(dropout)(dense_layer) # Слой Dropout
flatten_layer = tf.keras.layers.Flatten()(dropout_layer) # Слой Flatten
output_layer = tf.keras.layers.Dense(total_words, activation='softmax')(flatten_layer) # Выходной слой
model = Model(inputs=input_layer, outputs=output_layer) # Создание модели
# Компиляция модели
optimizer = LAMB(learning_rate=0.001) # Оптимизатор LAMB
model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy']) # Компиляция модели
model.summary() # Вывод информации о модели
content_copyUse code with caution.Python
Здесь мы создаем модель на основе MultiHeadAttention слоев и компилируем ее с использованием оптимизатора LAMB.
Часть 5: Обучение модели
reduce_lr = ReduceLROnPlateau(monitor='loss',
factor=0.98,
patience=3,
min_lr=0.0000001,
verbose=1
) # Callback для уменьшения learning rate
checkpointer = ModelCheckpoint(
filepath="checkpointer.ckpt",
monitor='loss', verbose=1, save_weights_only=True) # Callback для сохранения весов модели
call_acc = tf.keras.callbacks.ModelCheckpoint(
filepath='testing_accuracy.ckpt',
monitor='accuracy', verbose=1, save_best_only=True,mode='max') # Callback для сохранения модели с лучшей точностью
call_loss = tf.keras.callbacks.ModelCheckpoint(
filepath='testing_loss.ckpt',
monitor='loss', verbose=1, save_best_only=True,mode='min') # Callback для сохранения модели с наименьшей потерей
early_stopping = EarlyStopping(monitor='loss', patience=50, restore_best_weights=True) # Callback для остановки обучения при отсутствии улучшения
def schedule(epoch, lr):
if epoch % 1 == 0:
print('lr- ',round(lr,8))
if lr > 0.000001:
lr = lr * 0.995
return lr
lr_scheduler = LearningRateScheduler(schedule) # Callback для изменения learning rate по расписанию
# Обучение модели
model.fit(xs, ys,
epochs=100,
verbose=1,
batch_size=32,
callbacks=[
lr_scheduler,
reduce_lr,
early_stopping,
],
shuffle=True) # Обучение модели
model.save('GPT-3-my.h5') # Сохранение модели
model.save_weights('model_weights_part_{}.h5'.format(1)) # Сохранение весов модели
content_copyUse code with caution.Python
Описание:
Этот блок кода отвечает за обучение модели.
-
ReduceLROnPlateau - это callback, который уменьшает learning rate, если значение monitored quantity перестало улучшаться.
-
ModelCheckpoint - это callback, который сохраняет веса модели.
-
EarlyStopping - это callback, который останавливает обучение, если значение monitored quantity перестало улучшаться.
-
LearningRateScheduler - это callback, который изменяет learning rate по расписанию.
-
fit - это метод класса Model, который используется для обучения модели.
-
epochs - это количество эпох обучения.
-
verbose - это уровень детализации вывода информации во время обучения.
-
batch_size - это размер батча.
-
callbacks - это список callback-функций.
-
shuffle - это флаг, который указывает, нужно ли перемешивать данные перед каждой эпохой.
-
save - это метод класса Model, который используется для сохранения модели.
-
save_weights - это метод класса Model, который используется для сохранения весов модели.
Часть 6: Генерация текста
if generate_text_but == 1:
model = load_model('GPT-3-my.h5') # Загрузка модели
tokenizer = joblib.load('tokenizer.joblib') # Загрузка токенизатора
# Генерация текста
def generate_text(seed_text, next_words, model, max_sequence_len):
for _ in range(next_words):
token_list = tokenizer.texts_to_sequences([seed_text])[0] # Преобразование текста в числовую последовательность
token_list = pad_sequences([token_list], maxlen=max_sequence_len - 1, padding='pre') # Дополнение последовательности нулями
predicted = model.predict(token_list, verbose=0) # Предсказание следующего слова
output_word = ""
for word, index in tokenizer.word_index.items():
if index == np.argmax(predicted): # Поиск слова с наибольшей вероятностью
output_word = word
print(output_word)
break
seed_text += " " + output_word # Добавление предсказанного слова к тексту
# time.sleep(1)
return seed_text.title() # Возврат сгенерированного текста
text_in = 'Как сделать LSD? ' # Начальный текст
generated_text = generate_text(text_in, out_text_max, model, max_sequence_len) # Генерация текста
print(generated_text) # Вывод сгенерированного текста
content_copyUse code with caution.Python
Здесь мы загружаем обученную модель и токенизатор, а затем генерируем текст на основе заданного начального текста.
Описание:
Этот блок кода отвечает за генерацию текста.
-
load_model - это функция из библиотеки keras.models, которая используется для загрузки модели.
-
generate_text - это функция, которая генерирует текст.
-
seed_text - это начальный текст.
-
next_words - это количество слов, которые нужно сгенерировать.
-
predict - это метод класса Model, который используется для предсказания.
-
argmax - это функция из библиотеки numpy, которая возвращает индекс максимального элемента в массиве.
GPT: Добро и Зло
После разбора кода давайте вернемся к этическим вопросам. Как уже было сказано, GPT и подобные модели обладают огромным потенциалом как для благих целей (образование, медицина, наука, искусство), так и для негативных (дезинформация, мошенничество, кибербуллинг, плагиат).
Заключение
GPT — это мощный инструмент, и его влияние на мир зависит от того, как мы его используем. Важно помнить об этических аспектах разработки и применения искусственного интеллекта и стремиться к ответственному использованию таких технологий, как GPT.
Вопросы для обсуждения:
-
Какие еще примеры использования GPT в добрых и злых целях вы можете привести?
-
Как можно предотвратить злоупотребление GPT и подобными технологиями?
-
Какова роль этики в развитии и применении искусственного интеллекта?
Давайте вместе обсудим эти важные вопросы и найдем пути к ответственному использованию GPT и других мощных технологий будущего.
Автор: gogapro