AI может стать поворотным пунктом в методе познания — наравне с изобретением письменности
Некоторое время назад я понял нечто важное касательно AI. До того момента я рассматривал само явление искусственного интеллекта и все его приложения как чисто инструментальные способы выполнения определенных задач. В этом смысле AI для меня не отличался от программирования - просто набор алгоритмов, которые могут принять некоторые данные на вход и отдать на выходе нечто полезное для работы.
Однако, наблюдая за тем, какие изменения AI уже создал в мире всего за последние пять лет и какие новые сдвиги он продолжает порождать, я в конце концов пришел к выводу, что смысл AI не исчерпывается его прикладной пользой. Главное, на что надо было обратить внимание - это как AI соотносится с процессом познания и с наукой. Впрочем, нет ничего удивительного в том, что я, как и многие, игнорировал эту сторону явления AI, потому что наука уже давно, еще с 19 века стала интересовать людей ровно настолько, насколько хорошо она обслуживает индустрию и бытовые потребности. А познание - процесс не бытовой, он занимается изучением вещей независимо от того, как эти вещи могут быть нами использованы, если мы говорим о познании в полном, неограниченном смысле.
Тем не менее, изменения в процессе познания со временем дают о себе знать в жизни каждого человека - например, изобретение и распространение систем письменности в древние времена изменило жизнь людей сильнейшим образом, хотя и сравнительно медленно. Это был огромный сдвиг в возможностях накопления, хранения и передачи информации, знаний. Письменность является эпистемической технологией - то есть меняющей способность людей изучать и исследовать мир. AI также является эпистемической технологией, по значимости сопоставимой с письменностью, и превосходящей даже Интернет. А что касается изменений, происходящих по причине AI, они наступают в сотни или тысячи раз быстрее, чем изменения, связанные с распространением систем письменности. Т.е. есть риск, что настоящее значение многих из них мы будем понимать уже постфактум. Вы можете рассматривать данную статью как попытку придать ясности этой проблеме.
Прежде всего, в чем именно состоит особенность AI для процесса научного познания? В науке существует множество методов, которые человек может использовать как интеллектуальный инструмент для анализа данных о мире и получения знаний. Для каждого из них важна верифицируемость, когда можно независимо проверить верность того или иного полученного этим методом суждения. Впрочем, относительно верифицируемыми можно считать только точные науки, а скажем в истории, лингвистике и социологии, где мерой достоверности того или иного суждения часто служит авторитет приведенных цитат и рецензий, о настоящей верифицируемости говорить не приходится. И тут на научную сцену, где с трудом поддерживается шаткий консенсус мнений, выработанных в ходе традиционных исследований силами человеческого интеллекта, выходит AI.
С одной стороны, верификация суждений, сгенерированных искусственным интеллектом, представляет собой проблему настолько острую, что заставляет людей очень сильно сомневаться в их ценности - так было с первых месяцев появления generative AI. С другой стороны, в основе любой AI модели лежит математический закон, в обобщенном виде приведенный ниже, который является как бы фундаментальным аргументом в пользу того, почему AI все-таки стоит доверять. Он показывает, что нахождение искомого ответа практически на любой вопрос по некоторым вводным данным - проблема, имеющая вполне доступное решение, единственная трудность - необходимый для этого объем данных и вычислительная сложность математического выражения, описывающего градиентный спуск. Однако и это решаемо благодаря производительности современных видеокарт.
Совсем недавно известный в AI-сообществе Андрей Карпати опубликовал microgpt, минимальную реализацию нейросети-трансформера на чистом Python - 200 строк кода без единой зависимости. Согласно его блог-посту, этот небольшой скрипт стал итогом 10-летней работы с целью максимально упростить реализацию нейросети, которая за сложностью продакшен-кода в таких фреймворках, как Pytorch, не дает рассмотреть самую суть алгоритма. Но microgpt дает такую возможность. Для иллюстрации той идеи, о которой идет речь в этой статье, я приведу лишь этот фрагмент, в котором Карпати реализовал Autograd - часть логики, отвечающую за оптимизацию весов нейросети с помощью градиентов функции потерь по каждому из параметров весов.
# Let there be Autograd to recursively apply the chain rule through a computation graph
class Value:
__slots__ = ('data', 'grad', '_children', '_local_grads') # Python optimization for memory usage
def __init__(self, data, children=(), local_grads=()):
self.data = data # scalar value of this node calculated during forward pass
self.grad = 0 # derivative of the loss w.r.t. this node, calculated in backward pass
self._children = children # children of this node in the computation graph
self._local_grads = local_grads # local derivative of this node w.r.t. its children
def __add__(self, other):
other = other if isinstance(other, Value) else Value(other)
return Value(self.data + other.data, (self, other), (1, 1))
def __mul__(self, other):
other = other if isinstance(other, Value) else Value(other)
return Value(self.data * other.data, (self, other), (other.data, self.data))
def __pow__(self, other): return Value(self.data**other, (self,), (other * self.data**(other-1),))
def log(self): return Value(math.log(self.data), (self,), (1/self.data,))
def exp(self): return Value(math.exp(self.data), (self,), (math.exp(self.data),))
def relu(self): return Value(max(0, self.data), (self,), (float(self.data > 0),))
def __neg__(self): return self * -1
def __radd__(self, other): return self + other
def __sub__(self, other): return self + (-other)
def __rsub__(self, other): return other + (-self)
def __rmul__(self, other): return self * other
def __truediv__(self, other): return self * other**-1
def __rtruediv__(self, other): return other * self**-1
def backward(self):
topo = []
visited = set()
def build_topo(v):
if v not in visited:
visited.add(v)
for child in v._children:
build_topo(child)
topo.append(v)
build_topo(self)
self.grad = 1
for v in reversed(topo):
for child, local_grad in zip(v._children, v._local_grads):
child.grad += local_grad * v.grad
Андрей Карпати предупреждает, что эта часть самая математически сложная и предлагает 2.5 часовое, кстати, отличное видео об этом, но если как следует разобраться, становится понятно, как это просто. Нам нужен вычислительный граф, который представляет собой математическое выражение - функцию активации нейрона. Вначале это простейшая линейная функция, Wx + b, W здесь веса, x это инпут нейрона, b - это байас (который для простоты в данном коде отсутствует). Потом мы должны применить non-linearity к этому выражению, например tanh, чтобы прямая стала нелинейной, сжатой между 1 и -1 по оси Y.
Соответственно класс Value, который служит для представления каждого скалярного значения из узлов графа, должен реализовать все возможные математические операции - ребра графа. Но вычислить значение активации - не проблема, главное, что нам нужно - это понять, как любой из параметров W влияет на результат вычисления. И для этого служит градиент функции потерь по этому параметру.
Для начала следует определиться с самой функцией потерь: она должна иметь на выходе такое значение, минимизируя которое, мы улучшаем работу нашего алгоритма. Очень хорошим простейшим примером служит сумма (или среднее) квадрата ошибки:
Loss = sum((Y_predict - Y_ground_truth)**2 for Y_ground_truth, Y_predict in zip(targets, predictions))
Учитывая, что каждое из значений в массивах targets и predictions - экземпляр класса Value, мы понимаем, что при вычислении каждой из операций функции потерь - в данном случае вычитания, возведения в квадрат и суммы - в переменную value.grad сохраняется производная функции потерь по этому value. Производная функции Loss по value, на всякий случай, это отношение изменения Loss к изменению value (точнее, предел этого отношения, когда изменение value стремится к нулю, но сейчас лучше не забивайте себе голову этим). Т.е. на какую бы малую величину мы не изменили value, Loss всегда изменится на другую величину, связанную с первой коэффициентом пропорции, выражаемым через производную Loss по value.
Как видно, вычисление grad для каждого value происходит в два шага. Сначала вычисляются локальные производные по значениям детей каждого из узлов графа, т.е. операндов математического действия, результатом которого этот узел является. Эта задача сводится к применению формулы производной отой или иной функции - например, для сложения производная равна 1 по каждому из слагаемых, для возведения a в степень b - b * a**(b-1). по основанию степени. Затем применяется цепное правило дифференцирования сложной функции, каковой является Loss, через производные простых:
for child, local_grad in zip(v._children, v._local_grads):
child.grad += local_grad * v.grad
Т.е. мы просто умножаем локальные градиенты детей узла на градиент Loss по этому узлу, чтобы получить градиент Loss по каждому из них. Мы знаем grad самого первого узла - он равен 1, так как очевидно, что производная Loss по значению самого Loss - единица, и дальше применяем цепное правило ко всем остальным узлам рекурсивно.
Что мы получили, вычислив градиенты? Мы узнали точную меру того, как любой из параметров вычислительного графа каждого из нейронов сети влияет на ее выходное значение. Именно поэтому мы говорим, что данные параметры служат весами нейросети. Мы установили точную связь между причиной - весом - и следствием, или предсказанием нейросети. Все, что нам теперь нужно, это откалибровать веса так, чтобы функция Loss приблизилась к нулю, насколько это возможно, а predictions, соответственно, к targets. Это лишь дело времени и необходимого количества итераций, изменяющих каждый вес на значение его градиента, умноженное на learning rate. И какую бы задачу мы не моделировали с помощью нейросети, вплоть до предсказания следующего текстового токена в последовательности, у нас есть этот универсальный механизм, основанный на мере причинно-следственных связей.
Значит, база для верифицируемого алгоритма получения знания из набора данных без участия человека у нас есть. Точнее, все сказанное выше означает, что если люди предварительно сделали верные выводы на основе некоторого контекста и обучили нейросеть на этой информации, то она тоже сможет делать выводы из того же контекста, и они при независимой проверке часто оказываются верными. Но это нисколько нас не удивляет и вообще не является поводом для написания этой статьи - если бы все было так просто! На самом деле нейросети и двадцать лет назад могли с похвальной точностью воспроизводить действия, которым их обучили. О том, чтобы AI выполнял полностью самостоятельные манипуляции с вводными данными и приходил к верным выводам, можно говорить лишь теперь. Дело в том, что современные AI системы с существенной долей успеха выполняют действия, которым их никогда не учили.
Приблизительно 60%-90% задач, с которыми сталкивается AI и в особенности LLM cегодня - это задачи instruction-following. Индивидуальные инструкции очень варьируются - каждому пользователю нужно что-то конкретное, его требования содержат уникальный набор важных деталей. Несмотря на то, что для современных моделей обучающим набором служит плюс-минус весь интернет, почти все задачи такого типа будут казаться для AI новыми. Но даже без тюнинга на данном конкретном типе инструкций AI модели с ними справляются - от этого и зависит практическая польза систем наподобие ChatGPT. В основе этого феномена лежит так называемый in-context learning. Это не алгоритм в традиционном понимании, нет кода, который я мог бы вставить в этот текст и сказать - так реализуется ICL. Это поведение, которое проявилось в трансформерах само и о котором мы совершенно не знаем, как именно оно работает. Является ли ICL обучением в традиционном смысле, использует ли он градиентный спуск? Есть работы, например эта, которые убедительно предполагают (но не доказывают), что да, использует, причем GPT делает градиентный спуск сам, прямо внутри активаций. Так это или нет, возвращаясь к проблеме статьи, мы снова сталкиваемся с вопросом, насколько результаты AI являются достоверным знанием. С одной стороны, вроде бы все нейросети базируются на рациональном и понятном градиентном спуске, который объясняет, откуда в них берется решение той или иной интеллектуальной задачи. С другой стороны, на практике модели-трансформеры используют нечто, пока нашему пониманию недоступное. За это последнее обстоятельство мы бы, вероятно, сжигали их на костре, как в старые добрые времена, если бы они 1. были материальными сущностями и 2. не приносили бы столько рыночной ценности.
Экономический потенциал - одна из первых причин активного внедрения AI во все стороны жизни. Это неизбежно создает прецедент влияния AI на нашу систему знаний о мире. Пройдет несколько лет, и мы будем все чаще иметь дело с научными открытиями, к которым "приложил руку" AI. Актуальной повесткой станет смена того, что называется эпистемическим режимом - системы правил и норм, определяющих, что считается достоверным знанием. Эта смена может произойти в одном из двух диаметрально противоположных направлений, и в этом заключается главная мысль данной статьи, которая существенно изменила мое понимание AI как явления в последнее время. Или участие AI в процессе познания будет регулироваться централизованно и подвергнется строгой стандартизации, или AI системы будут действовать и развиваться децентрализованно - по сути, пользователи таких систем будут решать, какие знания, полученные посредством AI, являются полезными в практическом и этическом смысле.
Первый путь - стандартизация - имел бы смысл, если бы речь шла про обычную технологию. Все, что масштабируется, должно быть стандартизовано и подчинено центральному управлению. Но если мы примем во внимание, что AI является эпистемической технологией и его первая и главная роль - помогать процессу познания, к нему нельзя относиться как к обычной технологии и стандартизировать без вреда для человеческих знаний, особенно будущих. Самые очевидные последствия - стагнация в изучении и невозможность легко использовать и распространять новые концепции. К сожалению, я вижу этот риск сильно недооцененным в данный момент, и даже многие разработчики открытого AI, пригодного по своей природе для осуществления децентрализованного сценария, не понимают, что может зависеть от результатов их работы.
В конечном итоге централизованная стандартизация AI ведет к замещению им людей на рынке труда, так как нацелена на создание систем, максимально адаптированных для предсказуемого использования на крупном производстве, в технологических корпорациях, в административных и образовательных учреждениях - и для делегирования задач сотрудников этих организаций AI-агентам. Можно с большой долей уверенности предсказать, что разработчики закрытых AI-моделей, такие как OpenAI, Anthropic, Google будут двигаться главным образом по этому пути.
С другой стороны, со времен первой модели Llama конкуренцию закрытым LLM составляли модели с открытыми весами. Если первые осуществляют стратегию замещения, то для вторых характерна "склонность" к кооперации. Я хочу особо подчеркнуть, что открытые модели - неподходящий кандидат для замещения ими работников бизнеса. Такое замещение осуществимо в корпоративной среде, и во много раз труднее на малых и средних предприятиях, а корпорациям нужны предсказуемые, одинаковые, но очень хорошо масштабируемые результаты - для этого гораздо лучше подходят провайдеры OpenAI-класса. Открытые модели предполагают кооперацию человек - AI. Среди открытых моделей существует большое разнообразие, и у людей появляется возможность выбирать лучше всего соответствующие специфике их работы. Очевидно, что результаты использования разных AI-моделей разными людьми могут существенно различаться. В такой ситуации открывается широкое поле для исследования, и важно создать среду обмена знаниями между пользователями открытого AI, чтобы стимулировать их продуктивность.
Видятся следующие практические действия, важные для реализации децентрализованного развития AI, опираясь на открытые модели и кооперативный сценарий пользовательского опыта. Не следует заниматься искусственным выравниванием поведения нейросетей (AI alignment) - надо исходить из того, что при правильно выстроенной кооперации пользователь сам настроит поведение AI для своих целей. Надо сосредоточиться на том, чтобы создать для этого инструменты. Управление контекстом модели стандартизировать можно и нужно, и один из лучших способов сделать это на сегодняшний день - применять и развивать протокол MCP. Это облегчит для пользователей управление AI-моделью и позволит им обмениваться данными и результатами AI-инференса между собой посредством общего протокола.
Еще одна область, где требуется выработка общих эффективных практик, это AI-инфраструктура и MLOps. Необходимо дать инструменты для простого развертывания, инференса и обучения моделей, при этом сохраняя открытость весов и данных для пользователя. Успешное решение перечисленных задач уже обеспечит хорошую основу для децентрализованного сценария развития AI.
Меня очень интересует ваше понимание вопросов, о которых идет речь в этой статье, поэтому я оставляю здесь ссылку на телеграм-сообщество для ваших комментариев: https://t.me/ruslandevlabs/123


