Привет! Я Лёша, позывной
@а1ex_maв соцсетях и мессенджерах. Люблю нейросети, аниме, мангу и женщин-андроидов. Это моя первая публикация на Хабре — в ней я рассказываю о том, как создал свою первую нейросеть.
Один мой приятель мечтал разбогатеть, играя на бирже. Однажды, рассуждая с ИИ на тему выигрышной биржевой стратегии, он получил совет использовать линейную аппроксимацию по методу наименьших квадратов для вычисления линии тренда, а также использовать pandas для обработки значительных по объему данных — биржевых индексов и котировок акций. И, вишенкой на торте, нейросеть посоветовала ему создать нейросеть для предсказания результатов на основе предыдущих торговых сессий.
Мой приятель понимал, возможно, лишь часть из этих слов, но он очень верил в то, что нейросеть плохого не посоветует — и знал, что я занимаюсь чем-то подобным, поэтому сразу позвонил мне. А я в то время как раз был на середине изучения полугодового курса «Анализ данных»: python, pandas, sql etc.
Он обратился по адресу. Меня зацепила эта идея — нейросеть, которая дает совет написать нейросеть. А чтобы усилить этот сюр, я решил написать нейросеть с помощью нейросети. Абсолютный абсурд в квадрате — как раз то, что я люблю больше всего.
Эта история происходила на самой начальной фазе волны нарастающего хайпа вокруг нейросетей. Так получилось, что за короткий период времени сразу несколько человек написало мне с паническими настроениями: "Все пропало! Нас скоро заменят роботами!"
В учебных и ознакомительных целях я пригласил их присоединиться к нашему проекту, чтобы понять, что представляют из себя нейросети на практике, и на что они способны. Да мне и самому было интересно.
Я дал нейросети развернутый промпт (тогда это была одна из ранних версий ChatGPT), загнал его несколько раз и получил несколько вариантов кода, но ни один из них не работал.
Я разобрал каждый вариант по строкам — и вот что увидел. Задача была типовой, но не имела однозначного, идиоматического решения. В обучающей базе явно было что-то похожее — код выглядел реалистично. Однако написан он был так, как будто его писал троечник, который не понимал, что делает, но прилежно списывал у отличников: часть функции у одного, часть у другого.
Помню, в нашем рабочем чате я поделился первыми впечатлениями. Вот дословно, орфография оригинала сохранена:
Ребятушки, я прочитал на обеде, что написал нам ЧатГТП, и я впечатлен. Он не просто сделал все, что я его просил. Он сделал больше, и сделал даже то, о чем я не подумал и чего не учел. И он сделал это лучше, чем это сделал бы я!
Но это я прочитал только первую из нескольких функций.
Проверил остальное. Беру свои слова обратно. ChatGPT — тупое жывотное. Такое чувство, что он просто натырил код с интернета, а потом смешал в кучу. Три раза одно и то же действие повторил, разными словами
Это тоже я. Между двумя этими сообщениями прошло минут двадцать.
Мы скармливали нейросети одно и то же ТЗ дважды или трижды, с разной детализацией, и каждый раз получали примерно одинаковый выход, с небольшими вариациями. Как если бы разных людей попросили сделать одно и то же действие — результат одинаковый, но стиль и почерк разный. Сигмоида, например: один раз через math отдельной функцией, второй раз — numpy прямо в теле.
Проблемы кода нейросети я могу проиллюстрировать на примере функцииfeed_forward, которая рассчитывала значения нейронов при прямом проходе. Вот что выдал ChatGPT:
def feed_forward(inputs, layers, weights):
layers[0] = inputs
for i in range(len(weights)):
weights_i = np.array(weights[i])
layers_i = np.array(layers[i])
dot_product = np.dot(weights_i, layers_i) # ← здесь
layers[i+1] = 1 / (1 + np.exp(-dot_product))
return layers, weights
Выглядит правдоподобно. Но падает.
Дело в том, что матрица весов weights[i] хранится в форме (n_in, n_out) — для каждого нейрона входного слоя список весов к каждому нейрону следующего слоя. Вектор layers[i] имеет размер (n_in,). Операция np.dot(weights_i, layers_i) пытается перемножить (n_in, n_out) на (n_in,) — размерности не совпадают. Нужно транспонировать матрицу: weights_i.T даст форму (n_out, n_in), и тогда (n_out, n_in) × (n_in,) = (n_out,) — всё сходится.
Правка — одна точка и одна буква:
def feed_forward(inputs, layers, weights):
layers[0] = inputs
for i in range(len(weights)):
weights_i = np.array(weights[i])
layers_i = np.array(layers[i])
dot_product = np.dot(weights_i.T, layers_i) # транспонируем матрицу весов
layers[i+1] = 1 / (1 + np.exp(-dot_product))
return layers, weights
После этой и нескольких других подобных правок нейронка, наконец, заработала.
«Upd: я осознал, чутка поправил код ЧатГТП, и теперь оно работает. И мало того что работает, так ещё правильно работает»
Наша работа была завершена, о чем я и оповестил всех в чате:
«ОФИЦИАЛЬНО УВЕДОМЛЯЮ ВСЕХ!!! Работа над кодом нейросети завершена. На данном этапе мы можем: создавать полносвязанные нейросети с произвольным количеством слоев и нейронов, а также обучать их. [...] Спасибо ЧатГПТ за проделанную работу (хотя он троешник и приходилось его ВСЁ ВРЕМЯ поправлять). Спасибо Вам, что втянули меня в этот движ! Слава Человечеству!»
Нейросеть я назвал Nier: Automata Ver1.1a — в тот момент я как раз увлеченно смотрел только что вышедший одноименный аниме-сериал. События разворачиваются в далеком 11945 году. Андроиды воюют с машинными формами жизни — никто из них уже не помнит, зачем. Человечество, развязавшее эту войну, вымерло многие тысячелетия назад. "Слава Человечеству!" - молитвенное восклицание андроидов, рефреном проходящее через весь сериал. Абсурдная акламация, подчеркивающая бессмысленность происходящих военных действий.
Но эта потрясающая история — не только про андроидов. Сериал полон глубоких вопросов: о происхождении культуры, сознания, религии, цивилизации. Вопросов, которые не отпускают многие поколения авторов добротной научной фантастики.
Я считаю выход этого сериала, совпавший с началом волны хайпа вокруг нейросетей, знаковым событием и невольно провожу парралели. Нейросети эволюционировали в новый вид и продолжают развиваться: на смену агентам приходят агентные рои, и не за горами возможно появление AGI. На этом фоне галлюцинации тех первых версий нейросетей выглядят сейчас наивно, смешно и мило.
С каждым днем мы приближаемся к технологической сингулярности. Уже пройден тест Тьюринга — дать ответ, где проходит граница между человеческим сознанием и машинными формами жизни, становится все сложнее. Что такое сознание? что такое душа? что отличает живое и неживое? Может ли машина чувствовать, любить, страдать, сходить с ума — или всё это лишь точная имитация, зеркало, в котором мы видим только самих себя? Вопросы, поставленные в том сериале, появляются теперь в новостных лентах — и с каждым днем становятся все актуальнее.
Я не знаю, останутся ли жить наши копии в андроидах, когда человечество вымрет — но моя нейросеть, написанная нейросетью, по совету нейросети — точно останется жить на GitHub. Специально для этой статьи я сдул с неё пыль (2.5 года прошло!), оформил как библиотеку python3 и дописал примеры, взяв хрестоматийные ml-датасеты — распознавание цветков Ириса, перевод градусов из Цельсия в Фаренгейта, определение победителя в крестики-нолики.
P.S. К сожалению, мы так и не стали сказочно богатыми биржевыми трейдерами. Обученная на датасете биржевых индексов моя нейросеть может предсказывать котировки цен. Это математика — не магия. А вот предсказать реальные котировки цен на бирже — она, к сожалению, не может.
Слава Человечеству!
Подписывайтесь на мой технико-философский канал в Telegram.
Автор: A1exMa
