Лекция CS50 простым языком объясняет, что такое современный ИИ и из каких идей он вырос.
Через живые примеры видео показывает, что ИИ сегодня это уже не магия, а набор вполне понятных принципов: обучение на данных, поиск закономерностей, система поощрений, внимание к контексту и вероятностное предсказание следующего шага.
Это хорошее вводное объяснение для тех, кто хочет понять, как работают генеративные модели, почему они так полезны, откуда берутся их ошибки и почему за ними будущее программирования.
Источник на английском: https://youtu.be/-9bo8HlSxwQ
Я веду канал "AI из первых уст", потому что хочу сам слушать первоисточники по-русски — людей, которые сейчас и есть ИИ-индустрия: Альтман, Цукерберг, Харари, Маск. Поэтому перевожу и выкладываю сюда, чтобы и вы могли слушать их в наушниках без английского и без искажений. Буду рад, если подпишитесь на канал.
Мой телеграм канал: https://t.me/egoshin_kedprof
Таймкоды:
00:00:00 — Введение
00:02:13 — Генеративный искусственный интеллект
00:07:13 — Промпт-инжиниринг
00:08:47 — CS50.ai
00:10:22 — Copilot
00:16:46 — Искусственный интеллект
00:20:54 — Деревья решений
00:23:58 — Minimax
00:29:02 — Машинное обучение
00:37:28 — Глубокое обучение
00:42:57 — Большие языковые модели
00:46:06 — Галлюцинации ИИ
Не забудьте подписаться на канал и поставить лайк, ну или дизлайк — главное внимание :)
Оглавление (12 сегментов)
Введение
Итак, это CS50, и это наша лекция по искусственному интеллекту или и, в частности, для всех тех членов семьи, которые сегодня впервые находятся здесь в аудитории вместе с нами. Более того, для тех студентов среди нас давайте, возможно, поапплодируем всем членам семьи, которые пришли сегодня, чтобы поддержать вас. Очень приятно видеть всех. И как студенты CS50 уже знают, в кругах программистов существует такая традиция: держать на столе резиновую уточку. И действительно, несколько недель назад мы раздали такую всем студентам CS50. И идея в том, чтобы у вас был кто-то или что-то, с кем можно поговорить при наличии бага, ошибки в коде или путанице при решении какой-то задачи. И суть в том, что если рядом нет друга, члена семьи или ассистента, у которого можно спросить, вы буквально проговариваете свою проблему, свой вопрос этому неодушевлённому предмету на вашем столе. И в процессе такого проговаривания своей путаницы довольно часто над головой загорается та самая лампочка. И вуаля, проблема решена. Теперь, как студенты CS50 тоже знают, за последние несколько лет мы как бы виртуализировали эту резиновую уточку и совсем недавно в виде этого парня здесь. Так что в среде программирования студентов в CS50 в инструменте под названием Visual Studio Code по адресу CS50. def у них всегда доступна виртуальная резиновая уточка. И в самой первой версии этой уточки это было просто чаткно, которое выглядело вот так. Если у студентов возникал вопрос, они могли просто написать в чат что-то вроде: "Я надеюсь, ты поможешь мне? " не решить эту проблему. И в течение нескольких лет всё, что делала уточка CS50, это отвечало одним, двумя или тремя кря. У нас есть неофициальные свидетельства того, что одного этого было достаточно, чтобы студенты находили ответы, потому что именно в процессе набора своего вопроса ты понимаешь: "О, я делаю какую-то глупость". И разбираешься с этим сам. Но, конечно, теперь, когда мы живём в эпоху Ча GPT, Клод, Gemini и всех этих других и инструментов, неудивительно, что в 23рем году эта же уточка начала отвечать студентам на английском языке. И теперь это тот инструмент, который у них есть. По сути, менее полезная версия чат GPT, которая не просто сразу выдаёт ответ, а пытается направлять их к решениям, как это сделал бы хороший преподаватель или репетитор. И сегодняшняя лекция как раз об этом и об основных строительных блоках, которые
Генеративный искусственный интеллект
делают возможно эту резиновую уточку и вообще весь тот и, с которым мы всё чаще сталкиваемся, а именно генеративный искусственный интеллект, использование этой технологии для генерации чего-либо: изображений, звуков, видео или текста. И на самом деле, чтобы вовлечь всех с самого начала, если у вас под рукой есть телефон, вы можете отсканировать этот QR-код. Здесь он приведёт вас на страницу опроса, где вы сможете отправлять свои ответы. Рецептор CS50 Кеellли любезно присоединится ко мне здесь на сцене, чтобы помочь управлять клавиатурой. И сейчас мы сыграем в небольшую игру и посмотрим, насколько хорошо мы, люди сейчас умеем отличать Ииальности. И мы возьмём некоторые данные из The New York Times, которые пару лет назад опубликовали примеры Ии, и посмотрим, насколько продвинулась эта технология. Итак, здесь у нас на экране два изображения. Через мгновение вас спросят на вашем телефоне, если вам удалось отсканировать код. Какое из них и: левое или правое? Надеюсь, на вашем телефоне, если вы проведёте к следующему экрану, мы активируем опрос. Через мгновение вы должны увидеть приглашение. выбрать левое или правое, не стесняясь поднять руку, если вы этого не видите. Похоже, ответы поступают. И, рискуя заспойлерить, похоже, что более 70% из вас считают, что правильный ответ справа. И возвращаясь к двум фотографиям, это действительно изображение справа. Возможно, оно выглядело слишком идеальным или, может быть, слишком нереальным. Давайте посмотрим ещё пару примеров. Тот же QR-код сканировать заново не нужно. И давайте сейчас выведем следующие два примера. Две фотографии. Тот же вопрос. Какая из них и левая или правая? Я хочу взглянуть на диаграмму и посмотреть, как поступают ответы. В этом случае результаты чуть ближе. Но большинство из вас считают, что правильный ответ левая. Хотя 5% из вас честно признаются, что не уверены. Но, Кели, если вернуться к фотографиям, на этот раз правильный ответ был на самом деле с подвохом. Обе были на самом деле сгенерированы. И, что, возможно, говорит о том, насколько хорошей уже становится эта технология. Ни одно из этих лиц не существует в реальном мире. Они были синтезированы на основе большого объёма обучающих данных. Так что это две фотографии, которые выглядят как люди, но на самом деле не существуют. На этот раз сосредоточимся на тексте, который, конечно, лежит в основе нашей уточки. Написал ли это четвероклассник или новый чатбот? Вот два финальных примера. Тот же код, что и раньше. Так что пересканировать не нужно. Сочинение один. Я люблю брать вкусный сэндвич и холодный сок в пакетике на обед. Иногда я даже кладу вкусный фрукт или пакетик хрустящих чипсов. Пока мы едим, мы болтаем, смеёмся и делимся тем, как прошёл день. Точка, точка. Сочинение два. Моя мама кладёт мне сэндвич, напиток, фрукты, сладкое. Когда я прихожу в столовую, я нахожу пустой стол и сажусь там и ем свой обед. Мои друзья приходят и садятся со мной. Точка, точка. Теперь вопрос, что из этого и один или два? сочинение один или два. Полоски на графике буквально борются друг с другом. Похоже, что большинство из вас говорят сочинение один. Давайте вернёмся к тексту. И кто-нибудь из тех, кто выбрал сочинение один? Почему? О'кей. То есть сочинение два больше похоже на то, как вы бы написали. В каком ты классе? Пятый класс. Так это новый пятиклассник или нет? Ответ здесь, на самом деле, в том, что сочинение один - это и, потому что сочинение два больше похоже на то, как писал бы ученик четвёртого или, если позволите, пятого класса. Я осмелюсь сказать, что здесь есть некоторые характерные признаки. Не уверен, что типичный четвероклассник использовал бы выражение делиться тем, как прошёл день в такой форме. Но так или иначе, в будущие годы в эту игру мы играть не сможем, потому что будет просто слишком сложно отличить то, что сгенерировано и от того, что нет. Одна из наших целей на сегодня, на самом деле, дать вам понимание не только того, как работают такие технологии, как эта уточка и те игры с изображениями и текстом, в которые мы здесь играли, но и то, каковы базовые принципы искусственного интеллекта, которые, честно говоря, существуют и развиваются уже десятилетиями и которые в последние годы действительно вышли на первый план благодаря прогрессу в исследованиях, благодаря всё большему облачному вычислению, благодаря всё большему объёму памяти, дискового пространства и информации в целом, которыми мы располагаем и которые могут быть использованы для обуче. всех этих технологий. Так что эта уточка построена на довольно сложной архитектуре, которая выглядит примерно так. Вот студент, использующий один из инструментов CS50, вот сайт, с которым студенты CS50 знакомы под названием cs50. ai, где мы, сотрудники, написали много кода, который фактически общается с так называемыми API интерфейсами прикладного программирования, сторонними сервисами от таких компаний, как Microsoft и Open AI, которые проделали основную работу по разработке этих моделей, а также с некоторым локальным соусом, который мы CS50 добавляем смесь, чтобы сделать
Промпт-инжиниринг
ответы уточки специфичными именно для CS50. По сути, мы занимались промт инженерингом, который к лучшему или к худшему начал повсеместно появляться в профилях LinkedIn. И промtнриing - это, по большому счёту, не столько форма инженерии, сколько умение задавать хорошие вопросы и быть подробным в своём вопросе, давая контекст, чтобы с высокой вероятностью получить именно тот ответ, который вы хотите. И в этом мире промтенжеринга есть два термина, о которых стоит знать. CS50. Мы использовали оба из них, чтобы реализовать эту уточку. Мы, например, написали то, что называется системный промт. Это инструкции, написанные нами людьми часто на английском, которые как бы подталкивают базовую и технологию к определённой личности или конкретной области экспертизы. Например, мы CS50 написали системный промпт, который по сути выглядит примерно так. В реальности сейчас он состоит из многих строк, но суть в нём вот такая. Ты дружелюбный и поддерживающий ассистент преподавателя для CS50. Ты также резиновая уточка, и этого, как оказывается, достаточно, чтобы превратить е в резиновую уточку. Отвечай на вопросы студентов только оси50 в области компьютерных наук. Не отвечай на вопросы на несвязанные темы. Не давай полные ответы на домашние задания, так как это нарушает академическую честность. Ответь на этот вопрос двоеточие. И после этого вступления системного промта мы, по сути, просто копируем и вставляем любой вопрос, который ввёл студент, иначе известный как промт пользователя. И именно поэтому в нашем случае уточка ведёт себя как уточка, а не как кот или собака или доктор наук, а скорее как нечто настроенное под конкретные педагогические цели. И на самом деле, те из вас, кто является студентами CS50
CS50.ai
возможно, помнят, как несколько недель назад на нулевой неделе, когда мы впервые представляли курс класс, у нас был код, который мы написали в тот день и который в итоге выглядел примерно так. И я кратко пройду по нему построчно. Но теперь, после того, как вы изучили немного Python в CS50, этот код, который я написал на первой лекции, сейчас, возможно, будет иметь чуть больше смысла. В той первой лекции мы импортировали собственную библиотеку Open AI, код, который написала сторонняя компания, чтобы дать нам возможность писать код поверх решений. Мы создали переменную с именем Client на нулевой неделе, и это дало нам доступ к клиенту Open AI, то есть к программному обеспечению, которое они написали для нас. Затем на нулевой неделе мы определили пользовательский промт, который поступал от пользователя с помощью функции input. А затем мы определили системный промпт в тот день, где я сказал: "Ограничь свой ответ одним предложением. Притворись, что ты точка, точка код". Кажется, это была персона дня. И затем мы использовали ещё немного более арканный код здесь. Но по сути мы создали переменную с именем Respons, которая должна была представлять ответ от сервера Openii. Мы использовали client. create, create, что является функцией или методом, который Openi предоставляет нам и который позволяет передать три аргумента. Ввод от пользователя пользовательский промт, инструкция от нас, то есть системный промпт, и затем конкретную модель или версию И, которую мы хотели бы использовать. И последнее, что мы сделали в тот день - это вывели response. И вот так мы могли отвечать на вопросы вроде, что такое CS50 и тому подобное. Так что мы всё это уже видели раньше, но в ту неделю мы не обсуждали, как именно это работает и что ещё мы на самом деле можем сделать с этим. Я подумал, что
Copilot
сегодня мы снимем ещё один слой, к которому мы до сих пор не допускали в рамках курса. И по сути вы по-прежнему не можете использовать эту возможность до самого конца курса CS50, когда дойдёте до финальных проектов. И тогда вам будет разрешено и даже рекомендовано использовать VS-код. Для тех, кто не знаком, это среда программирования, которую мы используем здесь со студентами. И дайте мне открыть код, который был задан студентам пару недель назад, а именно проверку орфографии, которую им нужно было реализовать на C. Итак, я заранее подготовил папку под названием SpellerР. И внутри этой папки у меня был файл, который был у всех студентов на той неделе под названием diary. И в этом файле, который не будет знаком многим из вас, если вы не проходили недели с нуля по седьмую до этого момента, у нас были некоторые заглушки для студентов. Короче говоря, студентам нужно было ответить на несколько вопросов, то есть написать код, чтобы сделать это, сделать это и сделать это. И ещё одно. Было четыре функции или пустых места, которые студентам нужно было заполнить кодом. У большинства студентов это заняло 5 часов, 10 часов, 15 часов, что-то в этом очень широком диапазоне. Позвольте мне сейчас показать вам, как с использованием и вы, будущие программисты, сможете начинать писать код гораздо быстрее, не просто выбирая другой язык, а используя эти и технологии за пределами самой уточки. Итак, что я сделал здесь в первой части VS Code? Я включил функцию, которую CS50 отключает для всех студентов с самого начала курса под названием CILT. Это очень похоже на духу на продукта от Google Antropic, но это продукт от Microsoft и в свою очередь GitHub. И он тоже даёт нам здесь окно чата. И это лишь одна из его возможностей. Например, если бы я хотел начать и реализовать функцию чек, я мог бы просто попросить его сделать это. Реализуй функцию чек и давай использовать хэштаблицу на C. Я нажму Enter. Теперь он начнёт работать в качестве ориентира, то есть контекста. Он использует тот самый файл, который я открыл, а именно dictionary. c. Здесь кайло в целом, как и многие и инструменты, знаком с CS50, потому что курс уже много лет свободно доступен. То, что вы видите здесь, по сути, это как будто он думает, хотя это немного преувеличение. Он пытается найти шаблоны в том, в чём состоит задача, которую я хочу решить среди всех своих обучающих данных, которые он видел раньше, и придумать довольно хороший ответ. Так что для сегодняшних целей я махну рукой на пояснение в стиле чат GPT о том, что делать, которое появилось справа. Но самое интересное здесь слева. Если я сейчас прокручу вниз, то подсвеченное зелёным - это весь предложенный код для реализации этой функции чек. Возможно, это не тот способ, каким вы реализовали её сами, но я осмелюсь сказать, что здесь есть намёки ровно на то, что вы, вероятно, делали при реализации хэш-таблицы. И на самом деле я могу остановить весь этот код, если мне нравится, как он выглядит. Допустим, всё это здесь корректно. Возможно, теперь я захочу реализовать функцию load. Так что давайте теперь реализуй функцию load. Enter. Вот так просто. А какие данные используются? Ну, несколько разных вещей. Он говорит, что использует один источник, так что он действительно использует этот один файл. Но есть также так называемые комментарии в коде, с которыми все студенты теперь знакомы. Эти команды со слэшами в сером цвете, которые дают подсказки на английском о том, что должна делать эта функция. Есть неявная информация о том, какими должны быть входные данные этих функций, иначе называемые аргументами и какими должны быть входные данные. Так что у лежащего в основе и, который здесь называется копайт, есть довольно много подсказок. Этого контекста достаточно, чтобы понять, как заполнить эти пустые места. И поэтому здесь тоже, если я сейчас прокручу вниз, мы увидим подсвеченный зелёным предложенный код, с помощью которого он тоже может решить ту самую задачу, функцию load. Я осмелюсь сказать, что я говорил об этом гораздо меньше минут, чем студенты CS50 потратили на то, чтобы написать решение для этой задачи с нуля. Так что я нажму п. Я предположу, что это правильно, но это на самом деле довольно большое допущение. И те из вас, кто задаётся вопросом, зачем мы вообще учили всё это, если можно просто попросить чатбот? Ну, многое можно сказать о мышечной памяти, которую, я надеюсь, вы чувствовали, что развивали в течение последних нескольких недель. Реальность такова, что если у вас нет понимания того, на что вы смотрите, у вас нет никакого шанса отладить здесь проблему, внести небольшие изменения или что-то подобное. И при этом то, что невероятно захватывает, это то, что такой функционал усиливает ваши возможности как программиста практически за одну ночь. Как только у вас появляется этот словарь, э, мышечная память для самостоятельной работы и может просто взять всё остальное на себя и убрать всю рутину, позволив вам сосредоточиться у доски с другими людьми на более общих задачах, которые вы хотите решить, и оставить решение этих проблем на и забавным упражнением также может быть в конце семестра попробовать решить любое количество заданий курса. Например, вот что. В моём окне терминала здесь я вернусь в основной каталог. Я создам пустой файл под названием mario. В котором ничего нет, и я напишу в окне чата здесь: "Пожалуйста, реализуй программу на C, которая печатает пирамиду из кирпичей, выровненную по левому краю, используя символы решётки для кирпичей, и использую библиотеку CS50, чтобы запросить у пользователя неотрицательную высоту в виде целого числа". Точка. Осмелюсь сказать, что это, по сути, английское описание того, что в этом году в CS50 было заданием номер один. Реализовать программу под названием Mario. Это тоже делает своё дело. Он использует один источник, он работает. Он знает в качестве подсказки, что этот файл называется mario. И за время обучения он видел огромное количество таких файлов. Здесь есть английское объяснение того, что мне следует сделать. И студенты CS50 в зале, вероятно, узнают здесь базовую структуру. использование цикла Duайл для запроса у пользователя высоты, использование библиотеки CS50, которая была подключена, печать пирамиды, выполненной по левому краю, с помощью какого-то цикла. И бум, мы закончили. И это довольно небольшие задачи. Как вы увидите к концу семестра с вашим финальным проектом, который является довольно открытой возможностью применить ваши новые знания и навыки программирования к интересной задаче? Это позволит вам реализовывать гораздо более масштабные проекты. Конечно, даже всего за те несколько недель, которые у нас есть, благодаря такому усилению ваших собственных возможностей. Так что
Искусственный интеллект
с этим обещанием давайте поговорим о том, как вообще, чёрт возьми, всё это на самом деле работает. Я только что сгенерировал огромное количество всего. И именно так мы начали эту историю с генерации тех изображений и тех двух эсс от детей. Но что такое генеративный искусственный интеллект или по сути что такое самые? И вот некоторые из базовых строительных блоков, которые никуда не денутся в ближайшее время и которые, по сути, привели нас поэтапно к тем возможностям, которые вы только что увидели. Мы сейчас как бы воспринимаем как должное, что в наших почтовых ящиках большая часть спама просто попадает в отдельную папку. Но нет какого-то человека, который вручную помечает письма по мере их поступления, решая, спам это или нет. Они определяют это с помощью кода, а в наши дни с помощью и. Это выглядит как спам. И поэтому я помещаю это в папку спама, что, вероятно, правильно в 99% случаев. Но, конечно, существует потенциальный процент ошибок. Другие приложения могут включать распознавание рукописного текста. Разумеется, Microsoft и Google не знают почерк каждого из нас в этой аудитории, но система обучена на достаточном количестве почерков других людей, так что, скорее всего, ваш почерк и мой похожи на чей-то ещё. И поэтому с очень высокой вероятностью они могут распознать что-то вроде Hello World здесь, как именно тот же самый цифровой текст. Все мы сейчас пользуемся стриминговыми сервисами Netflix и тому подобным. Они становятся чертовски хороши в том, чтобы понимать, если я посмотрел X, мне, возможно, понравится Y. Почему? Ну, потому что из-за других вещей, которые я смотрел раньше, и, возможно, лайкал или дизлайкал, возможно, из-за других вещей, которые смотрели люди, которым нравятся похожие на мои фильмы или сериалы. Это тоже и там нет конструкции if, elsif, else. Для каждого фильма или сериала в их базе данных система гораздо более органично и динамически определяет, что вам и мне может понравиться. И затем все эти голосовые помощники сегодня, они тоже не распознают ваш голос и не обязательно знают, какие вопросы вы собираетесь им задать. Там нет огромной цепочки ifl со всеми возможными вопросами в мире. Это тоже, конечно, динамически генерируется, но это я уже немного забегаю вперёд. Давайте отмотаем назад. И некоторые родители в аудитории, возможно, помнят эту игру, одну из первых аркадных игр в мире. Это была чёрно-белая игра, в которой есть два игрока: ракетка слева, ракетка справа. И затем, с помощью какого-то джойстика или трекбола они могут двигать свои ракетки вверх и вниз, а цель - отбивать мяч туда-сюда и в идеале ловить его каждый раз, иначе вы теряете очко. Это просто анимированный гиф, так что здесь особо нечего смотреть. Ничего интересного не произойдёт, но это хороший пример игры, которая хорошо поддаётся решению с помощью кода. И действительно, уже много лет в нашей речи принято говорить, что мы играем не просто против компьютера, а против CPU, центрального процессора или, по сути, против ИИ. И при этом И вовсе не обязан быть таким же сложным, как те инструменты, которые мы видим сейчас. Например, вот приёмник Пон под названием Breakу. Похож по духу, но здесь только одна ракетка и один мяч. И цель - отбивать мяч от этих цветных кирпичей, и вы получаете всё больше очков в зависимости от того, насколько высоко вы можете отправить мяч. Все мы, даже если вы никогда не играли в эту аутскульную игру, вероятно, инстинктивно понимаем, куда нам следует двигать ракетку. Мы принимаем решение, которое довольно инстинктивно. Оно в нас не закреплено, но мы могли бы, по сути, убрать из игры всё удовольствие и начать количественно описывать это или формулировать чуть более алгоритмически, шаг за шагом. Подпишись прямо сейчас на мой Telegram-канал по ссылке в описании. Я подготовил для тебя топ-три материала, которые, на мой взгляд, должен знать каждый. Первое, карта сотни топовых AI стартапов - это будущее на одной картинке. Второе- прогноз от инсайдера из Openi, который ещё до появления чат GPT предсказал всё, что сейчас происходит с неронками. И вот в этом году он выпустил новый прогноз до двадцать седьмого года. И третье, самое мощное - это мой разбор эссе основателя компании Anроopic, который по сути второй человек в мире искусственного интеллекта. Он по полочкам разложил, что будет происходить в мире ближайшие 5 лет. И главное, каким будет универсальный AI, которого все так боятся или ждут. Переходи по ссылке в
Деревья решений
описании. — На самом деле, деревья решений - это концепция из экономики, стратегического мышления, а также из информатики. Это один из способов решить такую задачу так, чтобы вы всегда хорошо играли в эту игру, если просто будете следовать алгоритму. Например, как мы могли бы реализовать код или процесс принятия решений для такой игры, как Breйкаут? Ну, сначала вы спрашиваете себя, находится ли мяч левее ракетки. Если да, то вы знаете, что делать. Просто двигайте ракетку влево. Но что, если ответ нет? Тогда вы, вероятно, не будете просто вслепую двигать ракетку вправо. Какой следующий вопрос? Находитесь ли вы прямо под мячом? Если мяч летит прямо к вам, вы не хотите наивно двигаться вправо и тем самым рисковать промахнуться. Поэтому есть ещё один вопрос: находится ли мяч правее ракетки? Это вопрос с ответом да или нет. Если да, хорошо, тогда двигайте ракетку вправо, но если нет, не двигайтесь. Итак, это довольно детерминированный процесс, и мы можем отобразить это в коде, используя псевдокод. Мы можем задать: "Пока игра продолжается, если мяч левее ракетки, то двигай ракетку влево". Иначе, если мяч правее ракетки, извините за опечатку, двигайте ракетку вправо. Иначе просто не двигай ракетку. И такие деревья решений, как мы их нарисовали, идеально отображаются в код или, в данном случае, в псевдокод. То есть именно так люди, которые реализовали игру Breakу или Пон и программировали компьютерного игрока, наверняка и писали этот код. Но как насчёт такой игры, как крестики-нолики? Здесь у нас доска крестиков- ноликов с двумя ноликами и двумя крестиками. Для тех, кто не знаком, эта игра заключается в том, что два человека по очереди ставят крестик и нолик. И цель получить три нолика подряд или три крестика подряд по вертикали, по горизонтали или по диагонали. Итак, игра здесь в самом разгаре. Давайте подумаем, как можно было бы поиграть в крестики нолики, как компьютер. Как это мог бы делать и вы могли бы сначала спросить себя, могу ли я получить три в ряд на этом ходу? Если да, то вы просто делаете ход в нужную клетку, чтобы получить три вряд. Если же нет, какой следующий вопрос? Может ли мой соперник получить три вряд на своём следующем ходу? Потому что если да, то вам, по крайней мере, стоит заблокировать этот ход. Но эта игра при всей своей относительной простоте становится немного сложнее, когда не очевидно, куда именно стоит ходить. Все мы выросли, играя в эту игру. Вероятно, использовали какие-то лайфхаки, например, что нам нравится: центр или верхний угол или что-то ещё. Так что мы, скорее всего, можем быстро сделать следующий ход. Но оптимален ли он? И я осмелюсь сказать, если в детстве или даже недавно вы когда-либо проигрывали в крестике нолики, значит, вы просто плохо играете в крестики нолики, потому что логически нет никакой причины, по которой вы вообще должны проигрывать в крестике нолики, если вы играете оптимально. В худшем случае вы должны свести игру к ничьей. Так что если вы проигрываете, вы делаете что-то не так. Но в вашу защиту можно сказать, что здесь вопрос не всегда очевиден. Как ответить, когда правильный ход не лежит прямо перед вами? Ход на победу или ход на блок? Один алгоритм, который вы могли
Minimax
использовать все эти годы, называется Mimx. И как следует из названия, всё сводится к минимизации чего-то и или максимизации чего-то другого. Так что превратим игру в математику, но в относительно простую математику. Итак, здесь у нас есть три показательных поля для крестиков ноликов. Здесь выигрывает нолик, здесь крестик, а посередине ничья. Неважно, как именно мы оцениваем эти поля, но нам нужна последовательная система. Так что я предлагаю: каждый раз, когда выигрывает нолик, счёт игры равен -1. крестик, счёт игры равен +1. А каждый раз, когда никто не выигрывает, счёт равен нулю. Таким образом, на этом этапе каждая из этих полей имеет значение -1 0 и1. Следовательно, цель в этой игре в крестике Нолики теперь, чтобы крестик максимизировал свой счёт, потому что один - это наибольшее доступное значение, а цель Нолика - минимизировать свой счёт. Вот так мы убираем из игры веселье и превращаем её в математику, где один игрок просто хочет максимизировать, а другой минимизировать свой счёт. Небольшой тест. Вот поле, оно не раскрашено. Каково значение этого поля? Один, потому что крестик имеет вертикальную линию по центру. Значит, крестик - это один, но - это -1. В противном случае ничья. И теперь давайте посмотрим, как с этими принципами определить, куда нам следует ходить в крестиках-ноликах. Вот довольно простая конфигурация. Осталось всего два хода. Нетрудно понять, как выиграть или свести игру к ничьей. Ну давайте используем её для простоты. Сейчас, например, ход нолика. Итак, куда может пойти нолик? Это подводит к вопросу, какова ценность этого поля или как нам минимизировать значение поля, чтобы Нолик выиграл. Нолик может пойти в одно из двух мест: в левый, верхний или в нижний по центру. Если нолик идёт в левый верхний, нам следует рассмотреть, каково значение этого поля, является ли оно минимальным. Если нолик идёт сюда, крестик, очевидно, пойдёт сюда. Следовательно, крестик выигрывает, так что значение этого поля будет равно один. А поскольку есть только один логический путь от этой конфигурации к этой, мы можем по транзитивности считать значение этого поля равным один. И поэтому нолик, вероятно, не хочет идти туда, потому что это довольно максимальный счёт. А нолик хочет минимизировать. А вот здесь, если нолик идёт в нижний по центру, тогда крестик пойдёт в левый верхний. И теперь ни у кого нет трёх в ряд. Так что значение этого поля равно ноль. Мы вполне можем считать это нулём, потому что это единственный логический способ туда прийти. Так что теперь нолик более математически и логически может решить, хочу ли я конечный результат один или конечный результат ноль. Ноль, вероятно, лучший вариант, потому что он меньше, чем один. И, следовательно, это минимально возможный результат. Так что Нолик пойдёт в нижний по центру и как минимум обеспечит ничью. Здесь вы видите доказательство того, что если вы, люди когда-либо проигрываете в крестике Нолики, вы не следовали этой логике, но вы, вероятно, можете сделать это, когда осталось два хода. Но загвоздка в том, что давайте отмотаем назад к трём оставшимся ходам. Здесь есть три пустые клетки, и я как бы отдалил картинку. Загвоздка в том, что дерево решений становится гораздо больше по мере того, как остаётся всё больше и больше ходов. Оно становится всё больше и более разветвлённым, по сути удваиваясь по размеру и ширине. И здорово, если у вас есть возможность записать это на листе бумаги. Но если вы делаете это в уме, играя против пятиклассника, то вы, вероятно, не прорисовываете все возможные поля и конфигурации, пытаясь играть оптимально, а действуете по интуиции. И ваша интуиция может не совпадать с алгоритмом, проверенным и надёжным. Нимакс, который в идеале приведёт вас к победе, но, по крайней мере, позволит вам принудительно свести игру к ничей. Но крестики нолики не так уж и сложны. Я имею в виду, сколько вообще существует разных способов сыграть в крестики нолики. Мы могли бы написать компьютерную программу, которая практически всегда будет играть оптимально. Мы могли бы использовать такой код. Если игрок крестик, для каждого возможного хода вычислить счёт поля в данный момент времени, а затем выбрать ход с наивысшим счётом. То есть вы просто математически перебираете все возможности, а затем принимаете решениние. Иначе, если игрок Нолик, по сути, сделать то же самое, но выбрать минимально возможный счёт. Таков код для крестиков-ноликов. А сколько вообще существует способов сыграть в крестики-нолики? 255. 168, что означает, что если бы мы нарисовали это дерево, оно было бы чертовски большим, и вам потребовалось бы довольно много времени, чтобы как бы продумать все эти возможности. Так что в вашу защиту, возможно, вы не так уж плохи в этой игре. Но как насчёт шахмат, которые часто используются как мера того, насколько умён компьютер, будь то когда-то Ватсон, играющий против человека, или что-то ещё. Если рассмотреть даже только первые четыре хода в шахматах, под чем я имею в виду, что чёрные ходят и белые ходят, а затем они делают это ещё по три раза каждый раз, сколько существует разных способов сыграть в шахматы. Оказывается, 85 млрд только для того, чтобы начать игру. Это огромное количество решений, которые нужно рассмотреть, а затем принять. А как насчёт игры го? Первые четыре хода 266 квинтилионов возможностей. И вот здесь мы, как люди и даже с нашими современными ПК, Mac-телефонами в каком-то смысле должны развести руками, потому что у меня просто нет такого количества байтов памяти в моём компьютере. У меня нет и такого количества часов жизни, чтобы реально
Машинное обучение
посчитать все эти числа и найти решение. И вот здесь в игру вступает и, потому что всё уже не так просто, как писать if, else и циклы. И уже не так просто, как просто перебирать все возможности. Вместо этого вам нужно писать код, который решает задачу не напрямую, а в каком-то смысле косвенно. Вы пишете код так, чтобы компьютер сам понял, как выигрывать. Возможно, показывая ему конфигурации доски, в которых хорошо находиться, то есть перспективные, и, возможно, показывая ему доски, в которых он не хочет оказываться, потому что это приведёт к его поражению. Другими словами, вы его обучаете, но не обязательно исчерпывающим образом. И это то, что мы сегодня называем машинным обучением. Написание кода, с помощью которого машины учатся решать задачи, как правило, обучаясь на огромных объёмах данных, а затем в новых задачах, ищут закономерности, с помощью которых они могут применить эти прошлые обучающие данные к текущей задаче. И обучение с подкреплением - это, по сути, один из способов думать об этом. И на самом деле мы, как люди, используем обучение с подкреплением, которое является типом машинного обучения практически постоянно. На самом деле забавная демонстрация здесь связана вот с этими блинами. Я вам сейчас покажу короткую запись настоящего исследователя в лаборатории, который пытается научить робота переворачивать блины. Мы увидим в этом видео, что есть робот с рукой, которая может двигаться вверх, вниз, влево, вправо. Это человек-исследователь, и он просто собирается показать роботу один или несколько раз, как переворачивать блин, скрещивает пальцы и о'кей, похоже, у него получилось. Делает это снова. Не совсем так же, но довольно неплохо. И теперь он собирается позволить роботу просто попытаться понять, как переворачивать этот блин. после того, как он обучил его всего несколько раз, в первые несколько раз, скорее всего, у робота будет получаться не очень хорошо, потому что он на самом деле не понимает, что именно только что сделал человек и в чём вообще состоит цель. И вот ключевая деталь обучения с подкреплением. За кадром человек, вероятно, поощряет робота, когда он хорошо справляется. То есть, чем лучше и лучше он переворачивает блин, тем больше он получает вознаграждений. Например, нажатием клавиши и начислением ему очка. Мы даём ему цифровой эквивалент печеньки или наоборот каждый раз, когда робот косячит и роняет блин на пол, образно говоря, шлипок по рукам, наказание. И все вы, кто являются родителями, а по определению сегодня многие из вас ими являются, будь то не так буквально или просто словесное одобрение или выговоры, вы, вероятно, в какой-то момент обучали детей делать больше одного или меньше другого. И то, что вы видите на фоне - это теперь просто квантизация движений, координаты X YZ, чтобы он мог делать больше тех XYZ, которые привели его к какому-то вознаграждению. И теперь, после примерно пятидесяти попыток, робот, кажется, становится всё лучше и лучше. Посмотрим, смогу ли я перевернуть эту штуку, не опозорившись. Это довольно неплохо. Я делаю это уже давно. Итак, мы увидели, как можно усиливать обучение в такой области. Давайте возьмём пример, знакомый тем из вас, кто играет в игры. В любой игре, где есть какая-то карта или мир, который нужно исследовать вверх, вниз, влево, вправо, возможно, вы пытаетесь добраться до выхода. Итак, здесь упрощённо игрок находится в жёлтой точке, а здесь, например, зелёным показан выход с карты, и вы хотите добраться до этой точки. И, возможно, где-то ещё в этом мире есть много лавовых ям, и вы не хотите упасть в лавовую яму, потому что вы теряете жизнь или теряете очко. Мы с высоты птичьего полёта, очевидно, видим, как добраться до зелёной точки. Но если вы играете в игру вроде Зельды или что-то подобное, всё, что вы можете делать - это двигаться вверх, вниз, влево, вправо и как бы надеяться на лучшее. Предположим, жёлтая точка случайным образом выбирает направление и идёт вправо. Теперь мы можем как бы отнять жизнь, отнять очко или наказать его, чтобы он понял. Не делай так. И при условии, что у игрока есть немного памяти, будь то человек, игрок или кот, тёмно-красная линия означает не делай этого снова, потому что это не привело к хорошему результату. Так что, возможно, в следующий раз жёлтая точка идёт сюда и сюда. И затем, о, я не понял, что это та же самая лавовая яма, но это нормально. Используем немного больше памяти и напомним себе: "Не делай так", потому что я только что потерял вторую жизнь. Возможно, он идёт сюда и понимает, что не нужно делать так. По сути, меня либо наказывают за неправильные действия, либо, как мы скоро увидим, поощряют за то, чтобы делать больше успешных действий. И просто по случайности возможно, я наконец добираюсь до выхода вот таким образом. И за это я могу быть вознаграждён. Теперь я получил 100 очков или что-то там ещё. И теперь, согласно этим зелёным линиям, я могу просто следовать этому пути снова и снова. И я всегда могу выигрывать в этой игре, примерно как я сейчас спустя 30 лет играю в Super Mario Brothers. Я могу проходить все варпуровне, потому что знаю, где всё находится. Почему-то это всё ещё у меня в мозгу. Это лучший способ играть. Что плохого в этом решении? Да, именно. Да, я сделал гораздо больше ходов, чем было нужно. В каком ты классе? Седьмой класс. Прекрасно. Так вот, наблюдение семиклассника как раз в том, что мы могли бы выбрать более короткий путь, который, по сути, вот такой, пусть и с некоторыми прямыми ходами. И поэтому мы никогда не найдём этот более короткий путь. Мы никогда не получим максимально возможный счёт, если я просто продолжаю следовать своему проторенному пути. И как же нам вырваться из этого шаблона? Вы можете видеть это даже в реальном мире. Ещё один такой личный пример. Я из тех людей, которые по какой-то причине, если я прихожу в ресторан в первый раз, выбираю блюдо из меню, и мне оно очень нравится. Я больше никогда не заказываю в этом меню ничего другого, кроме этого блюда, потому что я знаю, что оно хорошее, но в меню может быть что-то ещё лучше, но я никогда этого не узнаю, потому что я застрял в своих привычках. Но что, если бы мы исследовали хотя бы немного? Есть такой принцип: исследование против использования, когда речь идёт об использовании искусственного интеллекта для решения задач. До сих пор я просто использовал знания, которые у меня уже есть. Не проходи через красные стены, проходи через зелёные. Я приду к финальному решению. Но что, если я просто добавлю немного случайности по пути? В 10% случаев я, как компьютер в этой истории, сгенерирую случайное число между нулём и единицей. Если оно меньше этого процента, что будет происходить в 10% случаев? Я сделаю случайный ход вместо того, который, как я знаю, приблизит меня к выходу. В противном случае я действительно сделаю ход с наибольшей ценностью. Теперь это не обязательно выигрывает мне игру в первый раз. Но если я буду играть достаточно долго и достаточно много и добавлять немного этой случайности, я вполне могу найти лучшее решение и, следовательно, стать лучшим игроком. Если бы я просто в 10% случаев заказывал что-то другое из меню, я мог бы обнаружить, что там есть потрясающее блюдо, которые иначе бы я никогда не открыл. Поэтому, используя такой подход, можем ли мы в итоге найти более оптимальный путь, максимизируя на счёт и показывая результат даже лучше, чем если бы мы просто использовали одни и те же знания. Так что вы можете видеть это даже в игре Breakout, особенно если вы пишете решение в коде, чтобы эта игра игралась за вас. Давайте я открою ещё одну видеозапись с играющим в брейкаут. И то, что этот и делает, это, по сути, пытается понять, возможно, более умно, чем вы или я могли бы, как играть в эту игру оптимально. И мы увидим здесь, что как и у робота, переворачивающего блины, здесь есть некоторые понятия очков, вознаграждений и наказаний. Так что прямо сейчас ракетка просто делает случайные вещи. Она ещё не очень понимает, как играть в игру. После 200 эпизодов она понимает, что мой счёт растёт, если я попадаю по мячу и падает, если я его пропускаю. И он всё ещё немного дёрганный. Он не совсем понимает, что именно ему нужно делать и почему. Но если делать это снова и снова, если его достаточно поощряют или наказывают, вы увидите, что он начинает играть довольно хорошо и приближаться к тому, как мог бы играть человек. Но вот здесь алгоритм становится немного жутковатым. Если дать ему играть достаточно долго, или если мы с вами, люди будем играть достаточно долго, вы можете обнаружить определённый трюк в игре. И становится немного пугающе разумным. Оказывается, если пробить верхний ряд, ты можешь позволить игре просто играть самой за себя и максимизировать свой счёт, даже не касаясь мяча. И мне это кажется немного жутким, что он просто сам догадался, как это делать, без каких-либо указаний. Но это всего лишь логичное продолжение поощрения за хорошее поведение и наказание за плохое. Так что в следующий раз, когда играете в брейкаут, подумайте о такой стратегии, вместо того, чтобы делать больше работы самому. Пусть вместо вас это делает компьютер. Ну а
Глубокое обучение
что ещё стоит учитывать в этом мире? И в контексте машинного обучения есть категория обучения, которая называется обучением с учителем. И мы используем её уже много лет. И на самом деле наш первый пример со спамом в начале был именно таким. Почему? Потому что именно вы и помещали письма в папку спама. И по сей день, может быть, раз в день я нажимаю сочетание клавиш в Gmail, чтобы сказать: "Ага, это спам. Ты должен был понять это". И это дополнительно обучает алгоритм Google, предполагая, что это не только я один, но, возможно, тысячи людей помечают такой же тип писем, как спам. Это и есть обучение с учителем. Так что обнаружение спама может быть одним из таких примеров. Но загвоздка в том, что ручная разметка данных таким образом плохо масштабируется. Это было бы похоже на то, чтобы кто-то в Google или Microsoft помечал каждое письмо или кто-то в Netflix делал то же самое для всех видео. Это дорого с точки зрения человеческих ресурсов. И, конечно, существуют задачи с таким объёмом данных, что людям просто нереалистично с этим справиться. Нам приходится переходить к модели без учителя. И именно здесь мир начинает рассматривать глубокое обучение, решение задач с помощью кода, где у вас уже нет людей в контуре в том же самом виде. И нейронные сети, вдохновлённые биологией, являются своего рода основой того, что сегодня считается передовым уровнем и что лежит в основе сегодняшней резиновой уточки, и в более общем смысле таких вещей, как большие языковые модели, вроде Ча GPT и им подобных. И вот здесь показанный довольно абстрактно изображён нейрон. Это нечто в человеческом теле, что передаёт сигнал, скажем, слева направо электрически. Если у вас есть несколько нейронов, они могут взаимодействовать друг с другом. Так что если я думаю какую-то мысль, то знаю, как поднять руку, потому что какое-то электрическое сообщение пришло от моей головы к этой конечности. Как компьютерные учёные, мы всё это абстрагируем. Так что вместо того, чтобы рисовать их как нейроны, давайте просто начнём рисовать их так. Если между ними соединительная ткань, просто нарисуем прямую линию, ребро между ними. Так что это то, что компьютерный учёный назвал бы графом. Если у вас есть два таких нейрона здесь, ведущих к одному нейрону здесь, вы можете думать об этом как о двух входах в задачу и теперь одном выходе тоже. Мы можем представить себе понятие решения задач, чем и занимается CS50 и вводные курсы в целом. Так что давайте решим задачу с помощью нейронной сети, не обязательно заранее её обучая, просто позволяя ей самой понять, как ответить на этот вопрос. Вот очень простой двумирный мир. Сетка XY. И вот две точки. И точки в этом мире либо синие, либо красные. Но я пока не имею ни малейшего представления, что именно делает точку синий или красной. Однако, если вы обучите меня на этих двух точках, особенно если вы позволите мне разместить этот мир в терминах X-координат по горизонтали, Y- координат по вертикали, и тогда знаете что? Мы можем очень просто представить эту нейронную сеть как представляющую X-координату здесь, Y-координату здесь. А ответ, который я хочу получить - это в кавычках красный или синий или ноль или один или труue или false. Как вам удобнее? Так как же мне перейти от конкретной xy координаты? К предсказанию цвета, если я знаю только координаты, возможно, лучшее, что я могу сделать - это просто разделить мир на синие точки слева и красные точки справа, провести линию наилучшего соответствия, исходя из очень минимального объёма данных. Конечно, если вы дадите мне третью точку, будет довольно легко понять, что я немного поторопился. Эта линия не вертикальная, так что, возможно, мы повернём линию вот так. Теперь я могу с большей вероятностью предсказывать на основе X и Y, какого цвета будет следующая точка. Дайте мне достаточно таких точек. я смогу получить довольно хорошую линию наилучшего соответствия. Это не идеально, но вот подсказка, почему и не идеален. Но в 99% случаев я прав. Я могу сделать ещё лучше, если вы позволите мне немного извить линию. Так что же мы на самом деле делаем, реализуя эту нейронную сеть, пусть и упрощённо, всего с тремя нейронами. Ну, по сути, мы пытаемся получить три значения, три параметра A, B и C. И что они представляют? По сути, просто решение этой формулы. Та линия, которую мы нарисовали, может быть представлена, если вспомнить школьную математику примерно такой формулой, где это а x + b x y плюс некоторая константа c. И мы можем просто произвольно договориться, что если это значение математически даёт мне число больше нуля, я предсказываю, что это будет синий. В противном случае красный. Мы можем таким образом сопоставить нашу математику, как и в крестиках-ноликах, с реальной задачей, которая нас интересует, определив мир таким образом. Итак, если вы дадите мне достаточно точек данных, я смогу получить значение для этого А, этого B и этого C, так называемых параметров в нейронных сетях. В реальности нейронные сети не состоят из трёх нейронов и пары рёбер. Они выглядят примерно вот так. И на практике у них миллиарды таких элементов здесь на экране. В этом случае практически каждый из этих рёбер представляет собой некоторое математическое значение, полученное на основе огромного объёма обучающих данных. И хотя я, как компьютерный учёный, могу знать, что представляют эти нейроны здесь, потому что это мои входы. И я, как компьютерный учёный знаю, что представляет вот это на выходе, если бы вы условно сняли крышку с этой штуки и заглянули внутренние нейронные сети, то, несмотря на то, что там были бы миллионы, миллиарды чисел, я не смог бы сказать вам, что представляет этот нейрон и почему у этого ребра такой вес. Это из-за огромного объёма обучающих данных. Так просто сходится математика. Если вы дадите мне больше данных, я могу изменить некоторые из этих параметров ещё раз. Так что в итоге граф может выглядеть совершенно иначе, но мои входы и выходы останутся там, что я использую для решения той самой задачи. Так что если вы хотите предсказывать осадки по влажности или давлению, у вас могут быть два входа, дающих один выход. Потраченные на
Большие языковые модели
рекламу доллары в конкретном месяце могут предсказывать продажи просто за счёт обучения на таких объёмах данных. И когда мы теперь возвращаемся к большим языковым моделям вроде CL Gemin H от GPT, то, что на самом деле происходит, и это всё совсем недавнение достижения, здесь на скриншоте показаны некоторые недавние научные статьи, которые продвинули большую часть этого прогресса в последние годы. У вас есть, например, от Open AI генеративный предобученный трансформер. Это много слов, но именно это GPT в чат GPT. И по сути это нейронная сеть, обученная на больших объёмах текстовой информации, которая даёт нам интерактивный чат, который у нас есть на занятиях. и в целом в самом чат GPT. Итак, пример того, что на самом деле происходит под капотом у этих GPT. Вот абзац, который до недавних лет было довольно сложно закончить троеточием. Массачуссетс - это штат в регионе Новой Англии на северо-востоке США. Он граничит с Атлантическим океаном на востоке. Столица штата - это почти любой, кто живёт в Массачусетсе, вероятно, знает ответ. Но если этот и просто обучался на огромном количестве данных, то, вероятно, есть много людей, которые говорят Массчуссетс в одной части предложения, а затем ответ, который я пока не буду называть, который находится в другой части. Но в этом примере, учитывая, что вопрос, который мы задаём, находится как бы далеко от некоторых полезных ключевых слов, до недавнего времени это была сложная задача, потому что расстояние было слишком большим. Более того, здесь используются существительные, которые подменяют собственное имя. На пример. Мы внезапно начинаем называть это штатом. Мы называем это штатом здесь внизу. И для ИИИ не обязательно было очевидно, что мы говорим об одном и том же, в отличие от случая вроде город, запятая штат. Так что в двух словах, то, что мы сейчас делаем, особенно для решения подобных задач - это сначала разбиваем предложения или обучающие данные или входные данные на массив или список самих слов. Мы создаём представление каждого из этих слов. Например, слово Mчусетс, если закодировать его определённым образом, будет представлено массивом или вектором чисел, значениями с плавающей точкой. Их так много, что слово Массачусетс в одной модели будет использовать эти 1536 чисел с плавающей точкой, чтобы представить Массачуссеs, по сути, в нм пространстве. То есть не просто XY, а где-то виртуально там. И затем, и это было ключевым для этих GPT, рассчитывается внимание на основе всех этих данных, при котором на этой картинке более толстые линии означают большую связь между этими двумя словами. Так что для Массачусетс и штат делается вывод о более толстой линии, более высоком внимании от одного слова к другому, тогда как наши эй и прочее имеют более тонкие линии, потому что они просто не дают и столько сигнала о том, каков ответ на этот вопрос. Между тем, когда вы затем подаёте это предложение вроде столица штата, эта здесь по одному слову на нейрон. Цель - получить ответ на этот вопрос. И даже здесь это представление намного меньше, чем реальная нейросеть. Но по сути все эти LLM, большие языковые модели - это просто статические модели. То есть какое слово с наивысшей вероятностью оно должно выдавать в конце этого абзаца? на основе всех постов на Redit, результатов поиска Google, энциклопедий и Википедий, которые оно нашло и на которых обучалось онлайн. Ответ, надеюсь, будет Бостон.
Галлюцинации ИИ
Но, конечно, в одном проценте случаев может быть и меньше. Ответ может быть неверным. И даже собственная утка CS50 не безошибочна, несмотря на то, что мы написали много кода, чтобы попытаться снизить количество этих ошибок. И эти ошибки - это то, что мы наконец называем галлюцинациями, когда и просто что-то выдумывает. Возможно, потому что какой-нибудь сумасшедший человек в интернете что-то выдумал, и это было интерпретировано как авторитетный источник или просто из-за невезение, из-за части этого исследования в 10% случаев, в 1% случаев, и как бы отклонился в эту сторону в большой языковой модели и выдал ответ, который на самом деле неверен. И поэтому я подумал, что закончу сегодня на этой финальной ноте стихотворением, с которым многие из нас могли вырасти. От Шела Сильверстайна про машину для домашки, которая много лет назад каким-то образом предсказала то состояние, в котором мы окажемся с этими и машинами. Машина для домашки. О, машина для домашки. Самое совершенное устройство, которое только видели. Просто положи свою домашку, затем брось 10 центов, щёлкни выключателем, и через 10 секунд твоя домашка выходит быстрой и чистой, насколько возможно. Вот она, 9 + 4. И ответ. Три. Ох, похоже, она не так совершенно, как я думал. Увидимся в следующий раз.