Живая клетка — прекрасный пример нелинейной системы. Она выполняет все свои функции благодаря сложной сети химических реакций, превращающих сырье в конечные продукты. Как мы видели в предыдущей главе, структуру этой сети можно открыть символистскими методами, например обратной дедукцией, но для построения полной модели работы клетки нужен количественный подход: надо узнать параметры, которые связывают уровень экспрессии различных генов, соотносят переменные окружающей среды с внутренними переменными и так далее. Это непросто, потому что между этими величинами нет простой линейной зависимости. Свою стабильность клетка скорее поддерживает благодаря пересекающимся петлям обратной связи, и ее поведение очень сложно. Для решения этой проблемы хорошо подходит метод обратного распространения ошибки, который способен эффективно учиться нелинейным функциям. Если бы у нас в руках была полная карта метаболических цепочек и мы располагали достаточными данными наблюдений за всеми соответствующими переменными, обратное распространение теоретически могло бы получить подробную модель клетки и многослойный перцептрон предсказывал бы любую переменную как функцию ее непосредственных причин.
Однако в обозримом будущем у нас будет только частичное понимание клеточного метаболизма и мы сможем наблюдать лишь долю нужных параметров. Для получения полезных моделей в условиях недостатка информации и неизбежных противоречий нужны байесовские методы, в которые мы погрузимся в главе 6. То же касается прогнозов для конкретного пациента, если модель уже имеется: байесовский вывод извлечет максимум из неизбежно неполной и зашумленной картины. Хорошо то, что для лечения рака не обязательно понимать функционирование опухолевых клеток полностью и во всех подробностях: достаточно просто обезвредить их, не повреждая нормальные клетки. В главе 6 мы увидим, как правильно сориентировать обучение, обходя то, чего мы не знаем и не обязательно должны знать.
На нынешнем этапе нам известно, что на основе данных и предыдущего знания можно с помощью обратной дедукции сделать вывод о структуре клеточных сетей, однако количество способов его применения порождает комбинаторный взрыв, так что требуется какая-то стратегия. Поскольку метаболические сети были разработаны эволюцией, возможно, симулирование эволюции в обучающихся алгоритмах как раз подойдет. В следующей главе мы посмотрим, как это сделать.
В глубинах мозга
Когда метод обратного распространения ошибки «пошел в народ», коннекционисты рисовали в воображении быстрое обучение все больших и больших сетей до тех пор, пока, если позволит «железо», они не сравняются с искусственным мозгом. Оказалось, все не так. Обучение сетей с одним скрытым слоем проходило хорошо, но после этого все резко усложнялось. Сети с несколькими слоями работали только в случае, если их тщательно разрабатывали под конкретное применение (скажем, распознавание символов), а за пределами этих рамок метод обратного распространения терпел неудачу. По мере добавления слоев сигнал ошибки расходился все больше и больше, как река, ветвящаяся на мелкие протоки вплоть до отдельных незаметных капелек. Обучение с десятками и сотнями скрытых слоев, как в мозге, оставалось отдаленной мечтой, и к середине 1990-х восторги по поводу многослойных перцептронов поутихли. Стойкое ядро коннекционистов не сдавалось, но в целом внимание переместилось в другие области машинного обучения (мы увидим их в главах 6 и 7).
Однако сегодня коннекционизм возрождается. Мы обучаем более глубокие сети, чем когда бы то ни было, и они задают новые стандарты в зрении, распознавании речи, разработке лекарственных средств и других сферах. Новая область — глубокое обучение — появилась даже на первой странице New York Times, но, если заглянуть под капот, мы с удивлением увидим, что там гудит все тот же старый добрый двигатель — метод обратного распространения ошибки. Что изменилось? В общем-то, ничего нового, скажут критики: просто компьютеры сделались быстрее, а данных cтало больше. На это Хинтон и другие ответят: «Вот именно! Мы были совершенно правы!»
По правде говоря, коннекционисты добились больших успехов. Одним из героев последнего взлета на американских горках коннекционизма стало непритязательное маленькое устройство под названием автокодировщик — многослойный перцептрон, который на выходе выдает то же, что получил на входе. Он получает изображение вашей бабушки и выдает ту же самую картинку. На первый взгляд это может показаться дурацкой затеей: где вообще можно применить эту штуку? Но вся суть в том, чтобы скрытый слой был намного меньше, чем входной и выходной, то есть чтобы сеть не могла просто научиться копировать вход в скрытый слой, а скрытый слой — в выходной, потому что в таком случае устройство вообще никуда не годится. Однако если скрытый слой маленький, происходит интересная вещь: сеть вынуждена кодировать вход всего несколькими битами, чтобы представить его в скрытом слое, а затем эти биты декодируются обратно до полного размера. Система может, например, научиться кодировать состоящее из миллиона пикселей изображение бабушки всего лишь семью буквами — словом «бабушка» — или каким-то коротким кодом собственного изобретения и одновременно научиться раскодировать это слово в картинку милой вашему сердцу пенсионерки. Таким образом, автокодировщик похож на инструмент для сжатия файлов, но имеет два преимущества: сам разбирается, как надо сжимать, и, как сети Хопфилда, умеет превращать зашумленное, искаженное изображение в хорошее и чистое.
Автокодировщики были известны еще в 1980-х, но тогда их было очень сложно учить, несмотря на всего один скрытый слой. Разобраться, как упаковать большой объем информации в горсть битов, — чертовски сложная проблема (один код для вашей бабушки, немного другой — для дедушки, еще один — для Дженнифер Энистон[68] и так далее): ландшафт гиперпространства слишком изрезан, чтобы забраться на хороший пик, а скрытые элементы должны узнать, из чего складывается избыток исключающих ИЛИ на входе. Из-за этих проблем автокодировщики тогда по-настоящему не привились. Чтобы преодолеть сложности, потребовалось больше десятилетия. Был придуман следующий трюк: скрытый слой надо сделать больше, чем входной и выходной. Что это даст? На самом деле это только половина решения: вторая часть — заставить все, кроме некоторого количества скрытых единиц, быть выключенными в данный момент. Это все еще не позволяет скрытому слою просто копировать вход и, что самое главное, сильно облегчает обучение. Если мы позволим разным битам представлять разные входы, входы перестанут конкурировать за настройку одних и тех же битов. Кроме того, у сети появится намного больше параметров, поэтому у гиперпространства будет намного больше измерений, а следовательно, и способов выбраться из того, что могло бы стать локальными максимумами. Этот изящный трюк называется разреженным автокодировщиком.