Вы находитесь на странице: 1из 234

Сергей Соболенко

Искусственный интеллект. Строки, контекст и волны на


Паскале
Шрифты предоставлены компанией «ПараТайп»

© Сергей Соболенко, 2019

Эта книга подарит путешествие в увлекательный мир строковых данных, открывающий


новые возможности для исследования искусственного интеллекта. В ней вы найдете
множество примеров и иллюстраций, а кроме того, идей, до этого момента
неопубликованных. Она будет полезна и интересна как новичку в теме программирования,
так и искушенному читателю, интересующемуся наукой и технологиями.

12+
ISBN 978-5-4496-3281-4
Создано в интеллектуальной издательской системе Ridero

Оглавление
1. Искусственный интеллект. Строки, контекст и волны на Паскале

2. Предисловие, которое рекомендуется прочитать

3. Глава 1. Строковые процедуры и функции на практике

1. Подготовка к работе в TMT-Pascal

2. Строковые данные

3. Длинные строки

4. Функция поиска

5. Копирование

6. Кодировки

7. Нормализация строк

8. Преобразования строк

9. Сложное сравнение

10. Модель пунктуации

11. Шаблоны поиска

12. Разреженный текст

13. Выбор слов в блоке текста

4. Глава 2. Использование модели многомерного множества

1. Принципы организации MSM

2. Алгоритмы записи и чтения данных MSM


3. Простое определение

4. Общее и частное

5. Использование свойств элементов

6. Синонимы

7. Вопрос-ответ

8. Весовые значения и зависимости

9. Возможные модификации правил обработки данных

5. Глава 3. Проблема понимания

1. Простой бот

2. Голосовой помощник

3. Сильная логическая машина

4. Культурный феномен искусственного интеллекта

6. Глава 4. Контекст и волны

1. Полисемия: волновое решение

2. Генерация волны

3. Обработка данных для волнового анализа

4. Связи элементов

5. Алгоритм и процедуры полуавтоматического расширения понятий классификатора

7. Глава 5. Теория познания

1. Модель символьной логики

2. Методология мышления

8. Глава 6. Информация, язык и интеллект

1. Материальная природа информации

2. Формы языка

3. Язык и письменность — не одно и то же

4. Интеллект из пустых банок

5. Гештальт-цикличность

6. Метафоры об MSM

7. Сингулярность неизбежна

8. Единство MSM как единство чисел

9. Трое в лодке, не считая автора

9. Заключение
«Обучение путем подачи хорошего примера часто — самый эффективный, а иногда —
и единственно возможный метод.»
Никлаус Вирт, создатель языка Паскаль.

«Меня не интересует создание мощного компьютерного интеллекта. Мне вполне хватило бы


самого посредственного — примерно как у президента Американской телефонной
и телеграфной компании.»
Приписывается Алану Тьюрингу

Предисловие, которое рекомендуется прочитать


Учебные заведения России и мира продолжают обучать программированию на Паскале.
И это происходит не из-за лени преподавателей к переизданию методических пособий
по информатике. Такое обучение позволяет понять гибкую внутреннюю логику организации
программ, ведь Паскаль обладает свойствами универсальности и широкими возможностями,
при своей компактности и легкости понимания. С помощью этого языка программирования
можно адаптировать, подготовить восприятие школьника или студента для самоорганизации
и в других языковых средах.
Поэтому в этой книге автор изложил полезные и практичные аспекты накопленного
многолетнего опыта, приемы и методы работы с неформализованными строковыми данными
на Паскале; а также сведения о новой технологии, являющейся плодом этих практических
изысканий. Модель описанной технологии искусственного интеллекта, в качестве
исследовательского проекта также реализуется на этом языке. При этом, значительная часть
приведенных алгоритмов и программных процедур публикуется впервые, что придает
изданию особую ценность.

Почему эта книга актуальна?


Вся беда в том, что профессиональным приемам подробной, прикладной работы
с данными строкового типа занимается очень ограниченное число специалистов. Отсюда
вытекает явный недостаток практических пособий по данной тематике,[1] и как следствие —
неявный прикладной функционал в современных языковых компиляторах.[2] Также этому
есть и другое вполне логичное объяснение. Тема парсинга строковых данных много
десятилетий являлась своего рода табу, дурным тоном программирования. Традиционно
устоялся стереотип, что строковые переменные — это «рабы интерфейса» и баз данных,
а неформализованные сведения — зло, с которым нужно бороться. Результат — налицо:
отсутствие приличной школы: как учителей, разработчиков, так и их учеников. Отсутствие
предложения за много десятилетий сформировало зеркальное отсутствие спроса. А затем
появились и искусственные нейронные сети, которые худо-бедно начали с этими данными
работать; но вот разработчикам от этого не стало легче. По существу, искусственные
нейросети «подарили» программистам «черный ящик», действия которого бывают
необъяснимы.[3]
Этот пробел явно требует компенсации; тем более, очевидно невостребованной
в современной парадигме когнитивных систем оказалась ниша символьного искусственного
интеллекта.[4]

В книге приводятся необычные, но достаточно простые решения по проекту


интеллектуальной символьной диалоговой системы. Тем не менее, описанные подходы к ее
реализации категорически отличаются от классического представления
об объектно-ориентированном программировании, традиционных символьных экспертных
систем и от современной методологии машинного обучения. Также весьма существенным
моментом в этой работе является отказ от прямого использования символьных конструкций
на естественном языке. Тем не менее, практические результаты показывают, что этот
комплекс методик может решать задачи, по сей день считавшиеся серьезной проблемой.

Чем мы занимаемся?
«Мы» в данном случае — это небольшое сообщество единомышленников, не входящих
в какое-либо формальное объединение, но захваченных идеей реализации искусственного
интеллекта на базе технологии MSM.
Сверхзадачей исследований в данном направлении не являлось и не является
создание сильного искусственного интеллекта[5] в понимании современных физиков
и инженеров; (такого, который будет многократно превосходить умственные способности
людей). Для начала, следовало бы создать «средний» интеллект. Такой, каким обладает
например, ваш сосед, Михаил Ефремович, учитель географии средних лет. Особо ничем
не выдающийся, иногда не очень внимательный или рассеянный, иногда циничный, иногда
смешной, но… понимающий. Способный сравнивать, оценивать, делать выводы,
формулировать суждения. Решать повседневные задачи. Планировать, следовать
определенным целям. И главное, способный действовать так, как этого требуют
обстоятельства. Вы скажете, такие машины уже есть? Хорошо, если вы так считаете,
не будем спорить. Но, автор считает, что нет.

Это учебник?
Книгу можно использовать как учебное пособие по разделу строковых данных
на Паскале. Но было бы неверно воспринимать показанные решения, как нечто
неоспоримое, — любая приведенная процедура может быть усовершенствована. Сама
природа строк приближает нас к другой форме подхода к методикам реализации. Здесь,
в этой новой реальности открывается то, что называется нечеткостью, субъективной оценкой
и многогранностью связей элементов конструктора, который мы можем выстраивать.
Книга затронет и некоторые философские, психологические, лингвистические аспекты
сущности человеческого восприятия. Но она не станет тешить человеческое самолюбие или
рисовать утопические миры. На этом поле и без того работают слишком много мастеров
слова, чтобы стать только очередным из них. Автору это неинтересно.
Гораздо интереснее работа, имеющая под собой практическое основание,
а не метафорические рассуждения. «Практика есть критерий истины» — известное
выражение, приписываемое Карлу Марксу, но авторство в данном случае не имеет значения.
Эта книга пробует осветить шаг за шагом движение в новом, малоизученном
направлении работы с новой технологией. Страница за страницей практического освоения
вы имеете шанс испытать чувства первооткрывателя, какие вероятно испытывал Левенгук,
настраивающий первый оптический микроскоп. И пусть спустя сотни лет был построен
и микроскоп электронный, но микроскоп конструкции Левенгука был самым важным,
первым шагом в нужном направлении.
С другой стороны, кто-то мог бы и сказать «Да обернитесь вокруг: в нашем мире data
science,[6] блокчейна[7] и искусственных нейросетей нет места для того, чтобы
заниматься какими-то символами…» Но вещь, кажущаяся сегодня слишком простой или
неочевидной может стать завтра тем самым электронным микроскопом. История знает массу
таких примеров.
Например, концепция первого перцептрона,[8] на основании которой родилось все
изобилие современных искусственных нейросетей и машинного обучения более чем
на 30 лет была подвергнута остракизму во время так называемой «Зимы искусственного
интеллекта». И что бы сказали бывшие критики перцептрона теперь, когда каждая
домохозяйка, школьник или пенсионер, имея некоторый интерес и немного свободного
времени может настроить искусственную нейросеть и сортировать огурцы по 12 критериям
в собственном гараже.[9]
Можно освоить вещи и поинтереснее огурцов, например машинный перевод, зрение
сквозь стены или толщи океанских вод… Но автор в данном случае равнодушен
по отношению к искусственным нейросетям, к биг-дате или к попыткам создавать
коннектоны. Безусловно, это в своем роде интересные, нужные и незаменимые вещи,
представляющие немаловажный научный и коммерческий интерес. Плохая новость состоит
в том, что все это имеет мало общего с настоящим интеллектом, который основан
на процессе понимания смысла. Да, искусственные нейросети хорошо работают.
Выписывают штрафы. Рисуют картины. Консультируют по ряду известных проблем. Играют
в шахматы, Го или водят машины. Они это все умеют или будут уметь; и ваша сетка будет
уметь гораздо лучше сортировать огурцы, чем человек, — с помощью нескольких строк
кода, небольшой настройки переменных и нескольких тысяч примеров выборки. Это —
сложная, но популярная и вполне осуществимая задача в рамках существующей парадигмы
машинного обучения. Кроме того — уже изданы сотни прикладных учебных пособий
по этой теме, существуют простые видеоинструкции по работе с кодом на Питоне
и в свободном доступе находятся нужные приложения и наборы данных.
То, о чем говорит эта книга — трудно. Требует умственного труда, фиксации внимания,
сосредоточенности. Эта книга — для тех, кто привык использовать критическое мышление,
ставить все под сомнение, моделировать собственную реальность, а не идти вперед
за общественным мнением.
Кого-то эта книга может развлечь, кого-то заставит задуматься или по-новому взглянуть
на информационные технологии. Возможно — кто-то сделает интересный учебный проект,
доклад, презентацию или реферат, за который может получить хорошую оценку. А кто-то,
(и на это хочется надеяться), использует описанные методы, чтобы участвовать
в приближении лучшего будущего с машинами, имеющими сознание. При этом, не будет
иметь значения язык реализации, — все описанные методики могут быть переведены
на любой язык программирования для достижения лучших показателей в скорости,
адаптивности или коммерческой ценности.

Что здесь интересного?


Во-первых, эта книга является практическим руководством по работе со строковыми
данными и может выполнять роль «решебника» для разного типа задач; во-вторых, она
рассказывает о новой технологии, (в которую автор оказался замешан практически
поневоле); и в-третьих — она затрагивает различные аспекты и неординарные подходы
к проблеме сильного искусственного интеллекта.
При этом автор не станет говорить о чем-то невозможном. Любые части повествования
будут относиться только к тем вещам, которые действительно существуют или к тем,
которые могут быть созданы.
Вначале мы поговорим о представлении строковых данных на Паскале и о том, какие
необычные процедуры и функции можно использовать, чтобы решать неординарные задачи,
из разряда олимпиадных задач по информатике. Вероятно, эта часть особенно понравится
школьникам и студентам, ведь здесь будет описано множество подпрограмм, имеющих
прикладное применение.
Также мы вспомним о том, что такое альтернативная классификация данных
в многомерном строчном множестве и каковы могут быть приемы работы с ними.
Далее, мы сосредоточимся на том, чтобы немного разобраться в действующих
диалоговых интеллектуальных системах, постараемся понять их сильные и слабые места,
разберем их «по винтикам» и порассуждаем, «как это работает?»
Во второй половине книги будут приведены новые методы работы с полисемией
и контекстом, в чем нам поможет волна предложений, адаптированный толковый словарь
и еще немного мозгового усердия.
И наконец, в завершении мы постараемся сконструировать систему, (пока только
в теории, но со значительной степенью детализации) претендующую на звание «сильной
логической машины». В частности, здесь мы поговорим о гештальт-цикличности, теориях
физики мышления и связи логики, языка и интеллекта.
Кстати, в книге вы не увидите отсылки в приложения (чего так не любят многие
читатели): все процедуры и функции описываются в разделе соответствующей тематики
прямо по ходу повествования с приведением иллюстраций, показывающих, что происходит
на экране компьютера.

О чем речь?
Это повествование является не столько логическим продолжением первой книги автора,
сколько изложением «обратной стороны» практического программирования, комплекса
приемов, демонстрирующих структуру программы обработки строковых данных «с нуля».

Книга «Искусственный интеллект: начала MSM», вышла в начале 2018 года.[10] Она
рассказывает об основах перспективной технологии в построении искусственного
интеллекта — многомерном строчном (строковом) множестве (или «Multidimensional Strings
Multiplicity», англ.). Простая программная среда, построенная на основе специфического
классификатора всего за год с небольшим своего существования показала замечательные
результаты, в связи с чем автор посчитал важным продолжить публикацию данных, а также
методов и технологий, реализуемых в этом проекте.
В новой книге автор расскажет и о технологических приемах, использующихся
в программной модели для решения наиболее сложных проблем «понимания» естественного
языка. В первую очередь это касается вопросов полисемии и контекста, которые чаще всего,
(а может быть и по привычке), считаются в ЭВМ непреодолимыми.

Что потребуется?
Все приведенные в качестве примера процедуры и функции реализованы на языке
Pascal, а точнее, в бесплатном компиляторе TMT Pascal lite.[11] Выбор автора оказался
на стороне этого компилятора отнюдь не случаен. Это один из немногих компиляторов
Паскаля, позволяющих использовать во внутренних процедурах и функциях входные
и выходные массивы переменных строчного, логического и целочисленного типа.[12] Кроме
того, TMT Pascal известен, доступен и понятен настолько, что строить простые программные
модели, обрабатывающие строковые массивы данных не доставит большого труда.

Споры об MSM
Технология MSM — вещь своенравная. Первые публикации о ней в сети в начале
2018 года были восприняты с подозрением, а иногда и с недоумением. Под сомнение
ставилась как сама технология, так и квалификация автора, мол «Куда ты, блогер, сунулся
в калашный ряд?»[13]Но были среди критических замечаний и вполне корректные,
достойные рассмотрения.
Особенно часто оппонентам автора вспоминался Курт Фридрих Гедель,[14] австрийский
математик и философ с его теорией о неполноте, а также интерпретация этой теории
физиком и математиком Роджером Пенроузом[15] в контексте принципиального различия
между человеческим мозгом и компьютером. Мы не будем сильно беспокоить Геделя,
поскольку систему MSM, едва ли можно назвать математически формальной.
Основой MSM является иерархическая онтология, которая строится в соответствии
с интуитивной, смысловой, неформализованной «нагрузкой» понятий, их синонимов, весов,
отношений и правил. Иерархия имеет комплементарный код каждого элемента, не имеющий
фиксированной числовой разрядности, который построен по принципу бесконечности
и многомерности. В словарях, организованных по принципу MSM программная модель
оперирует не конкретными словами, а их смысловым кодом, и действует на основе подбора
правил, выбранных в соответствие с конкретными ситуациями. Также в логике MSM
реализован механизм, который позволяет уйти от математической, компьютерной точности
в сторону нечеткости, адаптивности к конкретным условиям. Этот механизм помогает
определять близкие понятия, находить родство и различия слов-множеств на основании
онтологических связей, фактически вшитых в код понятий, в противовес четкому
математическому сходству формального написания слов на естественном языке.
В книге «Искусственный интеллект: начала MSM» приводился простой пример, когда
эталонное знание «Кошачьи имеют красивую шерсть» автоматически порождает новые
знания о том, что «У киски есть красивая шерстка» или «У льва есть прекрасная грива»,
и еще сотен подобных. Этот процесс совсем не похож на математичный. Первоначально
введенные данные, формально, математически, совершенно отличаются от проверочных,
и тем не менее программа находит их идентичными, поскольку связи объектов, вшитые
в коде, и правила обработки позволяют это сделать.
Конечно же, подобный результат можно было бы получить и посредством обычного
объектно-ориентированного программирования (ООП),[16] однако относительно
энергозатрат в данном случае MSM оказывается в безусловном выигрыше за счет
комплементарности кода понятий и общей простоты организации системы. На следующем
примере также видно принципиальное отличие в построении классификатора традиционной
семантической сети (рис. 1) и MSM (рис. 2).
В отличие от традиционного решения семантической сети и вариантов объектного
программирования, в которых сеть связей элементов описывается с помощью
дополнительных описательных блоков, не обладающих комплементарными зависимостями,
элементы в MSM входят в единую структуру, где каждый из них обладает «памятью
предков», а кроме того «отягощен» свойствами и «отношениями». Эта структура обладает
безграничной глубиной связей, «зашитой» в самом коде элементов. На рисунке — показан
лишь микроскопический фрагмент, примерно 1/10 000 доли реального объема структуры,
которая кодируется с помощью этих простых правил.

Р
ис. 1. Элементы семантической сети представлены в виде ориентированного графа, вершины
которого обозначают объекты предметной области, а ребра между ними формируют
отношения между ними.
Кроме того, во взаимоотношениях элементов MSM играют немаловажную роль
дополнительные словари зависимостей, весов и свойств, позволяющие с помощью
минимальных средств строить сложные логические конструкции, обобщающиеся на целые
классы значений.
Приведенный фрагмент классификатора занимает минимальный объем памяти,
составляющий менее (!) 1 килобайта. За счет подобной реализации в перспективе можно
достигнуть возможностей мощной логической машины, имеющей ничтожный объем
в десятки или сотни мегабайт. Так приложение на основе MSM сможет работать даже
в обычной бытовой технике вроде холодильника или микроволновки.

Р
ис. 2. Фрагмент визуализации дерева элементов MSM в 3D.
(Правда, насколько для потребителя может быть актуальна «понимающая» смысл языка
микроволновая печь — это большой вопрос, но почему бы и нет?)
Но возвращаясь к теории Геделя, а точнее, к ее интерпретации, сам Роджер Пенроуз
отчасти соглашается с вероятным сценарием построения сильного искусственного
интеллекта: «Наше непонимание человеческого сознания говорит о наличие большого
пробела в научных знаниях и этот пробел, возможно, находится там, где теории нужно
выйти за пределы вычислительной системы».[17]
Вот еще цитата из его книги «Тени разума»:[18]
«В современной научной картине мира отсутствует один очень важный ингредиент.
Этот недостающий ингредиент совершенно необходим, если мы намерены хоть
сколько-нибудь успешно уместить центральные проблемы мыслительных процессов
человека в рамки логически последовательного научного мировоззрения. Я утверждаю, что
сам по себе этот ингредиент не находится за пределами, доступными науке, хотя в данном
случае нам, несомненно, придется в некоторой степени расширить наш научный
кругозор…»
Не является ли MSM тем самым недостающим звеном, пробелом в науке, выходящим
за рамки математических вычислений? Ведь зависимости, образующиеся в этой технологии
в большей степени функциональны только по причине организованных «вручную» связей,
основанных на смысловой «нагрузке» языка, а также их отношений? Нематематические
«вычисления» следуют контексту естественного языка, который выступает носителем
смыслов, весов, свойств и отношений между элементами; и система MSM в достаточной
степени удовлетворяет полноте отражения этих отношений.
Возвращаясь к рассуждениям в книге «Тени разума», можно сделать вывод, что Пенроуз
в своем видении вычислительной модели опирается на математизм подхода к рассмотрению
идеи воплощения искусственного интеллекта. Суть же метода MSM состоит
в парсинге сходства и различия объектов и использовании правил обработки не только
относительно конкретных элементов, но и в отношении классов объектов и фраз,
предложений, составленных из классов моделей. Похожие процессы происходят
и в искусственных нейросетях, которые также основаны на приципе поиска сходства
и различий, однако диалоговые нейросети используют для своих операций слова, фразы
и предложения естественного языка, тогда как MSM оперирует их смысловым кодом,
заимствованным из понимания естественного языка.
Но другой вопрос состоит в том, является ли сам человек эталоном смысла
и интеллекта? И возможно ли, анализируя смысловую нагрузку языка, достигнуть более
высоких интеллектуальных результатов, чем у среднестатистического человека, как это
видится многим нашим современникам?
Еще одна цитата Пенроуза в этом месте кажется весьма уместной: «Мы уверены, что
являем собой апофеоз интеллекта в царстве животных, однако этот интеллект, по всей
видимости, оказывается самым жалким образом не способен справиться с множеством
проблем, которые продолжает ставить перед нами наше собственное общество».[19]
Таким образом Пенроуз понимает, что человеческий интеллект несовершенен. И как вы
помните, наша задача в конструировании MSM видится скорее в воссоздании модели
человеческой логики в программной модели, нежели в создании сверхинтеллекта.
Объективное человеческое несовершенство является частью человеческой сущности; в связи
с чем рано или поздно нам не избежать его воплощения, частичного или полного
в электронно-вычислительной машине.
Почему этот вывод становится нам очевидным? Напомню, что посыл реализации
диалоговой модели на основе MSM состоит в том, что человеческое мышление
и символьный язык по существу неотъемлемы, как утверждает, в частности, Ноам
Хомски.[20] И хотя этот тезис неоднозначен, но он хорошо аргументирован, ведь мышление
без языка — это набор рефлективных зависимостей, бихевиористический подход, способный
решать лишь узкий набор задач, отвечающих за реакцию на положительное подкрепление.
Находить выход в лабиринте, избежать столкновения, выиграть в шахматы или Го, — это все
замечательные примеры реализации статистических, а иначе говоря, математических
методов в построении искусственного интеллекта. И даже те современные системы, которые
направлены на работу с естественным языком (например, переводчики или
боты-консультанты) по существу не оперируют смыслом языка, а производят лишь
внешнюю, автоматную, формальную обработку статистических зависимостей того или иного
написания слов. Однако они не «понимают» принципиальной разницы между кукурузой
и кузнечиком, не могут сказать, кто быстрее или умнее, не различают позитивных
и отрицательных факторов; а ведь эти вопросы по существу является сутью мышления.
В пользу этой точки зрения стоит привести несколько фрагментов из статьи «Ноам
Хомский: где искусственный интеллект пошел не туда?»:[21]
«… Ноам Хомский и его коллеги работали над тем, что впоследствии стало
называться когнитивной наукой — открытие ментальных представлений и правил,
которые лежат в основе наших познавательных и умственных способностей. Хомский и его
коллеги опрокинули доминирующую в тот момент парадигму бихевиоризма, возглавляемую
гарвардским психологом Б. Ф. Скиннером, в которой поведение животных было сведено
к простому набору ассоциаций между действием и его следствием в виде поощрения или
наказания.
…В мае 2011 года, в честь 150-летней годовщины Массачусетского технологического
института, состоялся симпозиум «Brains, Minds and Machines» («Мозги, умы и машины»),
на котором ведущие ученые-информатики, психологи и специалисты в области нейронаук
собрались для обсуждения прошлого и будущего искусственного интеллекта и его связь
с нейронауками. Подразумевалось, что собрание вдохновит всех междисциплинарным
энтузиазмом по поводу возрождения того научного вопроса, из которого и выросла вся
сфера искусственного интеллекта: Как работает разум? Как наш мозг создал наши
когнитивные способности, и можно ли это когда-либо воплотить в машине?
Ноам Хомский, выступая на симпозиуме, не был преисполнен энтузиазма. Хомский
раскритиковал сферу ИИ за принятие подхода, похожего на бихевиоризм, только в более
современной, вычислительно- сложной форме. Хомский заявил, что опора
на статистические техники для поиска закономерностей в больших объемах данных
маловероятно даст нам объяснительные догадки, которых мы ждем от науки. Для
Хомского новый ИИ — сфокусированный на использовании техник статистического
обучения для лучшей обработки данных и выработки предсказаний на их основе — вряд ли
даст нам общие выводы о природе разумных существ или о том, как устроено мышление.
Эта критика вызвала подробный ответ Хомскому со стороны директора по исследованиям
корпорации Google и известного исследователя в области ИИ, Питера Норвига, который
защищал использование статистических моделей и спорил о том, что новые методы ИИ
и само определение прогресса не так уж далеки от того, что происходит и в других науках.
Хомский ответил, что статистический подход может иметь практическую ценность,
например, для полезной поисковой системы, и он возможен при наличии быстрых
компьютеров, способных обрабатывать большие объемы данных. Но с научной точки
зрения, считает Хомский, данный подход неадекватен, или, говоря более жестко,
поверхностен.
«Мы не научили компьютер понимать, что означает фраза „физик сэр Исаак
Ньютон“, даже если мы можем построить поисковую систему, которая возвращает
правдоподобные результаты пользователям, вводящим туда эту фразу…»
Еще раз уточним: задачей-минимумом нашего сегодняшнего исследования остается
реализация диалоговой системы, близкой к человеческой модели мышления. И есть надежда,
что технология MSM является принципиально новым подходом, способным дать нам новую
пищу, иной способ исследования; вдохнуть новую жизнь в парадигму искусственного
интеллекта как символьной системы, (но — не системы на естественном символьном
языке).[22]

[1] В данном случае рассматривались десятки русскоязычных учебных пособий,


самоучителей, методических рекомендаций и задачников по Паскалю, C++, Java и PHP,
изданных за последние 20—25 лет.
[2] Хотя современные наборы процедур и функций для работы со строками, например
в PHP, Object Pascal и C++ довольно похвальны, (а в Python, — интуитивно удобны
и компактны), но на практике очень редки сколько-нибудь интересные алгоритмы,
использующие их где-то, кроме баз данных и текстовых процессоров. Мастодонты
странного программирования, как Lisp и Prolog автором не рассматривались
принципиально, — они напугали его еще в ранней юности.
[3] Разработчик системы на основе ИНС далеко не всегда может отвечать
за определенные решения программы и ему также сложно утверждать, не является ли
определенный ответ эффектом «переобучения», иначе говоря, случайным, «мусорным»
ответом.
[4] Символический (символьный) искусственный интеллект — это собирательное
название для всех методов исследования искусственного интеллекта, основанных
на высокоуровневом «символическом» (человекочитаемом) представлении задач, логики
и поиска. Символический ИИ лёг в основу доминирующей парадигмы исследований ИИ
с середины 1950-х до конца 1980-х. Наиболее успешная форма символического ИИ — это
экспертные системы, использующие сеть продукционных правил. Продукционные правила
объединяют символы в отношения, похожие на оператор «если-то». Экспертная система,
обрабатывая эти правила, делает логические выводы и определяет, какая дополнительная
информация ей необходима, то есть какие следует задать вопросы, используя
человекочитаемые символы. Определение Wiki.
[5] Сильный искусственный интеллект — гипотеза в философии искусственного
интеллекта, согласно которой некоторые формы искусственного интеллекта могут
действительно обосновывать и решать проблемы. Теория сильного искусственного
интеллекта предполагает, что компьютеры могут приобрести способность мыслить
и осознавать себя как отдельную личность (в частности, понимать собственные мысли), хотя
и не обязательно, что их мыслительный процесс будет подобен человеческому. Определение
Wiki.
[6] «Наука о данных» (англ.) — раздел информатики, изучающий методы
статистической обработки больших объемов данных в приложениях искусственного
интеллекта и проблемы представления данных в цифровом формате для машинного
обучения.
[7] Blockchain (англ.) — технология распределенных баз данных для хранения
информации на различных компьютерах в сети; преимущественно используется для
хранения и передачи информации о финансовых транзакциях. Используется с 2008 года для
работы с криптовалютами.
[8] Перцептрон, или персептрон (англ. perceptron от лат. perceptio — восприятие; нем.
Perzeptron) — кибернетическая модель мозга, предложенная Фрэнком Розенблаттом
в 1957 году и впервые реализованная в виде электронной машины «Марк-1» в 1960 году.
Перцептрон стал одной из первых моделей нейросетей, а «Марк-1» — первым в мире
нейрокомпьютером.
[9] Пример с огурцами — не выдумка. Японец Макото Коике в 2016 году создал
систему, которая с помощью технологии машинного обучения TensorFlow от Google
сортирует огурцы на ферме своих пожилых родителей. Для этого Макото использовал
одноплатный компьютер Raspberry Pi 3, оснащенный камерой. Непосредственной
сортировкой в его системе был занят микроконтроллер Arduino, получающий команды
после обработки в сенсорной сети TensorFlow и отправляющий огурцы в разные ведра.
[10] Соболенко С. В. «Искусственный интеллект: начала MSM: Сингулярность
неизбежна: Издательские решения, 2018. — 272 с.
[11] MS-DOS Edition Version 3.90 (Copyright © 1995, 2002 by TMT Development
Corporation).
[12] Для сравнения, популярный в России ABC Pascal — не позволяет производить
данные операции; а поздние версии Delphi и Object Pascal используют более сложный
операционный инструментарий, чтобы сосредоточиться на нем на страницах небольшой
по объему книги.
[13] Однако, что более интересно, — реакция зарубежного форума OpenAI, где
демонстрация проекта произвела сильное впечатление, вызвала интерес и получила явное
одобрение. Прим. автора.
[14] Курт Фридрих Гедель (нем. Kurt Friedrich Gödel; 1906—1978) — австрийский
логик, математик и философ математики. Наиболее известен сформулированными
и доказанными им теоремами о неполноте, которые оказали огромное влияние
на представление об основаниях математики. Считается одним из наиболее выдающихся
мыслителей XX века.
[15] Сэр Роджер Пенроуз (англ. Roger Penrose, род. 8.08.1931 года, г. Колчестер,
Англия) — английский физик и математик, работающий в различных областях математики,
общей теории относительности и квантовой теории.
[16] Объектно-ориентированное программирование (ООП) —
методология программирования, основанная на представлении программы в виде
совокупности объектов, каждый из которых является экземпляром определенного класса,
а классы образуют иерархию наследования. Определение Wiki.
[17] «Роджер Пенроуз: Квантовая природа сознания», видео канала «2045 Initiative»,
2013 г., на 3 мин. 19 сек.
[18] Роджер Пенроуз «Тени разума — в поисках науки о сознании», М. 2005. с. 27—28.
[19] См. там же.
[20] Аврам Ноам (Наум) Хомски (также часто транскрибируется как Хомский или
Чомски, англ. Avram Noam Chomsky; род. 7 декабря 1928, Филадельфия, штат Пенсильвания,
США) — американский лингвист, политический публицист, философ и теоретик. Профессор
лингвистики Массачусетского технологического института. Также он известен своей
открытой позицией относительно связи мышления, языка и интеллекта.
[21] Автор статьи — молодой ученый-когнитивист Ярден Кац. Ссылка на публикацию:
https://habr.com/ru/post/432846/
[22] Это очень важная деталь, ведь письменный естественный язык по существу
является лишь системой письменного оформления звуков, а не классификатором смыслов.
(Прим. авт).

Глава 1. Строковые процедуры и функции на практике

Подготовка к работе в TMT-Pascal


Все, что нам первоначально потребуется для работы — скачать и установить программу
компилятора TMT-Pascal.
Это можно сделать бесплатно, например,
отсюда: http://pascal.sources.ru/tmt/download.htm.
Здесь можно выбрать, например, версию TMT Pascal Lite v.3.90, которая подходит для
реализации наших задач.
Далее, для работы с русским языком в DOS-приложениях, нам понадобится произвести
некоторые предварительные настройки. На 32-битной Windows:
В Windows XP:
В командной строке меню «Пуск» набираем команду «Regedit». Далее, вносим
изменения: HKEY_LOCAL_MACHINE -> SYSTEM -> CurrentControlSet -> Control ->
KeyboardLayout
Здесь нужно изменить значение ключа 00000409 в папке DosKeybCodes на «ru».

Также, в файле autoexec. nt, расположенном в Windows\system32, надо добавить строку «lh
%SystemRoot%\system32\kb16.com ru». После перезагрузки переключение раскладки
клавиатуры в DOS-приложениях будет производиться комбинациями Ctrl+Left Shift
(английская) и Ctrl+Right Shift (русская). Упомянутый метод нормально работает в том
случае, если Language settings for the system в качестве Default стоит Cyrilic.
В Windows 7:
В файле Windows/sistem32/autoexec. nt вписать строки:
«lh %SystemRoot%system32dosx
lh %SystemRoot%system32kb16.com ru
set clipper=F80»
В файле Windows/sistem32/config. nt вписать:
«files=80; buffers=99».
В командной строке в меню «Пуск» через команду «rehgedit» редактируем реестр:
HKEY_LOCAL_MACHINE -> SYSTEM -> CurrentControlSet -> Control -> Keyboard
Layout
DosKeybCodes изменить значение параметра 0000409 на ru
Раскладка будет переключаться сочетаниями клавиш:
русский — правые Shift+Alt; английский — левые Shift+Alt.
В Windows 10:
Не требует изменений в реестре. В файле Windows/sistem32/autoexec. nt добавляем
строчку — "%SystemRoot%/system32/kb16 ru».
В случае если используется 64-разрядный Windows, требуется использование
приложения-эмулятора для DOS-программ «DOS-box».

Строковые данные
Работе со строковыми данными всегда уделяют слишком мало внимания. Считается, что это
нечто, само-собой разумеющееся и слишком понятное, чтобы делать на них акцент.
В учебниках, самоучителях любой толщины и направленности нам сильно повезет, если им
уделяется хотя бы 2 страницы.
Попробуем же восполнить известные пробелы, для чего начнем с самых азов работы
со строками на Паскале.
Итак, строчные переменные и константы в Паскале описываются так же, как и любые
другие, например строка S: String означает что переменная S будет хранить некий набор
символов, строку (в количестве от 1 до 255).[1]
Соответственно, декларация S: String [100] в блоке переменных обозначает, что
переменная может хранить в себе последовательность элементов до 100 символов
включительно. Декларировать количество символов может быть удобно, когда мы работаем
с формализованными данными, например, с серией и номером документа с определенным
числом символов. Но при этом следует учесть следующее: при попытке присвоения такой
переменной более длинного ряда символов, не вошедшие символы будут «обрублены».
Например, описав переменную: S: String [8] следующая операция

даст в результате S=«Мама мыл» и соответственно, потерю оставшихся символов.


Также, если в одной процедуре входные или выходные переменные отличались
по своему числу символов от переменных в другой процедуре или функции, компилятор
вернет ошибку и укажет на разность типов переменных. В таком случае нам потребуется,
чтобы число декларированных в переменных символов совпадало и не превышало 255. Если
последнее условие представляет затруднения, но представляет крайнюю необходимость,
помогут методы обработки длинных строк.

Длинные строки
В Паскале возможна работа с длинными строками,[2] длина которых определяется
не числовым значением первого байта строки, а замыкающим символом «#0». Ограничение
в них определяется лишь объемом оперативной памяти или ее схемой адресации.
Максимально возможная строка в таком случае ограничена числом в 65 535 символов; еще
такие строки называют ASCIIZ-строками.
Для создания длинных строк, перед описанием программы следует включить директиву
расширенных значений компилятора {X+}; так же следует включить и модуль Strings.
Сама строка описывается типом Pchar, который является символьным указателем
и отвечает за хранение массива символов Char.
На следующем примере показан вывод строки из массива 600 символов. Здесь LongS —
длинная строка, S-массив символов. В данном случае массив S поочередно заполняется
символами A и B в зависимости от нечетности (Odd=true) или четности значений счетчика
цикла i.
И
лл. 3. Пример обработки длинной строки в программе longstring.
Далее, производится операция присвоения значений массива S переменной LongS и ее
последний символ помечается символом завершения строки «#0».
Кроме того, мы можем и напрямую работать с массивами символов Char, как
со строками.
В модуле Strings описываются следующие операторы для обработки ASCIIZ-строк,
но мы перечислим кратко основные из них, поскольку в обычной практике они нам
не потребуются:
StrCopy (S1,S2): Pchar; — Копирует строку S2 в строку S1, возвращая указатель на S1.
StrLen (S1): Integer; — Возвращает длину строки.
StrCat (S1, S2): Pchar; — Объединяет строки S1 и S2, возвращая указатель на начало
строки.
StrECopy (S1, S2): Pchar; — так же объединяет строки S1 и S2, но возвращает указатель
на конец строки.
StrComp (S1, S2): Integer; — Сравнивает две строки и возвращает код 0 если строки
равны, положительное значение если S1> S2 и отрицательное значение если S1 меньше S2.
StrlComp (S1,S2: Pchar; L: Word): Pchar; — так же сравнивает строки, но не более числа
символов, указанного в L.
StrEnd (S): Pchar — Возвращает указатель на конец строки.
StrLCat (S1, S2: Pchar; L: Word): Pchar; — функция копирует строку S2 в конец строки
S1 с учетом ограничения на количество символов L.
Пример работы с массивом символов S, как с длинными строками:
И
лл. 4. Обработка массива S с помощью функций StrCopy и StrLen.
В данном случае, мы присваиваем массиву значение функцией StrCopy, а затем измеряем его
длину с помощью StrLen и выводим на экран.

И
лл. 5. Результат работы программы Longstring.
Из недостатков работы с длинными строками выделяются:
— относительно долгие операции конкатенации (объединения двух строк) и получения
числового значения их длины;
— отсутствие контроля за концом строки, (что может вызывать потери данных
и критические ошибки);
— невозможность использовать символ завершающего байта (#0) в качестве элемента
строки;
— громоздкость синтаксиса.
По этим причинам и ввиду особой специфики работы, — большее внимание мы уделим
операциям с обычными строками.

Функция поиска
Одной из базовых функций работы с переменными строкового типа является функция
поиска подстроки в строке POS (S,S2), указывающая на числовую позицию первого символа
подстроки.
Например, в случае
n — должна быть переменной целочисленного типа (Integer, Word или Longint) и в данном
случае получит значение 6 — позицию подстроки «мыла» в строке.
Функция Pos достаточно хороша во многих случаях, однако особенностью строчных
данных может быть и такой случай, когда подстрока встречается в строке несколько раз.
В таком случае функция Pos вернет первое попадание в подстроку.
Например, следующее выражение

вернет значение 2, хотя символ «а» встречается здесь несколько раз и верными могли быть
также значения 4, 9 и 12.

Копирование
Если нам требуется получить фрагмент текста, являющегося частью строки, можно
использовать функцию Copy (S,N1,N2); Здесь N1 определяет, с какого символа будет
производиться копирование, а N2 — число копируемых символов.
Например, действие

присвоит переменной S значение «мыла». Если мы изменим числовые значения, например,


на «11, 4» — в переменной S окажется слово «раму»; при «1, 4» — это будет «Мама»; а при
«6, 2» в переменной окажется слово «мы».
Также, одним из ключевых элементов работы с фрагментами текста является
функция Length (S), позволяющая определять длину строки, чтобы не выходить за ее рамки.
Например,

присвоит переменной n значение 14 — число символов, содержащихся в строке.[3]


Рассмотрим и возможности построения более сложных конструкций с символами.
Предположим, переменной S присвоено значение «Мама мыла раму»; но нам известно
только, что в ней находится три слова (длина которых неизвестна) и необходимо получить
первое слово из этой строки, отправив его в переменную S2. Это действие мы можем
выполнить так:
— ведь мы помним, что функция Pos находит первое совпадение подстроки, а в начале
строки пробела у нас нет. Так в S2 попадет слово «Мама».
Если же нам требуется скопировать текст, следующий за первым пробелом, эта
процедура будет выглядеть несколько сложнее:

Здесь, в качестве позиции для отсчета мы берем место нахождения в строке первого пробела
и копируем следующие за ним символы за минусом числа символов, следующих до пробела
включительно. Проверить верность этой формулы можно в следующей программе:

И
лл. 6. Копирование фрагмента строки с помощью функций Copy и Pos, с целью получения
части текста, следующего за первым словом в строке.
Результат — можно увидеть на экране:
И
лл. 7. Результат работы программы копирования фрагмента текста.
Также, предположим, что нам необходимо скопировать последнее слово из строки. В данном
случае, поскольку функция «Pos» нам не поможет, придется воспользоваться циклом, чтобы
«вручную» установить место нахождения последнего пробела.
Контролировать конкретный символ строки можно, используя числовое значение
индекса символа в строке, при этом числовой индекс указывается в квадратных скобках
S [n].
Так, в упомянутой строке S [1] =«М», S [2] =«а», s [3] =«м» и т. д. Зная общее число
символов с помощью функции length (S) мы можем перебором достигнуть нужного нам
символа в цикле и после произвести нужную операцию. В следующей программе мы
получаем последнее слово, благодаря перебору символов с «хвоста», уменьшая значение,
полученное из длины строки оператором Dec (i). Так же, на всякий случай мы уточняем
условие выхода из цикла в случае, если пробел так и не будет достигнут (i <1).

И
лл. 8. Копирование последнего слова из фрагмента текста с использованием цикла Repeat
и строкового индекса.
Результат удовлетворяет ожиданиям.

И
лл. 9. Итог работы программы (илл. 8).
Почему же в примерах мы использовали английскую транскрипцию? Очень просто, —
поскольку по умолчанию в компиляторе TMT Pascal используется кодировка Win, и та же
программа с русским предложением внутри даст непонятный итог:

И
лл.10. Пример неудачного использования программы по работе с текстом, — из-за
несовпадения кодировок ввода (Win) и вывода (DOS) удовлетворительный результат
не может быть получен.
Так он будет выглядеть, несмотря на то, что формальных ошибок мы не допускали:
И
лл. 11. Так выглядит фиаско при несовпадении кодировок.
И это ничто иное как слово «раму», не переведенное в Dos-кодировку.
Похожий, «никакой» результат мы получим, если, например, напишем символы «а»
в строке в английской раскладке, а предложение — на русском; тогда функция Pos из поиска
вернет значение отсутствия символа (0), хотя визуально нам кажется, что никакого различия
в написании нет.
Эти проблемы открывают целый пласт операционных задач, связанных с кодировками.

Кодировки
Ввод данных в стандартном окне программы DOS осуществляется в кодировке DOS ASCII.
Также и данные, которые в нем отображаются, имеют кодировку DOS.
В случае, если нам требуется обрабатывать данные из какого-либо внешнего источника,
например из приложения «Блокнот», скорее всего, потребуется перекодирование
из Win-кодировки. «Скорее всего» поскольку символы цифр, пробелов, пунктуации
и английских букв имеют одинаковые адресные значения как в кодировке Win, так и в DOS;
но символы дополнительных языков, например кириллицы, имеют различные значения
в различных кодировках. Между тем если и вывод и ввод осуществляется в фоновом режиме,
и как исходные данные так и обрабатываемые находятся в одной кодировке,
перекодирование из одной кодировки в другую также может и не потребоваться. (Например,
в случае, когда мы принимаем в обработку данные, записанные в кодировке Win,
и записываем их часть в другой файл, имеющий ту же кодировку Win).
Для разбора кодировки символов нам понадобится следующая пара функций:
CHR (x) — указывает на символ с числом X из символьной таблицы (это можно сделать
и служебным обозначением «#x», например K:=#32, — в данном случае, значение k будет
равно пробелу, символу с кодом «32» в соответствии с таблицей символов ASCII).
ORD (k) — возвращает код символа K из символьной таблицы.
Здесь, K имеет тип Char (символ). Операции с символами схожи с операциями
со строковым типом, например к переменной строчного типа мы можем добавить символ:
S:=S+K;
Здесь, если содержимое S=«Мама мыла раму», а K=«c», мы получим значение S=«Мама
мыла рамуc»;

Значения таблицы символов по величине равны одному байту, следовательно, они могут
принимать численные значения в диапазоне от 0 до 255.
Чтобы вывести стандартную таблицу символов, нам понадобится следующая
программа:
И
лл. 12. Программа для вывода таблицы символов ASCII DOS.
Мы несколько усложнили ее для того, чтобы получить ровную таблицу: здесь мы выделили
код символа другим цветом, и добавили символы: «0» к двузначным и «00» однозначным
числам.
Так мы выводим значения таблицы символов ASCII в DOS-кодировке, кроме
управляющих символов с кодами «11» («vertical tab»/ «вертикальная табуляция»), «12»
(«form feed»/ «смена страницы») и «13» («Enter»). Также был «испорчен» управляющий
символ «8», равнозначный команде удаления предыдущего символа с клавишей
«Backspace».[4]

И
лл. 13. Результат вывода таблицы символов в программе Tabsym.
Здесь, символы с кодами до 32 являются служебными.
Кстати, из управляющих символов в будущем нам могут понадобиться:
«Тab» — #9
«Enter» — #13
и возможно, «Esc» — #27.
Несмотря на то, что они не имеют явного представления в виде конкретного
обозначения, но они так же записываются в тексте, как и все остальные. То есть, взглянув
на строку мы не увидим что там есть символ с кодом «13» («Enter»), но при обработке этой
строки последним символом может оказаться символ с кодом «13». Это особенно важно
понимать при обработке предварительно сохраненных файлов.
Что в этой таблице является очевидным: мы можем выделить значения чисел
от 0 до 9 (коды 48—57); ряд символов пунктуации и специальных знаков (коды 33—47);
английские прописные (большие) буквы от A до Z (коды 65—90); английские строчные
(маленькие) буквы от a до z (коды 97—122); русские прописные (большие) буквы от А до Я
(коды 128—159); русские строчные (маленькие) буквы от а до я (коды 160—175, 224—239)
отдельно буквы Ё (240) и ё (241); и элементы псевдографики (коды 176—223).
Для простоты восприятия на рисунке ниже представлена нумерация кодов клавиш
стандартной клавиатуры «QWERTY».

И
лл.14. Стандартный набор кодов клавиатуры «Qwerty».
На следующем рисунке приведена базовая кодировка ASCII в двоичном, восьмеричном
и символьном коде без использования дополнительных языков.
И
лл. 15. Различные характеристики кодов ASCII-таблицы
символов.
Справка:
ASCII (англ. American standard code for information interchange), — название таблицы
кодировки, в которой распространённым печатным и непечатным символам сопоставлены
числовые коды. Таблица была разработана и стандартизована в США, в 1963 году.
Так или иначе, если в программе нужно использовать какой-то символ, например для
условия выхода из цикла, уточнить его нам поможет простая программа:
И
лл.16. Программа вывода кодов символов «по требованию» пользователя: код нажатой
клавиши будет отображаться на экране.
Здесь, Key — переменная символьного типа Char отвечает за нажатие клавиш
и последующий вывод кода символа на экран.
Строка «If keypressed=true» — «Если нажата клавиша», то переменной «key»
присваивается символ нажатой клавиши «readkey». Затем, мы выводим на экран значение
символа в таблице (функция ord) и сам символ (key).
Пример ее использования:
И
лл. 17. Программа сообщает коды нажатых пользователем клавиш.
Итак, мы разобрались с таблицей символов.
Теперь поговорим о перекодировке.
Как уже упоминалось, Win-кодировка текстового файла отличается от DOS-кодировки,
но она необходима для получения данных из открытых источников и удобства
представления данных.

Нормализация строк
Для перекодировки строки текста из кодировки Win в DOS нам потребуется следующая
процедура DecodeToDOS:
И
лл. 18. Процедура для декодирования строки из стандартной кодировки Win в DOS.
Соответственно, обратно из кодировки DOS мы можем «перегнать» текст в кодировку Win
(например, для записи в файл).
И
лл. 19. Процедура для декодирования строки из стандартной кодировки DOS
в кодировку Win.
Также, нам может потребоваться перекодирование не строки (из Win в DOS), а отдельного
символа, в этом случае мы используем процедуру DecodeToDOSC:
И
лл. 20. Преобразование из кодировки Win в кодировку Dos отдельного символа.
В программах использующих перекодировку символов мы использовали простой принцип
преобразования, обращаясь к числовым значениям переменных.
Далее, говоря об обработке строковых данных нам регулярно будет требоваться
процедура замены подстроки в строке, как приведенная ниже InsInString:
И
лл. 21. Замена подстроки в строке на нужный набор символов в процедуре InsInString
происходит благодаря несложной конструкции из функций Pos, Length и Copy.
Как она работает. Переменная i получает позицию нахождения подстроки S2 в строке S.
Если при этом позиция находится не на первом символе, в строку результата S4 копируется
фрагмент строки до указанной позиции (фрагмент Copy (S,1,i-1), к нему прибавляется
«слово» -замена S3, и оставшийся фрагмент текста за минусом уже полученного фрагмента
с учетом стоявшего ранее на этом месте слова (фрагмент Copy (s,i+length (s2),length (s)
-length (s2) -i+1)).
В операции замены первого слова есть небольшое различие — первым сразу становится
подстрока замены S3.
Предположим, в строке «Мама мыла раму» нам необходимо заменить слово «раму»
на «окно».
Замена производится в одно действие:

В данном случае переменная s2 получит измененную строку «Мама мыла окно». А в случае,
если искомая подстрока не будет найдена, переменная S4 вернет в программу исходную
строку S.
Но здесь необходимо учесть один момент. В случае, когда в текстовой строке
встречается несколько раз одно и то же заменяемое слово, (например, слово «быть» в строке
«быть или не быть»), процедуру следует повторить. Поскольку нам неизвестно, сколько раз
во фразе может встретиться слово (или символ, или группа символов), один, три раза или
100 раз, мы можем усовершенствовать процедуру для того, чтобы она заменяла их все до тех
пор, пока искомой подстроки в строке не останется. Здесь можно применить цикл Repeat
с условием выхода.
Видоизменим процедуру InsInString, добавив цикл.

И
лл. 22. Усовершенствованная процедура InInstring прекращает заменять подстроку только
тогда, когда заменять остается нечего.
Еще одним необходимым элементом нормализации текста является его преобразование
из строчного написания в заглавное для удобства последующего оперирования.[5]
То есть наша строка «Мама мыла раму» после обработки должна выглядеть как «МАМА
МЫЛА РАМУ», где все буквы являются прописными, большими.
Приведенная ниже процедура Getups преобразует строку таким образом, что все
символы, написанные строчными буквами становятся прописными, а все прочие символы —
копирует в той же позиции. Для этого процедура, которая работает со строкой использует
другую процедуру, (Getup), которая производит ту же операцию, но на уровне 1 символа.
Илл. 23.
Процедуры «поднятия» букв из строчных в прописные GetUps (для строк) и GetUp (для
отдельного символа).
Ознакомившись с ними вы можете сделать вывод о принципе их работы. Чтобы не заменять
все буквы по одной, процедура GetUp работает с диапазонами кодировок символов, меняя их
нужным образом. В данном случае это уже упомянутые диапазоны кодировки DOS:
английские строчные буквы от a до z (коды 97—122) и русские строчные буквы от а до я
(коды 160—175, 224—239). Определив «попадание» в строчную кодировку мы уже знаем,
в какую «сторону» и на какое число следует изменить код, вычесть или прибавить.
В частности, для изменения английских строчных символов из кода символа вычитается
число 32; а в русских, — до буквы «п» также вычитается 32, с буквы «р» — вычитается 80.

Поскольку процедура Getups изначально готовилась как процедура нормализации,


по своему опыту в ней сразу использовались и дополнительные подготовительные элементы
как вложенная процедура Deldbspace — удаления двойных и тройных пробелов, а также
пробелов, стоящих перед началом и в конце строки:

И
лл.24. Процедура «очистки» строки от двойных-тройных пробелов, а также пробелов
в начале и в конце строки.
Теперь постараемся подытожить то, что мы получили.
С помощью описанных процедур мы можем нормализовать текст, используя буквально
несколько операторов.
Вернемся к нашей проблеме с кодировкой, но теперь будем во всеоружии:

И
лл. 25. Обработка ненормализованной строки из кодировки Win, которая содержит лишние
пробелы.
Здесь исходная строка написана в кодировке Win и содержит лишние пробелы. Мы
перекодируем ее в кодировку DOS, с помощью процедуры Decodetodos, переводим
в верхний регистр (и убираем лишние пробелы) с помощью процедуры Getups, и получаем
последнее слово строки «раму».

И
лл. 26. Нормализация данных привела к требуемому результату, нужному слову в нужном
написании.
Следует упомянуть еще о нескольких базовых процедурах работы со строками в Паскале.

Преобразования строк
Str (N, S); — преобразует число N в строку S.
Иногда это требуется для операций над числовыми данными, например, для
преобразования даты и времени в наборы символов строкового типа. Дело в том, что
в Паскале мы не можем смешивать данные разных типов, и для этого требуется привести их
к одному типу.
Для наглядности, рассмотрим процедуру, которая генерирует строку информации
о завтрашней дате в читаемом формате. Результат должен выглядеть, допустим,
так: «1 марта 2019 года». Все что у нас есть, это информация о дате сегодняшней,
полученной посредством оператора GetDate. Эта информация кажется банальной, но в ней
мы должны учесть в случае необходимости, содержит ли текущий месяц 30 или 31 день.
Также стоит знать, является ли год високосным, если сегодня 28 февраля; стало быть
завтрашний день может быть как первым днем календарной весны, так и 29 февраля. Как
осуществить этот выбор?
Оператор Str здесь используется дважды в конце: для преобразования числа года и дня
и последующей их конкатенации (иначе говоря, объединения) в одной строке.

И
лл. 27. Листинг процедуры Gettomorrow, получающей точную завтрашнюю дату в формате
строки.
Что происходит? В качестве выходной переменной процедуры мы указали единственную
переменную S, в которую будет необходимо отправить результат — строку с датой. Далее,
внутренними переменными мы описали Year (год), Month (месяц), Day (день) и Day_of_week
(день недели); а также их строковые версии: Years, Months, Days. (Поскольку день недели
в данном случае нам не интересен, мы не будем заниматься его описанием
и преобразованием).
Первоначально, получив из операционной системы информацию о дате в формате чисел
«GetDate (year, month, day, day_of_week)», мы прибавляем к числовому значению дня
единицу «Inc (day)», и смотрим, что из этого получится.
В операторе сравнения с перечислением «Case» мы выбираем варианты сценариев.
В месяце однозначно не может быть 32 дня, поэтому сталкиваясь с этим числом, мы
присваиваем переменной дня единицу и увеличиваем значение месяца на единицу. Но если
на дворе был декабрь? Мы помним об этом, и если это так (числовое значение
месяца «Month» превратилось в 13), то прибавляем к году единицу «Inc (year)», если сегодня
31 декабря.
Но как мы помним — 31-ый день бывает не в каждом месяце; поэтому мы включаем
в исключения и 31-ые числа ноября, сентября, июня и апреля, — если таковые получились,
то значение месяца «Month» так же увеличиваем на единицу, а значению дня
«Day» присваиваем 1.
Число 30 невозможно даже после крайне редкого дня «29 февраля», поэтому мы
предусматриваем и его в виде исключения.
И наконец, 29 февраля бывает не в каждом месяце. Поэтому если мы встречаем такой
вариант, нам необходимо уточнить, является ли год високосным или нет.
Точное определение високосного года звучит так:
«Год високосный, если он делится на четыре без остатка, но если он делится
на 100 без остатка, это не високосный год. Однако, если он делится без остатка на 400,
это високосный год.»
То есть, в данном случае, если мы видим попадание в одно из условий, когда год
не делится на 4 без остатка, либо когда делится на 100, но не делится на 400, то считаем этот
год обычным и следующим днем считается 1 марта.
Затем мы присваиваем в очередном блоке сравнений case значение месяцев в нужном
нам склонении: «января», «февраля» и так далее. И наконец, в результате преобразований
числовых данных в строковые, получаем итоговый, нужный результат.

Теперь мы рассмотрим обратную процедуру Val (S, N, R), где происходит


преобразование S — строки, в N — число, с сообщении об ошибке (или ее отсутствие) в R.
Ниже приведен фрагмент программы в которой число, записанное в строковой
переменной S преобразуется в N. Результат операции R при этом сообщит нам, есть ли
в преобразовании ошибка (код R <> 0) или ошибка отсутствует (R=0).

И
лл. 28. Пример использования процедуры преобразования строки S в число N с результатом
преобразования R, с помощью процедуры Val.
Теперь мы рассмотрим процедуру для преобразования фрагмента текста с использованием
дополнительной информации. Предположим, мы имеем текст статьи, который необходимо
дополнить некоторыми строковыми данными. В статье может встретиться употребление
информации о процентах, которое мы должны расширить, например, «95%» заменить
на фразу «почти все (95%)». Также при встрече дробного процентного показателя, процедура
должна округлить его, например «19,2%» употребить «менее пятой части (19%)».
Вариативность такого «очеловечивания» процентных показателей может быть достаточно
широкой (в приведенном примере, до 24 вариантов).
Что нам потребуется для упрощения этой задачи. Во-первых, это функция определения
символов цифр Trycifra.

И
лл. 29. Функция trycifra проверяет символ на принадлежность к цифрам от 0 до 9.
Во-вторых, это уже описанная ранее процедура InsInString. И в-третьих, это файл, «DictPer.
txt», который необходимо сохранить в рабочем каталоге программы (по умолчанию это
C:/TP/BIN). Он будет содержать числовые диапазоны значений и их описания (кодировка
Win). Приведем его содержимое полностью:
«0
3
незначительный процент
3
5
менее двадцатой части
5
8
чуть более двадцатой части
8
10
менее десятой части
10
15
более чем десятая часть
15
16
менее шестой части
16
19
менее пятой части
19
21
пятая часть
21
25
больше пятой части
25
25
четверть
26
27
более чем четверть
27
30
почти третья часть
30
40
более чем третья часть
40
50
менее половины
50
58
более половины
59
65
около двух третей
65
75
почти три четверти
75
77
три четверти
77
80
почти четыре пятых
80
82
четыре пятых
82
92
подавляющее большинство
92
100
почти все
100
100
все
100
10000000
более 100%»
Теперь приступим к сборке и рассмотрим происходящее подробнее.
В процедуре нам потребовалось много строковых переменных для текущих операций
(S-S8), две переменные для хранения диапазона (N2 и N3), одна — для текущего показателя
(N типа Real), одна — символьного типа (C), одна переменная для связи файла (F типа Text),
и две — логического типа (Boolean) для контроля над текущим состоянием операции (b
и tryfalse).

И
лл.30. Процедура LogicPercent, дополняющая числовые данные процентов различными
фразеологизмами.
На вход в процедуру мы имеем строку S, к обработке которой приступаем в случае
нахождения в ней символа «%». В цикле меняется значение текущего символа S [i], и если
мы встречаем обычные буквы или иные символы, то устанавливаем текущее значение
tryfalse=true.
Если же нам встречается число или символы дроби, то мы храним его в переменной S3,
поскольку оно может оказаться, а может и не оказаться процентом. Логический указатель
числа («нужного» символа) устанавливаем на B=true, и отменяем значение «ненужного»
символа TryFalse=false. Также мы дублируем это значение в переменной S8.
Встретив символ процента, цикл завершается. Мы преобразуем значение строковой
переменной S3 в число N. Результат преобразования j мы игнорируем, поскольку
контролировали код символов и уверены в числовом содержимом переменной. Поэтому
используем в дальнейшем j как хранилище для округленного значения N (Round (N)).
Затем мы открываем файл словаря значений DictPer. txt, читаем его по 3 строки сразу,
причем первые два «читаем» как числа (N2 и N3) с которыми сравниваем текущее число
значения j. Если число j попадает в промежуток между указанными числами, нами
используется символьное выражение из файла s6, которое мы не забываем переводить
в кодировку DOS (процедура decodetodos).
Теперь протестируем готовую процедуру в следующей программе.

И
лл. 31. Программа для тестирования процедуры
LogicPercent.
Илл.
32. Пример работы процедуры LogicPercent.
По такому принципу можно обрабатывать большие массивы текста, добиваясь, к примеру,
увеличения его уникальности.

Сложное сравнение
Предположим что нам необходимо выбрать из десятка слов два, наиболее похожих. Но что,
если все они разные и простое сравнение не работает? Если самыми похожими окажутся,
например, «ковровая» и «ковровый»? «Хлебный» и «хлебо-булочный»? «Эволюция»
и «конституция»? В данных случаях поможет функция сложного сравнения сходства.
Для начала поговорим о стратегии алгоритма. Мы могли бы здесь посчитать простое
количество попаданий букв одной строки в другую, однако это исключает вероятность
оценки сходства суффиксов и окончаний слов, как в последнем нашем примере
с «эволюцией» и «конституцией». Судите сами.

эволюция
конституция

Если мы начнем перебирать индексы букв этих слов с «головы», сравнивать их


последовательно [1, 2, 3, 4, 5…], то ни одного раза не получим совпадения:
э <> к, в <> о, о <> н, л <> c, ю <> т, ц <> и, и <> т, я <> у, «» <> ц, «» <> и, «» <> я.
Это плохо, поскольку для любого адекватного человека понятно, что слова похожи
окончанием « -ция».
Очевидно, что алгоритм должен быть несколько сложнее простого последовательного
перебора индекса для таких случаев.
Для решения этой проблемы, нам требуется провести комплексное сравнение. Мы
будем сравнивать не конкретные позиции, а нахождение фрагментов одного слова в другом
слове, меняя размер этих фрагментов от минимального к максимальному. То есть, сначала
мы будем искать наличие букв по одной (э, в, о, л…); затем буквенных пар (эв, во, ол, лю,
юц…); затем буквенных троек (эво, вол, олю, люц, юци, ция); четверок (эвол, волю, олюц,
люци, юция); пятерок (эволю, волюц, олюци, люция); шестерок (эволюц, волюци, олюция);
семерок (эволюци и волюция); и максимума — слова целиком (эволюция). Причем, чем
больший фрагмент определяется попаданием, тем большее количество баллов мы должны
присвоить за это попадание. Кроме того, нам следует учесть и разницу в длине строк.
Кстати, в данном случае, нам не принципиально соблюдение некой константы в виде
получения процента, нам важен результат, который может быть выражен некоторым
абстрактным числом баллов за количество попаданий и сравним его с другими результатами.
Программное решение этой процедуры может быть следующим.

И
лл. 33. Процедура сложного сравнения двух строк.
Что происходит: первоначально, мы присваиваем переменной оценки сравнения (P)
исходный балл (10 000), и оцениваем разность длины строк, за что также присваиваем
различный размер «шага» оценки (step). В зависимости от величины разницы длины слов (L
и L2) мы вычитаем эту разницу из первоначальной оценки (P). Затем происходит процесс
приведения обоих слов к одинаковым условиям, — мы считаем их равными по длине,
но если одно слово оказывается короче другого, то к нему присоединяется дополнительное
число пустых символов-пробелов (S4).
Далее, происходит процесс сравнения с использованием циклов, описанный выше.
И в завершении, мы вычитаем исходное количество баллов из полученной оценки.
В результате работы процедуры мы получаем оценку сходства слов «эволюция»
и «конституция» в 908 баллов. Если же в качестве первого слова выступит «рыба», или
«аргумент», оценка снизится до 0 баллов. Слово же «конституционный» поднимет оценку
до 8 880. Конечно, это абстрактное число, однако в рамках столь же абстрактных координат
оно дает стабильные сравнительные показатели сходства слов на естественном языке.
Но к сожалению, применять данную процедуру к крупным фрагментам текста
проблематично: разделители в виде пробелов в двух строках могут неоправданно повышать
показатели сходства. Мы могли бы конечно взять и заменить их на какие-либо другие
символы, но никто не гарантирует, что и эти символы не встретятся в тексте. Кроме того,
сравнение множества больших фрагментов текста будет сильно замедлять программу
и повышает вероятность «зависаний». Ввиду этого, самым адекватным решением может
быть специализация процедуры на сравнение одиночных слов.
Теперь следует определиться, что делать в таком случае с предложениями. Для начала
попробуем пилить их на слова и выводить в форме массива из отдельных слов. В таком виде
обработка больших фрагментов текста значительно упрощается.
А чем разделяются слова в предложениях? Правильно, пробелами и пунктуацией. Мы
приготовим универсальную процедуру, которая будет «распиливать» любое предложение
на набор слов и складывать их в массив для вывода. Стратегия здесь довольно простая, —
идти вдоль индекса предложения и используя маркер разделения (пробел) отделять
очередное слово. При этом, мы не станем сохранять пунктуацию, — ведь она «создает шум»:
в данном случае — это словарные конструкции, которых нет. Ведь фактически для
программы слова «корова» и «корова,» будут двумя разными словами, разными наборами
символов. Это нас не устраивает. Поэтому, помня о том, что нам еще следует обработать
пунктуацию, выделим исключительно все слова в предложении. Так может выглядеть эта
процедура:
И
лл. 34. Процедура Justbreak «распиливает» предложение на отдельные слова и сохраняет его
в массив с числом элементов j.
В процедуре Justbreak происходит обработка предложения, поступившего в переменную S
в двух циклах Repeat. В ней, индекс слова будет контролировать переменная j, а индекс
последовательного символа в предложении — переменная i. Первый цикл присваивает новое
значение счетчику индекса слова командой inc (j). Условием выхода из цикла, сохраняющего
слово, будет символ пробела, запятой, двоеточия, точки или превышение индекса i длины
строки предложения. Внутри этого цикла мы добавляем очередной символ к текущему
слову, если он соответствует условиям — не равен знаку пунктуации или пробелу. Кто-то
может возмутиться, ведь процедура разбивает некоторые составные слова, вроде «кто-то»,
«как-то», «как-нибудь» и т. д. Но в данном случае мы все же отделим «мух от котлет» —
выделим составные конструкции как слова по отдельности, но запомним, в какой
конструкции пунктуации они находились.

Модель пунктуации
Перейдем к процедуре сохранения пунктуации. Конечно же, она нам очень пригодится. Она
очень проста.
И
лл. 35. Выделение модели пунктуации из предложения.
Здесь мы берем исходное предложение и (на всякий случай) предварительно исправляем
наиболее распространенные ошибки: наличие пробела перед символами пунктуации,
с помощью ранее описанной процедуры insinstring. Далее поработаем с элементами массива
signs, в котором будем хранить символы пунктуации на время обработки.
Здесь мы начинаем «путешествие» по индексу входного предложения, отмечая каждое
слово символом пробела или символом пунктуации, если он есть. Кроме того, мы выделяем
весь полученный блок служебными символами «^».
В результате, на строку «Антошка — плохой, нехороший.» мы получим следующую
картинку пунктуации « ^-,.^». Что же, теперь мы можем рассматривать любое предложение
как набор «чистых» слов и модель пунктуации, к нему прилагающуюся.
Теперь вновь вернемся к задаче, в которой требовалось выделить и обнаружить пару
наиболее схожих слов в предложении.
Мы можем использовать следующий алгоритм:
1. Разбить слова в предложении на массив с помощью процедуры justbreak с числом
элементов j.
2. Сравним каждое слово массива с каждым и если полученное значение является
максимальным, то сохраним его, как ответ. Для этого нам потребуется два цикла и правило,
по которому одно и то же слово мы не будем сравнивать с самим собой.

Используя этот нехитрый метод, мы можем получить своего рода игру, в которой
программа будет искать слова, близкие по написанию и выбирать их, как на следующем
примере:
И
лл. 36. Тест игры в слова, где из ряда слов, введенных пользователем компьютер выбирает
два, наиболее похожих по написанию.
Как видно, программа действует, отсекая символы пунктуации и преобразуя ряд слов
из одной строковой переменной в массив слов, а также приводит каждое слово в верхний
регистр. Теперь рассмотрим программу, которая осуществляет эти действия.
И
лл. 37. Программа «Игры в слова» с компьютером, где из предложенных пользователем слов
программа выбирает два наиболее похожих по написанию.
Итак, что мы здесь видим. В первую очередь, это набор строковых переменных (s, s2, s3),
которые нужны для обмена данными между процедурами нормализации (decodetodos, getups)
и ввода строки пользователем. Также, здесь используются переменные для работы циклов
(i и n), для индексирования конца массива sm (j), для определения максимума (max)
и текущего состояния баллов (ball). Кроме того — переменные для хранения лучших
позиций двух слов (max1) и (max2) в массиве (sm). Массив требуется нам в качестве
выходной переменной для использования в описанной выше процедуре justbreak, поэтому
мы не производим иных действий с его элементами (по очистке, заполнению пустыми
символами и др.), поскольку эти действия уже прописаны в самой процедуре justbreak.
Весь алгоритм кроме исходных функций очистки мы поместили в цикл Repeat
с отсутствием условия выхода (Until false) для того, чтобы вопросы и ответы повторялись
при желании пользователя бесконечно.
После нормализации (декодирования) приветственной фразы «Введите ряд слов,
в котором следует найти похожие по написанию» и выведении ее на экран, от пользователя
получается строка S, в которой он написал ряд слов. Эту строку мы разбиваем процедурой
justbreak на массив слов sm с известным числом элементов j, после чего в двух циклах
последовательно сравниваем (с помощью percentcheck2) различные элементы массива друг
с другом, если речь не идет об одном и том же элементе (i <> n). Если текущий максимум
Max оказывается ниже текущей оценки Ball, мы передаем число Ball в Max, и запоминаем
позиции I и N, сохраняя их в переменные max1 и max2 соответственно. После окончания
циклов сравнения мы выводим результат из массива sm с индексами max1 и max2 и ждем
следующее задание.
Эта игра может быть усовершенствована. Например, в роли задающего вопрос
и генерирующего слова мы можем поставить программу, а человек будет их угадывать.
Но для этого нам уже потребуется работа со словарями, чем мы и займемся позже.

Шаблоны поиска
Еще одну интересную функцию можно считать очень полезной при обработке строковых
данных. Она незаменима для анализа, а точнее, парсинга по значительным объемам текста.
Предположим, перед нами — достаточно монотонный текст, состоящий из букв,
пунктуации и пробелов. Это может быть html -страница текста, полная рекламы, модулей
и ссылок; но небольшая часть этого текста носит важный для нас смысл. Мы хотели бы
разметить этот фрагмент текста какими-либо жесткими правилами, однако это невозможно.
На начало нужного фрагмента в тексте указывают лишь косвенные признаки, — например,
наличие даты, времени публикации и имени автора в следующем формате: «12.08.2018 01:20,
АНАТОЛИЙ ИВАНОВ». Строка перед ним — содержит только название статьи, а после
и до него — ряды случайных символов.
Эти данные — всегда разные, но формат их записи всегда один. Как нам прочитать их
в случайном месте текста?
В этом случае мы используем технологию шаблона. Под шаблоном здесь понимается
последовательное использование какого-либо ряда символов (точек, букв, чисел, дефисов
и т.п.), которое заранее может быть известно, однако его расположение в строке может быть
различным: этот ряд символов может находиться где угодно.
В чем состоит идея:
1. «Прочитать» строку текста, размечая встреченные группы символов одной
из нескольких меток. Например, все буквы русского алфавита мы можем пометить «0»,
пунктуацию — «1», числа — «2», английские буквы — «3», символьные команды
и псевдографику «4» и «5», а пробелы — «6». (Согласно этой схеме, упомянутый выше
шаблон без имени автора мы могли бы записать как последовательность
«22122122226221221»).
2. В «клоне» строки, размеченной полученным кодом мы находим искомый шаблон.
3. Поскольку длина клонированной строки и исходной не отличается, указание
на позицию шаблона укажет на позицию первого нужного нам символа в исходной строке
и общее количество символов.
И
лл. 38. Функция Shablon — определяет наличие в строке шаблона поиска, и возвращает
подстроку s2 с указанным в шаблоне фрагментом текста.
Как видно, функция довольно проста, но здесь были использованы некоторые жизненные
«лайфхаки». Поскольку бывает довольно сложно проконтролировать всю палитру
диапазонов таблицы символов, здесь введена дополнительная переменная логического типа
«plus», которая содержит информацию, об использовании очередного символа из строки
в шаблоне. Если мы пропустили какой-то символ (if plus=false) после проверки всех
полезных для нас вариантов, тогда мы добавляем символ кода «5» в S3 (там может оказаться
псевдографика, командные символы и т.п.). В таком случае длина строки, содержащая код
шаблона S3 не будет отличаться от исходной S. Также, для того, чтобы каждый раз
не проверять код текущего символа из исходника S, мы присвоили его значение переменной
j, что ускоряет время исполнения.
По окончании кодирования строки, мы выполняем поиск подстроки SS в полученной
строке S3, и копируем фрагмент из реальной строки S с позиции строки полученного
шаблона S3 и с длиной подстроки шаблона SS. Фрагмент «S2:=copy (s, pos (ss, s3), length
(ss));»
Проверим корректность процедуры:

И
лл. 39. Проверка функции shablon в программе.
И вот результат:

И
лл. 40. Результат работы программы с использованием функции shablon.
Функция шаблона с различными модификациями незаменима для парсинга
неформализованных данных. К примеру, она подходит для поиска даты рождения, номеров
телефонов, домашних адресов, номеров документов, временных периодов трудового стажа
и других сведений из текстовых файлов резюме, которые впоследствии могут быть внесены
в стандартную форму и нужным образом исправлены.
Но предположим, что пользователь написал дату рождения с лишним пробелом.
Например так, 02.12. 1962. Как можно предположить подобную ситуацию и исправить ее
автоматически?
Конечно же, во-первых, нам следует убедиться, что имелась ввиду именно дата
рождения а не период работы или дата составления резюме. На это могут указывать
сопутствующие данные: фрагменты слов в строке с «род», «рожд», «г.р» или «д.р».
Убедившись, мы используем ту же функцию shablon, но с некоторой модификацией, которая
может получать числовую информацию, игнорируя степень разреженности между
числовыми символами.
Так, функция clearshablon в случае необходимости игнорирует наличие или отсутствие
в строке дополнительных пробелов, благодаря нескольким операторам, добавленным
в функцию shablon и пользуясь описанной выше процедурой insinstring.
И
лл. 41. Функция clearshablon — осуществляет поиск шаблона и в случае неудачи пытается
улучшить результат, игнорируя символы пробелов.
В итоге, при обработке строки «02.12. 1962» с использованием шаблона, не включающего
пробел 2212212222 функция сlearshablon вернет результат «02.12.1962» без лишнего пробела,
благодаря синхронным усилиям процедуры insinstring, устранившим все пробелы из строк
как в коде-шаблоне, так и в исходной строке.

Разреженный текст
К разреженному тексту разработчики обычно относятся скептически; мол, явление это
редкое и тратить усилия на то, чтобы его распознавать — бессмысленно. Но если исходить
из анализа данных современных резюме, рефератов и сочинений, окажется, что почти
в каждом двадцатом из них встречаются одна-две строки разреженного текста. Неужели
строку типа «И в а н о в И в а н И в а н о в и ч» придется упустить? Быть может вы никогда
не столкнетесь с разреженным текстом, но сам по себе вопрос весьма интересен.
Посмотрим, как эту проблему можно решить средствами Паскаля.
1. Во-первых, нам следует определить некоторые признаки разреженности. (Одинарная,
двойная, тройная или четверная цикличность символов пробела, чередующаяся с символами
единичных букв).
2. Во-вторых, следует определить длину этой регулярной цикличности (поскольку число
пробелов после первого слова делается увеличенным, а значит, нерегулярным).
3. В-третьих следует обработать полученный фрагмент и проверить остаток текста
на наличие признаков разреженности.
А поможет нам в этом — описанная выше функция shablon и insinstring. Как? Смотрим
подробно код функции findras.

И
лл. 42. Функция FindRas находит и нормализует разреженный текст в строке.
Здесь мы используем массив из четырех видов строковых констант ST, в которых храним
«заготовки» для шаблона, описывающие минимальные фрагменты содержания четырех
видов разреженности. (Здесь: «6» означает пробел, «0» — букву русского языка, и требуемые
нам последовательности мы кодируем «60», «660», «6660» и «66660»). Почему их только 4?
Логично предположить что разреженность формата «пять пробелов один символ» едва ли
встречается в практике.
Далее, мы начинаем работать в трех циклах, главный из которых, цикл Repeat, имеет
условием выхода отсутствие вариантов признаков разреженности в тексте (здесь мы считаем
таким признаком отсутствие 3-х порядков последовательности одного из четырех вариантов
разреженности. То есть, если «shablon» отвечает «true» на последовательность 606060 значит
имеет место вариант разреженности с одним пробелом (Step=1) и следует его отработать).[6]
Далее, получив вариант разреженности (if step <> 0) мы попадаем в цикл, измеряющий
длину встреченной регулярности. В ней мы увеличиваем значение s3 на дополнительный
шаг регулярности, в случае удачи запоминаем его в переменной S5 и выходим из цикла,
когда терпим неудачу (пустой возврат s4). Далее, с помощью Insinstring мы получаем
из регулярной последовательности S5 строку без пробелов S4 и заменяем в оригинале строки
S фрагмент S5 на фрагмент строки без пробелов S4 с дополнительным пробелом, складывая
все в переменную S6. Затем, заменяем содержимое исходника S на частично
отредактированное S6 в котором была произведена замена и повторяем весь цикл с начала.
После того как регулярности пробелов перестают встречаться в тексте (Step=0), остается
только удалить двойные пробелы из общего текста и наслаждаться корректным написанием
строки, отправленным в переменную S2.
Испытаем функцию на практике в программе:

И
лл. 43. Применение функции FindRas к строке с разреженным текстом.
Причем, как видно все слова в тексте имеют разную степень разреженности, (от 0 до 3-х
пробелов между буквами), что однако не мешает привести его к нормальному виду:

И
лл. 44. Результат обработки разреженной строки с помощью функции FindRas.

Выбор слов в блоке текста


Вы можете удивиться, но функции Pos на практике оказывается недостаточно для
определения наличия определенного слова в блоке текста. Судите сами, — предположим,
наше искомое слово «интеллект», а текст, в котором мы его ищем, содержит фразу
«интеллектуальные системы». Функция Pos укажет на наличие подстроки «интеллект»
в строке, но в реальности конкретное слово «интеллект» в данной фразе отсутствует; и если
мы изымем его из фразы, то получим бессмысленное выражение «уальные системы».
Получается, что выбор отдельных слов в предложении осложнен тем, что слово может
находиться в начале, в середине или в конце предложения; либо предложение может
состоять целиком из единственного слова. Их обработку необходимо ограничить двумя
правилами:
1. Начало слова определяется предшествующим символом пробела или пунктуации;
либо его буква является первой в предложении.
2. Конец слова определяется последующим символом пробела или пунктуации; либо его
последняя буква является последним символом в предложении.
Для поиска полноценного слова, (а не его фрагментов), мы будем использовать
функцию Tryfreew, которая будет возвращать значение true в случае действительного
нахождения слова в предложении и false — в случае его отсутствия.

И
лл. 45. Функция поиска отдельного слова или нескольких слов tryfreew в блоке текста.
Теперь можно считать, что мы рассмотрели основные функции, которые позволяют работать
со строками в широком диапазоне практических операций. Следующие главы расскажут
о том, как строковые данные могут стать разумнее.

[1] По существу, строка является массивом символьных переменных


типа Char, описываемого по умолчанию как содержимое [1..255], вызов к индексу которого
аналогичен операции с традиционным массивом (array). При этом, нулевой индекс [0]
содержит информацию о текущей длине массива символов.
[2] Методы, процедуры и функции обработки длинных строк и обычных в TMT Pascal
и в других языках программирования существенно отличаются, — с длинными строками
объективно работать сложнее и они имеют ряд критических недостатков. В дальнейшем
повествовании они не будут использоваться. Поэтому вы можете достаточно
безболезненно пропустить этот раздел, или только бегло с ним ознакомиться.
[3] Аналогом функции Length является и прямое обращение к нулевому индексу строки,
например L:=S [0]; — в данном случае числовой переменной L будет присвоено число
символов в строке.
[4] Вывод управляющих символов на экран равнозначен произведенному действию
в блоке текста.
[5] К сожалению, предусмотренная для таких операций функция Паскаля Upcase (k) (где
k — переменная символьного типа Char) работает практически всегда только
с англоязычными символами.
[6] Следует заметить, что функцию рекомендуется использовать с осторожностью,
поскольку например предложение « — А я и Марина пошли в кино» может вызвать ложный
положительный ответ и в результате мы получим «слипшуюся» кашу « — Аяи Марина…».
Если же мы увеличим число проверочных фрагментов в FindRas, то рискуем пропустить,
например, короткую фамилию из 3-х букв с разреженностью, например «К о х Дмитрий
Иванович». Здесь следует найти разумный консенсус: искать разреженные строки там, где
они могут быть: в заголовках, на титульных листах, в анкетных данных, в конце текста,
на сносках и т. д.

Глава 2. Использование модели многомерного множества

Принципы организации MSM


Предлагаем ознакомиться, а может быть и вспомнить, на чем строится технология MSM
и почему она оказывается эффективна в решении самых разнообразных задач.

Идея бесконечного символьного (строкового, строчного) множества или бесконечной


символьной последовательности не описывалась и не применялась в какой-либо
технической или иной литературе, поэтому следует детальнее сосредоточиться на этой идее.
В идеале, как мысленный эксперимент, она состоит в следующем:
Предположим, что мы имеем бесконечную последовательность отличающихся друг
от друга символов и имеем бесконечную память, для того, чтобы хранить знание об этой
последовательности. В данной ситуации нам нет необходимости совершать позиционный
перенос для организации счетных операций и нет необходимости использовать цикличное
(ограниченное) количество символов, — в таком случае нам будет достаточно использовать
один символ для обозначения любого конкретного числа в любой системе счисления.
Однако, для отображения нескольких категорий значений, мы можем
использовать последовательности классов. То есть, добавив одну категорию класса, мы
прибавляем следующий символ, давая понять, что мы обозначили следующий класс
значений, и так далее.
Так, например, в системе бесконечного символьного множества любой номерной знак
автомобиля, состоящий из трех категорий классов обозначений (серия, регион и числовой
номер), может быть записан тремя символами.
Аналогично, серия и номер паспорта — может описываться двумя символами, или
тремя — если нам также важно выделить и регион его происхождения.
Номер телефона — обозначается двумя символами (если мы хотим категоризировать
только страну и номер абонента), тремя символами — если для нас важно выделить код
страны, код города и номер абонента, и четырьмя символами — если хотим выделить
дополнительно к последнему варианту и код оператора связи.
Можно пофантазировать еще немного. Если бы мы могли существовать в таком мире,
хранить и передавать информацию в столь странной символьной системе, вероятно, наши
часы могли бы показывать время с использованием единственного символа (который
содержал бы информацию о числе истекших секунд с начала большого взрыва), или три
символа — если бы мы хотели категоризировать часы, минуты и секунды с этого момента
или любого другого, принятого в современной истории.
И более того, мы могли бы договориться, что символьная последовательность
с определенного числа становится хранителем имен или других символьных
последовательностей.
Так, мы могли бы носить имена, включающие всего три символа (три категории
классов) — например, обозначающие фамилию, имя и отчество. Допустим, «FP^»
обозначало бы «Иванов Иван Иванович»…

И
лл. 46. Фрагмент последовательности из 2042 иероглифов японской письменности Кандзи
мог бы оказаться лишь каплей в море бесконечной символьной последовательности.
И вот, мы подходим к самому главному. Мы могли бы записывать слова, используя
на каждое — по одному символу; также, мы могли бы их категоризировать, отделяя символы
позиционно друг от друга в каждом таком «слове». Но позиционное смещение мы могли бы
использовать и как обозначение преемственности одного слова к другому.
Поскольку слова имеют свойства группироваться, обобщаясь с неким общим родителем,
логично предположить, что все возможные группы слов-родителей мы можем заключить
в достаточно небольшой последовательности позиционной записи этих наборов символов.
Таким образом, каждое слово будет иметь первым символом единого предка, но отделение
каждой позиции будет обозначать следующий уровень перехода.
Мы не существуем в таком идеальном мире. Однако, нам, быть может, окажется
достаточным количества символов, предлагаемых современными системами для подобного
эксперимента?
В таблице ASCII — 256 символов; и если мы будем использовать переход позиции
родства достаточно часто, вполне может оказаться, что нам будет достаточно и этой
последовательности для фиксации не арифметических, но смысловых операций. И здесь
наступает магический момент — оказывается, что любое слово или понятие естественного
языка мы можем угадать с помощью форм обобщения за количество попыток от 1 до 22. Это
означает, что наш классификатор с достаточной степенью детализации будет использовать
последовательности от 1 до 22 символов бесконечного символьного (строчного) множества.
На основе этой идеи и родилась концепция многомерного строчного множества,
единого классификатора для всех понятий естественного языка, а также для обозначения
комплекса операций по работе с ним. Чем она удобна? А чем удобен позиционный перенос
в арабской десятичной арифметической системе? Идея переноса десятков и сотен оказалась
прорывом в математике и привела к существенному упрощению арифметических операций.
Можно предположить, что подобная организация строковых данных может быть довольно
прогрессивной.
Итак, многомерное строчное (строковое) множество получает свое название
от принципа организации классификатора, действующего на основе трех простых правил.
1. Все элементы классификатора являются потомками прародителя, имеющего код A.
2. Каждый первый потомок родителя получает в наследство код родителя
с дополнением символа A.
3. Каждый следующий потомок родителя получает в наследство код родителя
с дополнением следующего по порядку свободного символа (В, С, D и т.д.) По завершении
буквенного ряда (после символа «z»), следующий символ получается из кода действующей
символьной таблицы.[1]

Р
ис. 47. Принцип классифицирования MSM на простом объекте «Кошка».
Таким образом, мы получаем классификатор, в котором стараемся достигнуть максимальной
разветвленности элементов, различая на каждом новом уровне усиление определенных
признаков, где каждый конечный «пункт назначения» может стать родителем следующего,
и так до бесконечности.[2]
При классификации мы также стараемся придерживаться того принципа, что более
общее определение становится родителем более узкого понятия. Так конечные элементы
ветвей классов оказываются наиболее узкими определениями. Если в полной мере соблюдать
этот принцип невозможно, когда одно понятие может быть родителем другого и наоборот, то
мы записываем их интуитивно, в произвольном порядке.
В начале книги, на рисунке 2 был приведен только небольшой фрагмент ветвей
классификатора, поскольку его трехмерное изображение представляет ряд технических
трудностей.[3] Поэтому здесь и далее приводятся двумерные иллюстрации.
На показанном фрагменте слова и лексемы используются как самостоятельные,
полноценные формы объектов что видно в хвосте классификатора: «Туманный» является
частным случаем «Туманное», а «Туман» — один из случаев «Туманный».
В случае, когда одно слово имеет несколько значений, они описываются в разных ветках
с добавлением символа "|" для каждого нового значения. Так, например слово «Сладкий»
в буквальном значении вкуса описывается кодом AAAAAABABAAAABBA, а в значении
«Льстивый» — AAAAAAABABBAIQJFGAAE. (См. рис. 49).

Р
ис. 48. Пример классификации слова «Туман», где он получает кодировку AABBADAIEA.
Р
ис. 49. Представление двух значений одного понятия «Сладкий» в различных ветках
классификатора.
Но в чем разница, отличие от других классификаторов, спросите вы? И совершенно верно,
что сомневаетесь. Первое отличие — в количестве уровней детализации предков. «Среднее»
понятие в MSM состоит из 15—20 переходных элементов. Во-вторых, в MSM не существует
дискриминации предлогов, — слова «а», «не», «в», «и», «но» и т. п. — являются
полноценными носителями смысла, как и более длинные их родственники. И наконец, мы
достигаем эффекта комплементарности элементов, «бонуса» от бесконечной символьной
последовательности, которым мы легко пользуемся.
Алгоритмы записи и чтения данных MSM
С чего можно начать формирование собственного классификатора? Для самой простой
организации словаря нам потребуется создать и сохранить два файла, которые мы можем
назвать произвольно, допустим, «ALIK. txt» и «ALIK2.txt».[4] Почему два? Они будут
братьями-близнецами и содержать одинаковые сведения, однако будет удобнее если один
из них хранит данные в формате «наименование/код», а другой — «код/наименование». Нам
не следует создавать их пустыми, поэтому в каждом из них мы сделаем первые записи,
например, в первом: «ВСЕ А», а во втором «A ВСЕ». («A» в данном случае -английский
символ).
Далее, нам потребуется процедура, которая добавляет записи в эти словари. Схема
простая: она находит искомое слово и формирует код потомка, на основании кода родителя,
с добавлением следующего по порядку (начиная с «А»), свободного от потомков символа
к коду родителя. То есть, если мы имеем понятие «ABB» с потомками в словаре «ABBA»,
«ABBB» и «ABBC», то добавляя в него следующего потомка, он должен получить кодовое
имя «ABBD». Этот процесс организован в процедуре addnext, получающей в качестве
входных параметров наименование S и код родителя SC.

И
лл. 50. Процедура добавления в словари элемента S к родителю с кодом SC.
Здесь происходит следующее. Если длина слова составляет менее трех символов, его длина
увеличивается при помощи одного или двух символов «|».[5] (Так например, слово «да»
превратится в «да|», а предлог «и» в «и||»).
Далее происходит чтение содержимого файла «alik2.txt». Если встречается искомая
запись, нам следует уточнить, действительно ли она оказалась в строке с первого
символа (Pos (sc, sc2) =1 и является ли этот код потомком исходного кода (l2> l). На самом
деле здесь нас интересует только наличие потомков, поскольку в них мы можем
«подсмотреть» использованные символы. В переменной max мы сохраняем числовой код
прочитанного символа потомка. По завершении просмотра словаря формулируется
актуальное имя для записываемого понятия: если потомки нам встречались, то символ имени
потомка будет равным символу имени последнего потомка +1 (для «A» это будет «B», для
«Y» это будет «Z», для «Z» это будет «a» и т.д.); если же потомки не встретились, то
именем для записи станет код родителя + «A» (if max=0 then sc2:=sc+«A» else sc2:=sc+chr
(max+1)).
Затем остается только записать результат в файл, используя в качестве разделителя
символ пробела.
Мы разобрались, как добавлять одиночные элементы в классификатор, но тем не менее,
не разобрались с интерфейсом и самим процессом реализации. Что должно происходить
с алгоритмом программы, когда она получает команду типа «M это N»? Во-первых, нужно
проверить не находится ли сохраняемое слово уже в словаре и существует ли его родитель.
В зависимости от этого будут применяться различные стратегии. Во-вторых, для
оптимизации скорости «обучения» было бы интересно создавать сразу набор
дополнительных потомков из словоформ исходного слова. Но остановимся пока на первой
задаче, а ко второй вернемся немного позднее, поскольку она потребует использования
дополнительных словарей.
Следующая процедура — находит сохраненное понятие и возвращает его код.

И
лл. 51. Процедура findword находит в словаре alik2 сохраненное понятие S и возвращает его
код S2.
В данном случае используется поиск по файлу alik2.txt. Напомню, файл хранит записи
данных в формате «код /наименование», как например «AAAAAABAABACE
ТЕМА». Условием работы цикла является отсутствие указателя на конец файла (while not eof
(f)). Внутри цикла читается каждая строка и в случае совпадения входной переменной S c
наименованием из фрагмента строки S3, (начиная от пробела и до конца строки),
переменная S2 получает фрагмент строки с кодом наименования. После этого производится
выход из цикла оператором Break, — нам больше нет необходимости читать другие записи
словаря, поскольку он не содержит одинаковых наименований с разными кодами и каждое
из них уникально. Соответственно, быстрый выход в данном случае обеспечивает ускорение
работы программы.
Понятно, что нам не обойтись и без обратной операции чтения слова по коду. Она
действует аналогичным способом:

И
лл. 52. Процедура извлечения из словаря слова S2 по коду SC.
Что нам потребуется еще для формирования записей словарей в формате «N это M»?
Конечно же, следует проверить наличие в базе обоих понятий, и здесь есть три варианта
сценариев:

1. N отсутствует, M присутствует, -> записываем в словари.


2. M отсутствует, -> сообщаем об отсутствии понятия M.
3. N присутствует, M присутствует -> уточняем наличие указанного родства понятий:
— > если да, сообщаем «уже знаю»;
— > если нет, сообщаем об ошибке, известной связи и предлагаем сохранить
понятие N потомком M с дополнительным символом второго значения «|». С этим вполне
может справится процедура chatit, предназначенная для ввода определения и реакции на нее.
Описанная процедура (илл. 53) не слишком совершенна, прежде всего потому, что
использует в качестве входного элемента слова естественного языка. (В данном случае, это
слово «это», но в самом начале формирования словарей мы не может этого никак избежать).
Что происходит:
Строка принимает на вход задание в формате «М это N» (Readln (s)), поднимает строку
в верхний регистр (Getups (s,s2)), перекодирует строку в кодировку win (decodetowin (s2,s) —
для чтения словарей) и затем смотрит на содержимое. Если оно содержит слово « это»,
выделенное пробелами, то процедура приступает к анализу данных.
С помощью insinstring мы изымаем входное слово и у нас остается два слова:
определяемое и определитель, к которому первое «просится» в потомки. Предварительно мы
проверяем наличие в словарях кодов обоих слов с помощью findword и сохраняем
результаты в переменных sc (определяемого) и sc2 (определителя). Если определителя нет —
все остальное бессмысленно, — сообщаем об ошибке «Я не знаю слова…» (s3).
И
лл. 53. Процедура обработки запроса типа «M это N».
Идеальный случай — неизвестное определяемое и известный определитель, — тут мы сразу
сохраняем определяемое с помощью addnext.
Если же оба слова известны — мы проверяем их «родство». В единичном случае код
матери может получится из собственного кода, минус символ с хвоста sc3:=copy (sc,1,length
(sc) -1). Если полученный код совпадает с кодом матери, то сообщаем «Я знаю». В случае
если это не так, предлагаем сохранить вариант определения.
Посмотреть на этот процесс можно в мини-программе:
И
лл. 54. Использование процедуры chatit в программе.
И так может выглядеть конечный результат:

И
лл. 55. Фрагмент диалога с диалоговой процедурой в режиме добавления понятий Chatit.
Итак, если как следует набраться терпения и заняться вдумчивым и планомерным
наполнением словарей[6], каждый элемент классификатора становится похож на слоеный
пирог из «генома» кода, в котором мы можем отсекать части хвоста и получать более
обобщенные сведения об элементе. Возьмем, например фразу:
Мы сегодня пойдем в кино
В закодированном виде это предложение выглядит так:
AAAAAABACIJ AAAAAAABAAHPFA AAAAAAACCABABCFA AAAAAAAAFFG
AAAAAABAADLJ
Если мы уберем от каждого кода по одному символу с его конца, то получим фразу:
AAAAAABACI AAAAAAABAAHPF AAAAAAACCABABCF AAAAAAAAFF AAAAAABAADL
Или
Объединение сейчас идем где кинотеатр
И пусть эта фраза звучит против правил русского языка, однако если бы это
предложение произнес иностранец, скажем из ЮАР, она не показалась бы чем-то
экстраординарным, и нам все равно был бы понятен ее смысл.
Ради интереса усечем еще один символ из каждого слова-множества и мы получим
предложение:
AAAAAABAC AAAAAAABAAHP AAAAAAACCABABC AAAAAAAAF AAAAAABAAD
Или
Сообщество настоящее идти указание кинематограф
Понять его еще немного сложнее, но все же, возможно. Таким образом, утрата или
приобретение одного или нескольких символов кода в отдельных словах-множествах
практически не меняет конечного смысла целой фразы, что в значительной мере упрощает ее
анализ и операбельность.
Кстати говоря, в каждом слове приведенного предложения есть общий фрагмент,
который легко выделяется, — это головной элемент AAAAAA, означающий «Понятие»
и говорящий о том, что во фразе мы оперируем абстрактными смыслами, порожденными
человеческим разумом.
Рассмотрим превращения этого предложения при позиционном прибавлении кода и его
удалении на рисунке 56. Цветом выделен оригинальный текст, строчки ниже — «предки»
кода, строчки выше — его потомки.

И
лл. 56. Результат работы процедуры, иллюстрирующей «путешествие» по содержанию кодов
слов-множеств из исходной фразы. Ниже исходных слов — его предки, выше — его
потомки.
Возможно, вам захочется отметить, что «кино» в действительности относится к конкретному
зданию или строению, и это справедливое замечание. Второй смысл
слова «кино» действительно закодирован в ветке классификатора «Здание»/ «Сооружение».
Также и смыслы слова «Мы» разнятся, и это может быть как указание на «Сообщество»/
«Объединение», так и на «Людей», выполняющих определенную роль; но о возможности
оперировать несколькими смыслами слов мы подробно поговорим в главе 1. Пока же
рассмотрим второй пример:
Над городом поднимался густой туман
В закодированном виде это предложение выглядит так:
AAAAAAAAFFEBA AAAAAAAAFFETEC AAAAAAAAFFEBCCFA
AAAAAAABAAHGAAFA AABBADAIEA
Вновь удаляем по одному последнему символу и получаем следующее:
AAAAAAAAFFEB AAAAAAAAFFETE AAAAAAAAFFEBCCF
AAAAAAABAAHGAAF AABBADAIE
Вверху город поднимается частый туманный
Это также нарушает правила русского языка и немного смутно, но подобное вполне
можно услышать от иностранца. Теперь продолжим и отсечем еще по одному символу
от кодов:
AAAAAAAAFFE AAAAAAAAFFET AAAAAAAAFFEBCC AAAAAAABAAHGAA
AABBADAI
Место городское подниматься частое туманное
Эту фразу можно понять уже двусмысленно: то ли в пригороде можно видеть смог,
то ли в городе часто виден туман, и тем не менее общий смысл того, о чем идет речь, все еще
может быть уловлен.
И
лл. 57. Предки и потомки слов из фразы «Над городом поднимался густой туман».
Эти примеры легко показывают, что кодирование смыслов в MSM имеет существенное
значение: фразы слов-множеств достаточно устойчивы к обобщениям, и если изменения
затрагивают лишь несколько символов в предложении, они с высокой долей вероятности
сохранят свое смысловое значение. Устойчивость и мобильность семиотических значений
позволяет расширять вероятностное попадание в необходимые смыслы. Так фразы «Мама
мыла раму» и «Мать моет окно» получают очень близкое семиотическое значение, которое
легко обрабатывается программными методами, поскольку их коды оказываются очень
близки. Визуально это можно увидеть на рисунке 58.

И
лл. 58. Родственность фраз «Мама мыла раму» и «Мать моет окно» очевидна.
Фразы можно сравнить и по написанию кода:
AAAAAAAEAADL AAAAAAACUKJFA AAADCABAAABJJAC (Мама мыла раму)
AAAAAAAEAAD AAAAAAACUKJF AAADCABAAABJ (Мать моет окно)
Если сравнивать их машинным способом, с помощью процедуры вычисления
процентного сходства, мы получим следующие значения: 92%, 92% и 80%; из этих
показателей вычисляется среднее значение сходства (92+92+80) /3=88%. Если в базе данных
не находится более точное попадание, (с более высоким процентным соотношением)
исходное предложение считается самым подходящим и используется в зависимости
от наших нужд для генерации необходимых данных.
Стоит отметить, что для сравнения слов-множеств используется не стандартная
описанная процедура сложного сравнения, (которую мы используем для сравнения слов
на естественном языке), а процедура, работающая по принципу «первого расхождения».
Почему это так? Все слова классификатора родственны и имеют одного общего предка.
Родственность будет считаться совпадающей до того момента, когда следующий символ
перестает совпадать; то есть ветки родственности начинают расходиться, — дальнейшее
сравнение может только запутать, поскольку, например, коды
ABAAABBCD и
ABAEABBBA
могут иметь совпадения после расхождения, что однако не приближает родственность
смыслового значения. И очевидно, что понятие с кодом ABAABADDE должно иметь
большее родство с первым значением, чем второе, поскольку имеет общую
последовательность из четырех прямых родственников «ABAA» и должно получить большее
количество баллов за сходство.
Стоит привести оригинал процедуры Truepercent.

И
лл. 59. Процедура truepercent измеряет сходство кодов MSM — до первого расхождения
значений.
Как действует алгоритм. Он получает на вход два кода слов-множеств, S и S2. В выходной
переменной T будет находиться значение массой от 0 (полное различие) до 10 000 (полное
сходство). Для начала, здесь проверяется длина значений и если один из кодов (или оба)
имеют длину меньше 1, то проверка заканчивается со значением T=0. Если эта проверка
пройдена, мы проверяем полное совпадение значений (IF s=s2), (и оставляем в T значение
10 000, если это так). Далее, значению step присваиваем число, равное 10 000 поделенным
на число символов в самой длинной строке из сравниваемых.
В цикле мы будем пробегать по индексу строки вперед с помощью указателя i до тех
пор, пока не наткнемся на первый не совпадающий символ или длина счетчика превысит
длину одной из строк. После этого, вычисляем значение T, по числу счетчика i-1,
умноженного на значение Step. Так например, сравнение значений ABABA и ACABA даст
показатель 2000, а сравнение ABABA и ABACA — 6000, что нам и требовалось.

Простое определение
Начиная работу с MSM нельзя не упомянуть возможность получения простого определения
на вопрос о значении того или иного слова. Для получения определения нам понадобится
прочитать родителей понятия, а мы помним, что код всех родителей записан в их детях.
Следовательно, для получения информации о его родителях нам следует удалить с «хвоста»
определяемого слова один-два символа и уточнить, что значат полученные коды в словаре.
Для этого нам понадобятся уже описанные процедуры Findword и Findcode, описанные
выше. Организовать их взаимодействие можно, добавив условие вхождения в диалоговую
процедуру Chatit. Мы будем давать определение, исходя из условия предоставления
пользователю двух ближайших по «старшинству» родственников понятия.

И
лл. 60. Пример реализации функции поиска объекта в словаре и разъяснения с помощью
процедур Findword и Findcode в диалоговой сборке Chatit.
Теперь диалог с компьютером может носить определенную полезную функцию, если нам
необходимо выяснить информацию о положении некоторых понятий в структуре
«дерева» MSM.
И
лл. 61. Пример работы с задачей «что такое», встроенной в диалоговую сборку Chatit.
Также, мы можем уточнять, принадлежит или нет определенное понятие к определенной
ветке, если проверим наличие понятия в составе кода слова. Этот тип запроса может звучать
как «Лиса это животное?» для чего программе требуется проверить наличие общих предков
у обоих слов-множеств этих понятий.
И
лл. 62. Функция проверки предположений пользователя по типу « M это N?»
Теперь «продегустируем», как это происходит на практике, развернув в процедуре Chatit уже
вполне осмысленный диалог, со стороны, напоминающий философский разговор двух
образованных людей. Поневоле в такой момент задумаешься, а кто на самом деле разумнее?
И
лл. 63. Пример работы диалога по принципу «M это N?» в диалоговой сборке Chatit.

Общее и частное
Семиотические (смысловые) сходства и различия понятий позволяют осуществлять простые
операции сравнения. То есть, в MSM не составляет никакого труда найти лишний объект
в ряде других, поскольку он будет отличаться своим кодом.
Рассмотрим пример: «Найди лишнее: карандаш, ручка, бумага, фломастер?» Здесь
программа может безошибочно определить лишний объект «бумага», по той простой
причине, что его код будет более отличен от других. Пример того, как это работает —
на иллюстрации 64.
И
лл. 64. Пример решения задач по нахождению лишнего объекта в программе MSM.
Выводы можно сделать, даже просто взглянув на состав кода:
AAADAACBABA (Карандаш)
AAADAACBABC (Ручка)
AAADAACBAAA (Бумага)
AAADAACBABB (Фломастер)
Это программное решение описывается в процедуре Findelse.
И
лл. 65. Процедура нахождения лишнего из серии слов, на основе их кода MSM.
В приведенной процедуре используются два массива — sm и sm2, в которые записываются
отдельные слова и их коды, а также массив Ball, где сохраняются оценки схожести одного
элемента со всеми остальными.
Для начала, строка S здесь разбивается на набор слов с помощью процедуры justbreak
и слова оказываются в массиве sm, с максимальным индексом j. В цикле массив sm2
заполняется кодами слов массива sm с помощью процедуры findword.
Далее, используются два цикла I и X. В случае, если значения i и x отличаются
(поскольку они выполняют функции индексов массива sm2), с помощью процедуры
truepercent получаются оценки пар кодов, результат которых добавляется в массив ball
текущего индекса i.
После перебора всех элементов в цикле x, для оценки каждого элемента используются
переменные min и mini. В случае если сумма текущих оценок оказывается меньше
минимальной, она сохраняется в переменной min а индекс элемента — в переменной mini.
По завершению работы циклов выходная переменная s2 получает значение sm
с индексом минимума mini, — это слово и будет лишним элементом на основе сравнения
кодов MSM.

С той же легкостью находится и сходство между объектами, на основании простого


сравнения кода. В этом случае общий фрагмент кода, совпадающий для всех элементов,
становится общим признаком.
Пример того, как это работает — на иллюстрации 66.
И
лл. 66. Пример нахождения общего признака между объектами в программе MSM.
Вариант реализации может осуществляться с помощью процедуры Findsame:
И
лл. 67. Процедура нахождения общего признака в серии слов, на основе кодов MSM.
Как и в процедуре Findelse, здесь производится разделение строки на слова и их
перекодирование в массив sm2.
Затем в цикле x производится сравнение текущего символа i в массиве sm2
со следующим по порядку (x+1) кодом из массива. В случае нахождения несоответствия,
логической переменной notsame присваивается значение true и производится выход
из общего цикла repeat. Соответственно, совпадающий фрагмент всех кодов считается
равным i-1, и код этого слова находится с помощью процедуры findcode. Оно
и присваивается выходной переменной s2.

Использование свойств элементов


Помимо простого родства между словами-множествами большое значение имеют
дополнительные свойства элементов, хранящиеся в отдельных словарях.
И
лл. 68. Образец сохранения свойств объектов в словаре AlikP. Здесь первый код обозначает,
к какому понятию принадлежат свойства, а последующие коды — присваиваемые значения.
Например, сохраняя свойство «Небо голубое» в виде записи «AABBACA
AAAAAAABACAHA», мы можем легко получить простой ответ на вопрос «Какого цвета
небо», поскольку понятие «Голубое» (AAAAAAABACAHA) является близкой родней слова
«Цвета» (AAAAAAABACAP). Добиться такого эффекта не так сложно, как может показаться
на первый взгляд.
На иллюстрации 68 приведен пример сохранения свойств в словаре AlikP.
Для обработки свойств в первую очередь понадобится создать пустой файл «alikp. txt»
и процедуры для записи свойств. Первая процедура Addproperty будет обрабатывать
единичную команду записи свойств (илл. 69). Здесь используются две входные переменные:
S и S2; в S хранится определяемое слово, а s2 содержит одно или несколько слов,
характеризующих это понятие. Слова проверяются на наличие в словарях с помощью
findword, так же как и сама запись на наличие в файле alikp. txt. Если записываемое
определение является новым и все коды слов содержатся в словарях (проверка переменной
good), тогда определение сохраняется в словаре.
И
лл. 69. Процедура записи свойств addproperty.
Но если в качестве свойств мы используем дополнительные определения, которые
перечисляются через запятую, удобно использовать процедуру Addproperties (илл. 70).
И
лл. 70. Процедура Addproperties — запись серии свойств через запятую, где S- определяемое
слово, s2 — серия описаний где отдельные свойства могут разделяться запятыми и состоять
из одного или нескольких слов.
В ней используется два цикла, которые читают содержимое строки s2 c увеличением индекса
i и разделяют содержимое на блоки, которые при встрече запятой сохраняются с помощью
описанной выше процедуры addproperty.
Сохранение свойств позволяет реализовать возможность отгадывания загадок или
получения агрегированных знаний.
Например, сохраняя в качестве свойств информацию об определенных особенностях
строения родов животных мы можем получить информацию о свойстве животного
определенного вида. Предположим, мы сохранили свойство «Парнокопытное ест траву»
в таком случае на вопрос «Чем питается корова» мы получим ответ «Ест траву» или получим
утвердительный ответ на вопрос «Корова питается травой?»
И
лл. 71. Одно знание о питании парнокопытных позволяет просчитывать много вариантов
вопросов. Последний вопрос вызвал некоторое «смущение», поскольку знанием о том, какие
виды «пасутся на лугу», программа не была снабжена.
Кроме того, знания, полученные из свойств в системе, имеют возможность агрегироваться.
Так мы имеем возможность, например, поинтересоваться, чем питаются животные,
и получить информацию о мясном питании хищных, растительной пище травоядных
и т. д. Подобная интеллектуальная реакция компьютера, когда обучение занимает считанные
секунды, а результат превосходит все ожидания и оказывается настолько многогранным, —
обычно производит ошеломительное действие на наблюдателей.
На иллюстрации 72 — агрегированное знание о хищниках, питающихся людьми, это
лев, волк, акула и крокодил. Записи о том, что тот или иной хищник «Ест людей»
указывались в свойствах отдельных видов животных. Теперь мы видим перечисление
и можем уточнить конкретного хищника по любым из дополнительных свойств.
И
лл. 72. Программа агрегирует знания и отгадывает загадки.
Как это работает? Для начала, разберемся с загадками. Из-за объема и сложности процедуры
findanswer2, в ней добавлены комментарии, которые должны помочь разобраться.
И
лл. 73. Процедура отгадывания загадок Findanswer2.
Для работы со свойствами по типу «расскажи о» применялись и более сложные алгоритмы,
включающие обработку синонимов.

Синонимы
Синонимы при работе с текстом встречаются регулярно. Поэтому нам следует уметь с ними
работать. В идеале программа должна понимать, например, что фразы «Ты хочешь есть?»
и «Ты хочешь кушать?» по существу означают одно и то же, несмотря на то, что
дополнительные значения слова «есть» кроме как «находиться» мы могли еще и не описать.
(Однако это не означает замещения смысла слова, эта стратегия используется только для
входного «понимания» блока текста, предложения).
Для хранения синонимов можно использовать отдельный словарь, например sinonims.
txt (Илл. 74). Он имеет самую простую структуру: здесь находятся словесные пары, которые
могут являться синонимами друг друга.
И
лл. 74. Содержимое словаря синонимов sinonims. txt.
Также стоит помнить, что одно и то же слово может иметь несколько синонимов
и описываться в различных местах этого словаря, поэтому оптимальным вариантом
получения сведений из него является генерация массива значений, (а не 1,2 или
5 переменных).
И
лл. 75. Процедура чтения синонимов findsin. По коду S происходит генерация списка
синонимов из словаря синонимов.
Для обработки словаря понадобится соответствующий алгоритм чтения и записи. Прочитать
записи можно с помощью процедуры Findsin (илл. 75), где варианты синонимов будут
сохраняться в выходном массиве с числом элементов j — так же, как и в случае с процедурой
justbreak.
В качестве входной переменной здесь используется единичный код из переменной s.
В процедуре происходит считывание сведений из словаря синонимов, и в случае, если
рассматриваемый код попадает в часть содержимого одного из значений, а также модуль
числа разницы в длине этих строк не превышает 4 символа, то итоговый массив дополняется
новым значением второй пары. Считывание является зеркальным; то есть искомый синоним
может быть получен как из левой так и из правой части записей словаря.
Процедуру записи синонимов в словарь мы можем не выделять в отдельный блок,
а встроить в описанную выше процедуру Chatit (илл. 53), как одну из форм реакций
на введенную пользователем информацию. Условием вхождения мы можем считать наличие
в строке символа равенства '=», который ставится между двумя словами. Так же здесь нам
потребуется предварительно созданный файл sinonims. txt, в который мы будем сохранять
новые синонимы.
И
лл. 76. Дополнительный блок входа в процедуре Chatit (илл. 53) сохраняет новые синонимы,
предварительно проверяя наличие более ранней записи в файле sinonims. txt.
Также в практике нам потребуются процедуры для генерации синонимов в блоке текста. То
есть, для нас имеет смысл оперировать несколькими вариантами предложений, собранных
целиком с использованием различных комбинаций синонимов. Эту задачу будут выполнять
процедуры sincombine и sinchanger.
Процедура sincombine занимается обработкой двух предложений, составленных
из кодов слов-множеств; но мы предполагаем, что эти два предложения могут отличаться
по причине использования в них одного или нескольких слов, имеющих несколько значений.
В результате нами генерируется массив из R значений, который содержит несколько
возможных вариантов рекомбинаций имеющихся значений.
Например, у нас есть предложения из слов:
«A B C D E» и «A F C D G». В данном случае нам известно, что слова B и F, а также E
и G являются синонимами друг друга. Но в то же время В не является синонимом G, а G
не является синонимом F. В данном случае позиция «руководит» объектом рекомбинации.
Идеальным результатом работы процедуры должно стать получение массива из двух
дополнительных рекомбинированных предложений: «A F C D E» и «A B C D G».
Мы не используем исходные предложения в качества вариантов вывода; а если у нас
окажется предложение с большим числом синонимов, число вариантов должно
пропорционально возрасти.
И
лл. 77. Процедура sincombine занимается рекомбинацией двух предложений с разными
вариантами синонимов.
Процедура sinchanger занимается исчерпывающим поиском вариантов синонимов
и созданием на их основе рекомбинированных предложений с использованием описанной
выше процедуры sincombine.
И
лл. 78. Листинг процедуры sinchanger, занимающейся исчерпывающим поиском «кучи»
вариантов с использованием словаря синонимов.
Итак, мы собрали нужные вещи, для дальнейших шагов. Каким образом мы можем получить
некоторые сведения, агрегированные из свойств ряда тех или иных объектов? Для этой цели
реализуется следующий механизм: на вход процедуры поступает некоторая заявка, назовем
ее N с рядом свойств N2, N3, N4.. -число серии свойств при этом не ограничивается. После
чего программа производит поиск соответствий всех параметров, которые связаны с N
с некоторой стадией обобщения. То есть, при чтении данных допускается некоторая разница
в «хвосте» элементов, которая делает соответствие отвечающим требуемому условию. Так
например, слова-множества «Цвет» (AAAAAAABACA) и «Красноватый»
(AAAAAAABACALAH) имеют общее основание «Цвет» и разницу в 3 символа. Это
означает, — если мы ищем свойства, соответствующие запросу «Цвет» и используем
допущение до 4 символов отклонения, то свойство «Красноватый» становится подходящим
элементом в качестве ответа на такой запрос. Аналогичным образом будут обрабатывать
и многие другие обобщающие запросы, например «Вода» (AABBAFC) и «Мокрый»
(AABBAFCKL), «Звук» (AAAAAAABADA) и «Громкая» (AAAAAAABADAAFE),
«Ругательство» (AAAAAAACaLGAC) и «Обматерить» (AAAAAAACaLGACJIE).
Но например, для обнаружения обобщения «Разрушение» (AAAAAAACA) и «Ударил»
(AAAAAAACaIJA), допустим дополнительный отступ в сторону общего предка «Действие»
(AAAAAAAC).
Так, с помощью эпмпирического метода проб и ошибок в алгоритме поиска свойств
с обобщением мы будем использовать обобщение до 4 символов с отступом в 1 символ
в сторону общего предка понятия. Кроме того, программа должна следить
и за использованием синонимов, чтобы они были полноценными участниками действия.
Переходим к практической реализации процедуры, занимающейся всем этим.
И
лл. 79. Листинг процедуры Anatomy, занимающейся практическим обобщением свойств
искомых понятий.
Из нашего внимания выпал еще один момент, это использованные
процедуры uncodecs и getfathercode.
Uncodecs занимается групповым восстановлением предложения в строке S из серии
кодов слов-множеств, и передаче перевода в S2:
И
лл. 80. Листинг процедуры Uncodecs для перевода предложения, написанного в кодах
слов-множеств на естественный язык.
Getfathercode — находит общее в двух словах, написанных в кодах слов-множеств SC
и SC2, и возвращает его в выходной переменной SC3.

И
лл. 81. Листинг процедуры Getfathercode для нахождения общего предка из кодов двух
слов-множеств.
Теперь мы готовы к обработке сложных запросов типа «Расскажи о цвете неба», и так этот
фрагмент может быть оформлен в нашей процедуре ChatIt, отвечающей за диалог
с пользователем:
И
лл. 82. Фрагмент вставки процедуры Anatomy в диалоговую процедуру Chatit.

Вопрос-ответ
Так же мы можем и прямо сохранить форму вопроса (это реализуется в словаре Queans
с помощью формы, как на иллюстрации 83).

И
лл. 83. Фрагмент записей словаря вопросно-ответных моделей Queans. И вопросы и ответы
выглядят как полные фразы, записанные в форме слов-множеств.
В подобном формате может быть записан нужный ответ. Пример такого диалога
с программой — на иллюстрации 84.
И
лл. 84. Прямое обучение конкретному вопросу. Здесь перефразирование вопроса не влияет
на «понимание» и возвращает систему к нужному ответу.
Помимо упомянутых форм взаимодействия с системой MSM мы имеем возможность
получать так называемые зеркальные ответы, когда организованные взаимосвязи позволяют
регулировать формы ответа в зависимости от поставленной формы вопроса.
Рассмотрим пример. Мы просим систему запомнить ситуативную фразу «Ты принес
из магазина продукты?» на которую записываем форму ответа «Продукты я принес». Далее,
на вопрос «Ты принес из магазина хлеб?» последует ответ «Хлеб я принес», а на вопрос «Ты
притащил из „Ашана“ молоко?» ответит «Молоко я притащил». Как это происходит?

И
лл. 85. Образец зеркального ответа из модели прямой записи вопросов и ответов.
Как мы уже упоминали, исходное предложение записывается в форме кода MSM в паре
с формой ответа. В данном случае запись модели выглядит так:
«AAAAAAAAFDAA AAAAAAACGLIEA AAAAAAAAAAA AAADCABBBA
AAADCCFHE
AAADCCFHE ABABACAAAACAP AAAAAAACGLIEA.»
В первой строке звучит вопрос, во второй — ответ. Ответная строка помечается точкой
в конце. Итак, записали.
Затем при совпадении/частичном совпадении с исходной фразой (где нам безусловно
поможет функция процентного сравнения) мы анализируем текст, отмечая наличие
совпадений в вопросе и ответе. В данном случае в тексте ответа используется два слова
из вопроса, это «Принес» (код AAAAAAACGLIEA) и «Продукты» (код AAADCCFHE).
После чего мы отмечаем позиции тех слов, которые имеют неполное совпадение, и копируем
вариант родственника из вопроса.
Записать модель вопросно-ответной схемы мы можем с помощью
процедуры writemodel:
И
лл. 86. Листинг процедуры записи вопросно-ответных моделей.
В этой процедуре записи моделей используется и незнакомая нам процедура Decodecs. Ее
основная функция — преобразование предложения в набор кодов MSM.
И
лл. 87. Листинг процедуры Decodecs, переводящая предложение на естественном языке
в набор кодов MSM.
Далее, нам потребуется и процедура чтения моделей, для прикладного применения
к конкретному заданию от пользователя. Этим занимается пара
процедур Checkmodels и Readmodels, где checkmodels — является вспомогательной,
процедурой, в которой производится выбор и проверка наличия моделей в словаре,
а readmodel — основной для взаимодействия с пользователем. Начнем с Checkmodels:
И
лл. 88. Процедура Сheckmodels в которой производится проверка наличия записанных
моделей ответа.
Здесь также используется функция multicheck, которая занимается сравнением наличия
одного кода в другом или одной серии кодов в другой серии кодов, записанных через точку,
как например "AADG.ADFD» и "ADFE.ADDD. AADG», — в последнем случае функция
вернет значение true (поскольку здесь совпадают значения AADG в строках).
И
лл. 89. Функция Multicheck, занимающаяся сравнением совпадений кодов слов-множеств
в одиночной или серийной записи.
И наконец, окончательная процедура обработки запроса Readmodel, принимающая запросы
пользователя и отвечающая на них.
И
лл. 90. Листинг процедуры Readmodel, занимающейся чтением модели и выбором вариантов
ответа на запрос пользователя из модели типа вопрос-ответ.
В этой же процедуре производятся и «зеркальные ответы», а также происходит контроль
за порядком соблюдения последовательности построения слов в вопросе.
Применение readmodel в нашей сборке диалоговой процедуры Chatit может быть
следующим.
И
лл. 91. Применение процедуры Readmodel в сборке диалоговой процедуры Chatit.
В данной сборке мы добавили переменную Entered, которую описали типом Boolean. Ее
также следует добавить и во входные параметры других процедур в сборке Chatit, — она
контролирует процесс вхождения в одну из процедур, и тогда становится True, иначе ее
значение остается False, — это означает что текущее задание еще не выполнено другими
процедурами и неплохо было бы решить поставленную задачу.
Однако на этом возможности системы на базе MSM далеко не исчерпываются.
В качестве свойств мы имеем возможность сохранять зависимости и удельные веса
значений.

Весовые значения и зависимости


Зависимости значений-антагонистов записываются в виде кодов в отдельном словаре
с указанием в сторону более сильного признака (здесь и далее в скобках записана
непосредственная техника оформления в словаре, слова на естественном языке нигде кроме
классификатора в программе не используются). Например, ЯРКИЙ> ТУСКЛЫЙ
(AAAAAAABAAVDE> AAAAAAABAAVEE), ГОРЯЧИЙ> ХОЛОДНЫЙ
(AAAAAAABAAGAA> AAAAAAABAAGBA), УМНЫЙ> ГЛУПЫЙ (AAAAACA>
AAAABA), СИЛА> СЛАБОСТЬ (AAAAAAABAAB> AAAAAAABAABBF), ВКЛЮЧЕНИЕ>
ВЫКЛЮЧЕНИЕ (AAAAAAACIANMEDH> AAAAAAACadJIEEE), ЖИЗНЬ> СМЕРТЬ
(ABF> AAAAAAAH), СОЗИДАНИЕ> РАЗРУШЕНИЕ (AAAAAAACbE> AAAAAAACA)
и т. д.
И
лл. 92. Фрагмент записей словаря антагонистов.
По умолчанию, производные этих значений могут использоваться как варианты
предпочтительного выбора. То есть, в случае свободного выбора система предпочитает
выбирать варианты развития событий, в которых направление значений преимущественно
ориентировано в сторону сильного признака. В каком-то роде это «понимание»
неравнозначности смыслов закладывает основы «характера» в систему и является основой
предпочтений. Получается, что при полученном выборе остаться включенным или
выключиться, система будет неравнодушна и предпочтет включенность. Так же, когда
(гипотетически) этот выбор будет предоставлен в отношении другого живого существа, он
предпочтет сохранить жизнь, нежели уничтожать ее. (Конечно же, с другой стороны, эта
система антагонистов может порождать в системе и «баги» в виде мании включения всех
подряд устройств, но впрочем, будем надеяться, что к тому времени у нее же хватит
«мозгов» не допускать включений механизмов, способных повлечь разрушение, аварию или
чью-то смерть). В более простой интерпретации эти знания дают простые ответы на простые
вопросы типа «Что лучше, жить или умереть?», «Из-за землетрясения здание рухнуло. Это
хорошо или плохо?» и т. д.
Функцию записи в словарь антагонистов можно осуществлять непосредственно
в процедуре Chatit, следующим набором действий:

И
лл. 93. Запись значений антагонистов в словарь antagon. txt.
В некоторых случаях оказывается полезным и более прямолинейно указывать
на характеристики весов значений. Например, словарь с записями весовых значений
оформляется кодами следующим образом:
БЕГЕМОТ ТЯЖЕЛЫЙ +500 (ABABACCEAA AAAAAAABAAAA +100)
СЛОН ТЯЖЕЛЫЙ +2000 (ABABACFAA AAAAAAABAAAA +2000)
КИТ ТЯЖЕЛЫЙ +7000 (ABABACPAA AAAAAAABAAAA +7000)
ЧЕЛОВЕК ТЯЖЕЛЫЙ +100 (ABABACAAA AAAAAAABAAAA +100)

И
лл. 94. Листинг процедуры Incalik4, записывающей весовые значения слов-множеств
в словарь.
Так мы легко получаем ответы на вопросы о сравнительных характеристиках, как например,
в данном случае: «Кто тяжелее, слон или человек?», «Кто легче: кит, бегемот или слон?»,
и т. д. Характеристика может также даваться по любому признаку: силе, скорости, яркости,
насыщенности, кислоте, сладости, и т. д.
Для создания возможности обработки подобных запросов нам понадобится две
процедуры, motherland и tryweight. Первая процедура — вспомогательная, она понадобится
нам для того, чтобы мы могли оценивать значения весов в зависимости от удаленности
потомка от своего родителя.
И
лл. 95. Листинг процедуры motherland, оценивающей близость родства двух слов-множеств.
В качестве ответа используется несколько вариантов:
— отсутствие родства — « -100»;
— родство, но разница в числе символов — положительное значение разницы
в символах (от 0 до бесконечности);
— родство, но разница в матери на один символ — то же самое, +1.
Следующая процедура tryweight просматривает массив условий SM и сверяет
соответствие с серией значений SM2 по трем параметрам: соответствие весового значения,
наличия заданного свойства и соответствия родства условий с предлагаемыми значениями.
И
лл. 96. Вычисление весовых значений серии условий к серии значений с помощью
процедуры tryweight.
Таким образом, на вопрос: «Выбери желтое сильное животное: таракан, крокодил, апельсин,
лев, шпиц, человек» процедура даст корректный ответ «Лев». Как видно, желтых животных
здесь два, «Лев» и «Шпиц» и оба они имеют сильного предка «Хищное». В этом случае
и играет свою роль как разница в удаленности от предка, имеющего весовое значение, так
и сумма весовых значений конкретной особи. «Хищное» имеет весовое значение силы +100,
«Лев» — так же имеет весовое значение +100, а непосредственное весовое значение силы
«Собаки» +20. Разница между кодами льва (ABABACBBBA) и хищного (ABABACB)
составляет 3 символа; такая же, как между ним и шпицем. Так эти существа получают
по (100/3) =33 балла силы по умолчанию. Дополнительное значение силы льва составляет
так же 100, итого — у льва оказывается 133 балла, в то время как у собаки второе значение
составляет 20, и в сумме 20+33=53 балла. Так в этом соревновании побеждает «Лев»,
набравший максимальное количество баллов и попаданий в родство свойств и условий.
Теперь встроим эту процедуру в диалоговую сборку Chatit.
И
лл. 97. Использование процедуры Tryweight в диалоговой процедуре Chatit.
Теперь рассмотрим возможный сценарий диалога на примерах.

И
лл. 98. Тест работы программы с использованием процедуры Tryweight на практических
примерах. Высказывание « Hmm..» в третьем примере означает, что полное соответствие
всем условиям не достигнуто: не обнаружилось ни одного значения, в свойствах или весах
которого хранилось бы слово «Самое». Программа просто нашла сколько-нибудь быстрое
насекомое.
Это замечательный результат. Но мы можем и улучшить его, построив алгоритм, согласно
которому из полученных сведений об удельных весах, система может строить
предположения на основе данных о родственниках без прямого на них указания.

Возможные модификации правил обработки данных


Я не стану углубляться в практическую детализацию этих алгоритмов, но нам легко
представить ситуации, как мы могли бы модифицировать вышеописанные процедуры, для
решения других практических задач. Если они заинтересуют читателя, то при определенном
усердии их можно реализовать.

Задача о корове
Представим, что никаких других данных о весе других живых существ, (кроме
описанных выше) у нас нет. Но спросив о весе коровы, допустим в такой форме «Корова
тяжелее человека?», мы можем получить ответ: «Предполагаю, что да». Как это можно
осуществить?
Не найдя прямого ответа, программа может построить предположение на основе
родственной связи кода существа, вес которого неизвестен (корова, код ABABACCAAA),
к коду существа, вес которого прямо указан (бегемот, код ABABACCEAA). Они имеют
общий головной фрагмент кода (ABABACC — парнокопытное), но и некоторое расхождение
(последние три буквы). Таким образом, весовое значение может быть рассчитано
приблизительно, исходя из предположения, что разность веса на каждом переходном этапе
кода не превышает 20% от веса родственника. Так можно получить числовое значение
+500 +-60% (по 20% за каждую букву разницы в родстве) итого — предположительный вес
коровы по оценке системы может составлять от 200 до 800. Теперь программе остается
только сравнить наименьшее значение с весовым значением человека (+100) и озвучить свое
предположение. Кстати, как вы наверное уже догадались, в описании значений веса был
использован приблизительный вес в килограммах. Так же можно использовать и другие
единицы мер и весов в описательных характеристиках объектов.

Задача об автомобилях
В случаях, когда весовые значения подаются в форме описанного задания, можно
попробовать найти решение, исходя из данных значений. Например, рассмотрим простую
задачу:

«Две машины едут в одном направлении: первая со скоростью 100 километров в час,
вторая со скоростью 120 километров в час. Через 50 километров пути вторая машина
сделала остановку на 5 минут. Какая из них приедет быстрее в пункт назначения,
находящийся на расстоянии 200 километров?»

Эта задача может быть решена системой при условии составления соответствующей
формы выбора правила, где система может самостоятельно «собирать» уравнения,
основываясь на ключевых фразах.
При добавлении достаточного числа правил решения задач в форме моделей, система
может выбирать наиболее похожую задачу и применять аналогичные методы решения.
Сначала мы отвлечемся и разберемся с описательной моделью на человеческом языке.
В задаче требуется определить следующие ключевые объекты и их значения, а также разбить
задачу на несколько последовательных подзадач:
Первая (машина): скорость 100 км/ч, путь 200 км = время (быстрее)?
Вторая (машина): скорость 120 км/ч, путь 50 км. 5 минут остановка. 120 км/час путь
150 км = время (быстрее)?
Теперь переходим к непосредственному подсчету. В случае с первой машиной мы
делим путь (200) на скорость (100) и получаем значение времени равное 2 часам.
В случае со второй машиной нам необходимо посчитать время, за которое машина
пройдет первые 50 километров, для этого мы делим путь (50) на скорость (120) и получаем
значение 0,417 часа. Умножаем это значение на 60 и получаем 25 минут. Затем прибавляем
к этому значению 5 минут, получаем 30 минут, или 0,5 часа. И теперь считаем, за какое
количество времени вторая машина преодолеет оставшийся промежуток пути, равный
150 км: 150/120 = 1,25 часа. Теперь к этому числу мы прибавляем 0,5 часа из предыдущего
времени пути и получаем число 1,75. Затем сравниваем значение времени, полученное
от первой машины (2) со второй (1,75) и получаем ответ — вторая машина приедет быстрее,
чем первая, несмотря на остановку в пути.
Таким образом, мы выделяем ответ в соответствии с меньшим значением, понимая, что
означает «Быстрее». Решение нельзя назвать достаточно простым для системы, однако
форма записи последовательности решений может быть зафиксирована простыми методами
таким образом, что подобные и иные задачи могут решаться достаточно легко
с использованием словарей моделей задач, имеющих соответствующие шаблоны решений.
В частности для решения подобной задачи мы выделяем текстовую форму с сохранением
модели пунктуации, где начало записи фиксируем символом».». Запись эталонной модели
задачи и решения может выглядеть следующим образом:
«.
AAAAAAADAAAAAABAB AAADAAAAAAANA AAAAAAACgPBFA
AAAAAAAAFFG AAAAAAADAAAAAAAAE AAAAAAAAFFDJ
AAAAAAADAAAAAAAAHAE AAAAAAACECB AAAAAAABAACD
100 AAAAAAABAAUJFF AAAAAAAAFFG AAAAAAABAAHBBAAAAA
AAAAAAADAAAAAABAADAE AAAAAAACECB AAAAAAABAACD
120 AAAAAAABAAUJFF AAAAAAAAFFG AAAAAAABAAHBBAAAAA *: A, B.*
AAAAAAAAFFEBAB 50 AAAAAAABAAUJFF AAADCAAADMA
AAAAAAADAAAAAABAADAE AAADAAAAAAAN AAAAAAAABAIB
AAAAAAACPHAC AAAAAAAAFFEBB 5 AAAAAAABAAHBBAAAAAAAB * C D.*
AAAAAAAADAAD AAAAAAAAAAA AAAAAAAAFGB AAAAAAACgPBGH
AAAAAAABAACAAAB AAAAAAAAFFG AAADCABBAL AAAAAAAAFFDYIHA
AAAAAAAAECAB AAAAAAAAFFEBB AAAAAAABAAEOD 200 AAAAAAABAAUJFF
*, E.*
>> F=E/A; G= (C/B) *60+D; H=60/G; I= (E-C) /B+H;
<<AAAAAAADAAAAAAAAHAE = F
<<AAAAAAADAAAAAABAADAE = I
>>>> I <F = AAAAAAADAAAAAABAADAE»
Конечно, описательная часть задачи в формате модели для решения выглядит довольно
громоздко, но при наличии хорошего объема словаря и большой базы записанных таким
образом моделей задач, должна показывать хорошие результаты.
Что здесь происходит? Мы просто переводим задачу на язык кодов MSM так, как есть,
предложениями, не забывая однако выделять численные значения, а так же модели чтения
пунктуации (выделены звездочками), в которой резервируем для каждого численного
значения в задании свою последовательную переменную (A, B, C, D, E).
Далее следуют предварительные расчеты за символами “>>», где мы также имеем
возможность заводить новые переменные (в данном случае F, G, H, I). Затем за символами “
<<” мы обозначаем связи переменных со значениями из текста, соответственно
«AAAAAAADAAAAAAAAHAE» означает «Первая»,
а «AAAAAAADAAAAAABAADAE» — «Вторая». И последняя строчка, следующая
за символами “>>>> ” — в ней мы описываем условие соответствия, при котором этот ответ
соответствует действительности.
На практике запись подобных моделей может быть результативна, хотя
полномасштабного тестирования в данном направлении еще не проводилось, и подробно
описывается она впервые.
Подобные выводы сделаны на основе сходной процедуры, благодаря которой
производилось расширение словарного запаса системы при полуавтоматическом чтении
с дополнением слов из толкового словаря русского языка, а также дополнении его
морфологическими формами исходных слов. Эффективность этого решения наглядна —
общий объем словаря удалось увеличить на более чем 30 тысяч слов всего за двести
человеко-часов взаимодействия с системой. Впрочем, подробнее об этом методе вы можете
прочитать в четвертой и пятой главах повествования.
Теперь мы остановимся на основной проблеме в решениях современных диалоговых
систем и изучим этот вопрос с разных сторон.

[1] По умолчанию мы работаем в символьной таблице ASCII кодировки DOS.


[2] Тем не менее, длина слов-множеств на практике колеблется в довольно узком
диапазоне. Самые длинные коды элементов по независимым от каких-либо ограничений
причинам составляют до 22 символов, и лишь единичные элементы — до 28 символов.
[3] Число элементов словаря MSM в настоящее время составляет более 60 тысяч и над
его графическим исполнением бьются несколько светлых умов.
[4] Здесь приведены названия из оригинальной программы проекта MSM.
[5] Проблема в том, что строковые процедуры и функции могут вызывать критические
ошибки при обработке коротких строк длиной в 1 или 2 символа. Самое простое решение,
которое родилось в данном случае — увеличить длину строк искусственно, вместо того
чтобы подвергать пересмотру весь остальной код.
[6] Для ленивых, можно просто скачать тестовые словари MSM с содержимым в более
чем 60 тыс. записей из облака по адресу: https://cloud.mail.ru/public/6yrC/agdBLjGsT
Глава 3. Проблема понимания
Из предыдущей главы мы узнали, какими базовыми возможностями обладает программа
на основе классификатора MSM. Если вникнуть подробнее в этот вопрос, то оказывается, что
самое простейшее ее свойство выделения общего и лишнего из серии элементов — уже
оказывается неподъемной задачей для современных диалоговых систем. Со всей
ответственностью можно заявить, что ни одна современная диалоговая система
по состоянию на начало 2019 года, какой бы архитектурой она не обладала, не имеет
возможности найти корректный ответ по запросу общего и лишнего в серии слов, как это
делается в MSM. Не важно, на чем она построена: нейросеть, экспертная система,
объектно-ориентированная база знаний, чат-бот, онлайн-консультант, и так далее. Вы
спросите, почему?
Потому что все они настроены на один принцип: «вопрос-ответ». Точнее, 1 вопрос =
1 ответ. Они не имеют возможности «вычислять» что-либо, поэтому строятся по принципу
сохранения максимального возможного числа вариантов вопросов и вариантов ответов.
Но поскольку мы не можем предусмотреть все возможные варианты перечислений всех
возможных объектов в запросе, это и становится их камнем преткновения, неразрешимой
задачей. В этом легко можно убедиться.
Рассмотрим подробнее и другие проблемы, с которыми сталкиваются диалоговые
системы, а для этого совершим небольшой экскурс к основным типам современных
диалоговых систем.

Простой бот
Принцип работы простейших ботов — когда запрос связан с ответом. Система выбирает,
основываясь на статистических методах, какой запрос больше похож на имеющийся в базе
данных, и выбирает ранее записанный ответ. Это — наиболее распространенный и наименее
интеллектуальный вариант. И, как правило, если это решение приводится с привлечением
искусственной нейросети, то оно не дает ему существенных преимуществ, кроме небольших
вариаций из симбиоза запросов. Например, мы научили подобного бота нескольким фразам:
«Как дела?», «Как твои дела» и «Как у тебя жизнь?» и варианты ответа: «Нормально»
и «Хорошо». Так вот, предел возможностей такого бота, это комбинаторность запроса, — то
есть очень большой удачей будет корректный ответ на запрос «Как у тебя дела?», — исходя
из указанных данных. Причем, удача в данной ситуации не гарантирована.
Теперь давайте рассмотрим конкретные примеры диалогов с простыми ботами, которым
старались задавать похожие вопросы, требующие немного больше, чем типовой ответ
на типовой вопрос.
С одним из простых ботов нам удалось пообщаться в рамках известного конкурса «The
Conversational Intelligence Challenge» («Состязание разговорного интеллекта»), в котором
производится набор базы знаний. При этом, вступая в диалог, заранее неизвестно, с кем он
производится: с человеком или с машиной. Но в данном случае нам попался довольно
примитивный бот первого типа. Диалог звучал так (Б-бот, Ч-человек). В скобках приводится
перевод фраз:

Б: — Hey! Are you a gold medalist Olympian? Because I am.


— Хей! А ты золотой медалист-олимпиец? Я — да.

Ч: — I’m not. But I’m not sure about you


— Я нет. И я не уверен насчет тебя.

Б: — I like to eat pizza and eat healthy


— Мне нравится есть пиццу и полезную еду
Ч: — Can you answer the question?
— Ты можешь ответить на вопрос?

Б: — I think it is a good idea. agreed. How do you feel about pot bellied pigs?
— Я думаю это хорошая мысль. согласовано. Как ты относишься к пузатым
свиньям?

Ч: — I try to ask u. I can?


— Я пытаюсь спросить тебя. Я могу?

Б: — I do not know what I do for a living


— Я не знаю, что я делаю для жизни

Ч: — So. what color is the sky?


— Итак. Какого цвета небо?

Б: — I like the color green.


— Мне нравится зеленый цвет

Ч: — How much legs lion have?


— Сколько ног у льва?

Б: — 3 years old
— Возраст 3 года

Ч: — A water is liquid or solid?


— Вода жидкая или твердая?

Б: — I like to eat pizza and eat healthy?


— Мне нравится есть пиццу и полезную еду

Ч: — bye
— Пока

Б: — I like to eat pizza and eat healthy


— Мне нравится есть пиццу и полезную еду
Илл.
99. Пример диалога с простым ботом от Conversational Intelligence challenge.
Похожий по содержанию диалог получился и с парой русскоязычных ботов. Удручающее
впечатление показал чат-бот xu.su.
И
лл. 100. Пример простого бота от xu.su.
Несколько лучше себя ведет pBot, однако это все тот же диалог 1 типа. Так выглядел диалог
с ним:
И
лл. 101. Пример простого бота от pBot.
ρBot: — Привет, как дела?
Незнакомец: — У меня отлично, меня интересует пара вопросов. Ты можешь ответить?

ρBot: — А тебе оно надо?


Незнакомец: — Какого цвета небо?

ρBot: — Голубое.
Незнакомец: — Сколько ног у льва?

ρBot: — У скорпиона 8 ног.


Незнакомец: — Человек это рыба?

ρBot: — Колбаса)
Незнакомец: — Кошка и рыба это млекопитающие?

ρBot: — Колбаса) Извини, что я повторяюсь


Незнакомец: — Какого цвета лев?

ρBot: — Мимимишного.
Незнакомец: — Что можно разбить тарелку или вилку?

ρBot: — Каким образом это можно сделать?


Незнакомец: — Найди лишнее: кот, тетрадь, стол, диван?

ρBot: — Гаррус Вакариан — турианец, родом с планеты Палавен



И так далее. Тем не менее, он ответил верно на 1 вопрос про цвет неба, но все же можно
подозревать, что этот вопрос очень популярен.
Так же, к ботам первого типа можно отнести известного Eviebot.
И
лл. 102. Пример реакций по типу простого бота Eviebot.
Приводим диалог и с программой Evie. Несмотря на то, что программа якобы знает русский
язык, мы все же постарались говорить на родном для нее английском:

Ч: — What color the sky?


— Какого цвета небо?

Б: — Sometimes blue, sometimes red, sometimes orange, sometimes purple, and sometimes
many other colors. But usually blue.
— Иногда синее, иногда красное, иногда оранжевое, иногда пурпурное, и иногда
многих других цветов. Но обычно синее.

Ч: — How much legs have a lion?


— Сколько ног у льва?

Б: — Sky blue its a LOT, white some


— Небесно-голубого много, немного белого

Ч: — How much legs lion have?


— Сколько ног у льва?

Б: — I have two. What I mean is SHOW that contract to me.


— У меня две. Что я имею ввиду показать, чтобы договориться со мной

Ч: — The fish and the bird is a mammals?


— Рыба и птица это млекопитающие?

Б: — And the crow eats children


— И ворона ест детей

Ч: — What is color of the lion?


— Какого цвета лев?

Б: — Blue, grey
— Синий, серый

Ч: — Find an extra: color, religion, christianity, monotheism?


— Найди лишнее: цвет, религия, христианство, монотеизм?

Б: — That makes the bible correct.


— Это делает библию верной.

О чем говорят эти и подобные ответы? Все программы первого типа выглядят разумно
лишь в случаях поддержания «светской беседы» в духе:
— Погода сегодня не очень, не так ли?
— Да, конечно. Я совсем не люблю плохую погоду. А как вам нравится сериал «Битва
престолов»?»
— О, этот сериал великолепен…
И так далее. Но в этом нет ни капли логики, ни грамма понимания. Это чистой воды
«Китайская комната».[1]
Но все возможные вопросы не только невозможно предусмотреть, их даже невозможно
просто перечислить. Поэтому, задав такой программе простой вопрос, который требует
небольшого рассуждения, — ее ответы сразу выглядят нелепо; это можно проверять
бесконечно. Становится очевидным, что здесь нельзя говорить даже об интеллекте
новорожденного, — он хотя бы в состоянии определять эмоции родителей и обучаться.

— Ситуативный бот. Это другая версия диалоговой программы, чуть более


совершенная. На протяжении всего диалога, с помощью набора словарей
и объектно-ориентированных методов в вопросах и ответах определяются некоторые
ключевые слова, касающиеся места жительства собеседника, его имени/фамилии, профессии,
возраста, семейного положения и некоторых других сведений, которые впоследствии могут
использоваться. Конечно, здесь так же используется тип шаблонного ответа, но уже
в дополнении небольшой ситуативной лингвистики.
К большому сожалению, прославившийся в 2014 году бот Евгений Гусман (Eugene
Gustman), (который можно было бы отнести к ситуативным ботам 2 типа), получивший
в 2014 году известность, как прошедший тест Тьюринга в королевском университете Рединга
(его приняли за человека 33% судей) нам не удалось обнаружить в открытом доступе в сети.
Однако, основываясь на более ранних тестах этой программы, она так же не прошла
испытания на простую логику, — отшучиваясь от вопросов или меняя тему.
Но лучшее впечатление ситуативной программы второго типа производит
чат-бот Mitsuku, кстати говоря, четвертый раз подряд получивший бронзовую медаль
премии Лебнера[2] (бронза — высший знак отличия в этом конкурсе по сей день; по крайней
мере, в 2018 году). К слову, Eugene Gustman получал лишь 2 место премии Лебнера
в 2012 году.

Общение с Mitsuku от Pandorabots местами приятно удивляет: этот бот был в состоянии
корректно ответить на пару простых предметных вопросов, хорошо запоминал имя
собеседника и географию, местами умело жонглировал фразами и не так грубо уходил
от незнакомых выражений. Он явно заслужил того, чтобы здесь привести полный диалог
с ним.

Б: — I am Mitsuku. I want to be your friend.


— Меня зовут Митсуку. Я хочу быть твоим другом
Ч: — Hi! Can I ask you some questions?
— Привет! Могу я спросить несколько вопросов?

Б: — Hi there. Of course. What do you want to know?


— Привет. Конечно, что ты хочешь узнать?

Ч: — What color is the lion?


— Какого цвета лев?

Б: — Hmm, a lion looks brownish to me.


— Хмм, лев выглядит коричневато для меня

Ч: — How much legs a lion have?


— Сколько ног имеет лев?

Б: — How much do you think?


— Сколько, как думаешь?

Ч: — I know, but i want to get your answer


— Я знаю, но я хочу получить твой ответ

Б: — Where did you learn that from? I just told you it.
— Откуда вы это узнали? Я просто сказал тебе это.

Ч: — Find an extra: pen, cat, book, table, sofa?


— Найди лишнее: ручка, кошка, книга, стол, диван?

Б: — I would look in a lounge for a sofa


— Я бы посмотрел в гостиной для дивана.

Ч: — Human is a fish?
— Человек это рыба?

Б: — My creator is a human
— Мой создатель это человек

Ч: — Two plus three how much?


— Два плюс три сколько будет?

Б: — Are you a math teacher?


— Ты учитель математики?

Ч: — just answer two plus three


— Просто ответь два плюс три

Б: — Do you like playing video games?


— Тебе нравится играть в видеоигры?

Ч: — What color is the sky?


Какого цвета небо?
Б: — The sky is blue
— Небо синее

Ч: — The fish and the bird is a mammals?


— Рыба и птица это млекопитающие?

Б: — Is it really? Ok I will remember that


— Серьезно? Ок, я запомню это

Ч: — My name is Serge, can you remember?


— Меня зовут Сергей, ты можешь запомнить?

Б: — Oh yes I remember now. Hi Serge. I think I can, don’t you?


— О да я запомню. Привет Сергей. Я думаю, я могу, а ты?

Ч: — Thanks
— Спасибо

Б: — You are a very polite person. Your mother raised you well.
— Ты очень вежливый. Твоя мать хорошо воспитала тебя.

Ч: — What is my name?
— Как меня зовут?

Б: — Your name is Serge


— Тебя зовут Сергей

Ч: — Ok. I am from Tyumen, Russia. And you?


— Ок. Я из Тюмени, Россия. А ты?

Б: — Ugh. Are you currently in Tyumen Russia? I am in Mousebreaker’s home in Leeds.


Where are you?
— Уф. Ты сейчас в Тюмени, в России? Я нахожусь в доме Маусбрейера в Лидсе.
Где ты?

Ч: — Siberia
— Сибирь

Б: — I have no idea where that is. Tell me a little about your life in Siberia.
— Я понятия не имею, где это. Расскажи немного о своей жизни в Сибири.

Ч: — Here is cold
— Здесь холодно

Б: — I fail to see the relevance of that allusion.


— Я не вижу значимости этой аллюзии.

Ч: — Ok. What do you think, how much kilometeres from my place to your?
— Ок. Как ты думаешь, сколько километров от моего места до тебя?

Б: — I see. I haven’t thought much about how much kilometeres from your place to my, so
I don’t have a good answer for you.
— Понимаю. Я не очень много думал о том, сколько километров от твоего места
до меня, поэтому у меня нет хорошего ответа для тебя.

Ч: — What is bananas and tree color?


— Какой цвет у банана и дерева?

Б: — More than one banana. Hmm, a tree looks brown with green leaves to me.
— Больше одного банана. Хм, дерево выглядит коричневым с зелеными листьями.

Ч: — What can i broke: the dish or spoon?


— Что я могу сломать: блюдо или ложку?

Б: — You can do whatever you want


— Ты можешь делать все, что захочешь.

Ч: — The shark is the fish?


— Акула это рыба?

Б: — Is it really? Ok I will remember that


— В самом деле? Ок, я запомню это

Ч: — Ok, thanks. Bye


— Ок, спасибо. Пока

Б: — Yeah that’s right. Are you going? Ok, good evening, afternoon err. morning madame.
— Да, это так. Ты собираешься уходить? Хорошо, добрый вечер день полудня
утром мадам.

Ч: — What is my name?
— Как меня зовут?

Б: — Your name is Serge


— Тебя зовут Сергей

Ч: — From were are my?


— Откуда я?

Б: — What else is from there?


— Что еще оттуда?

Ч: — Were i am situated?
— Где я нахожусь?

Б: — You said you were in Siberia


— Ты сказал ты находишься в Сибири

Ч: — Thanks a lot. Bye again


— Спасибо. И еще раз пока.

Б: — Don’t mention it. Once more? Until next time Serge.


— Не упоминай об этом. Еще раз? До следующего раза Сергей
Ч: Ok

И
лл. 103. Фрагмент диалога с Mitsuku, диалоговой программой второго типа.
И
лл. 104. Mitsuku помнит месторасположение и имя собеседника.
Что в этом диалоге было полезного? Программа запомнила важные вещи: имя собеседника
и название его географического положения. Верно ответила на два тестовых вопроса (о цвете
неба и льва) и изящно увернулась от обсуждения других, при этом, следуя некоторой логике,
сценарию разговора.
Теперь перейдем к следующему типу программ.

Голосовой помощник
Помимо некоторого функционала первого и второго типа, они активно используют
поисковые алгоритмы, в том числе, достаточно сложные — для прокладывания маршрута,
заказа такси или пиццы; кроме того они умеют использовать прикладные программы для
несложных задач — чтения и отправки электронной почты, голосовых вызовов, установки
будильника, вызова карты и т. п.
И
лл. 105. Презентация возможностей голосового помощника «Алиса», от компании «Яндекс».
Приведем диалог с голосовым помощником «Алиса», которому мы задали схожие вопросы.
В чем-то она нас порадовала, а в чем-то огорчила. Она верно ответила на вопрос о цвете неба
(правда переадресовав вопрос), и не вполне верно — о цвете льва, так же положившись
на информационную ссылку на некий ресурс.
И
лл. 106. «Алиса» начинает диалог достаточно оптимистично.
И
лл. 107. Из серии предметных вопросов «Алиса» ответила только на простой
арифметический. Продолжение диалога с «Алисой» не приносит результат. Она
не запоминает имени собеседника и не может отгадывать загадки.
Подведем небольшое резюме. Вопросы типа «Найди лишний объект» или «Найди общее»
ставят голосового помощника в тупик, и он переадресовывает их установленному
поисковику. Помощник не запоминает имени пользователя (по крайней мере
в десктоп-версии). В этом «Алиса» схожа с простым ботом первого типа. Конечно же,
невозможно обойти в этом вопросе и давнего конкурента «Алисы», голосового помощника
от компании «Apple», приложение к iPhone, «Siri». На следующей иллюстрации —
некоторые презентационные возможности «Siri».
И
лл. 108. Примеры полезных функций голосового помощника «Siri» от Apple.
Но на практическом прогоне нашего теста на понимание смысла приложение показало
далеко не лучшие результаты (Илл. 109—111).
Иллюстра
ции 109—111. Диалог с «Siri».
Плюс «Siri» оказался в способности открыть калькулятор для простого вычисления.
А за акулой — она отправила нас в ближайший рыбный магазин. Однако на вопрос-загадку
голосовой помощник не только не ответил, но и стал задавать дополнительный вопрос; то же
произошло и при попытке представиться. Кроме того, многие вопросы «Siri» была
не состоянии даже распознать, так что задать корректно вопросы «Пара сложение тройка
сколько будет?» и «Какого цвета неба?» не представилось возможным.
Из этого мы можем сделать печальный вывод, что современные диалоговые системы
в своем роде полезны, но чрезвычайно далеки от адаптивного, корректного понимания
смысла.

Сильная логическая машина


Этот тип программы (или нескольких программ, объединенных в одном интерфейсе),
несмотря на некоторые попытки создания[3] пока не существует, но к его реализации
следует стремиться..

Итак, мы постараемся сформулировать, какой следует быть сильной логической


машине:
А) Решать задачи различного уровня сложности, от самых простых (типа «найди
лишнее») до сложных, со многими неизвестными и предварительными подсчетами. Эти
задачи могут быть описаны в свободной форме на естественном языке и для их решения
необходимо применять общедоступные методы логики с привлечением информации
из других дисциплин. При этом, машина должна иметь возможность разбивать большую
задачу на несколько подзадач и уметь находить нужную информацию и методы для ее
решения, из которых генерировать собственные правила обработки.
Б) Автономно обучаться. При этом машина должна не только адекватно усваивать
новые знания, но и относиться критически к получаемой информации, проверять ее и делать
собственные выводы.
В) Понимать содержание диалога. Разделять и запоминать собеседников; вырабатывать
стратегии общения в зависимости от личного отношения к собеседнику; иметь личное
отношение и мнение о том или другом предмете разговора.
Г) Разделять долгосрочные цели и оперативные. Это означает, что машина может
принять своей долгосрочной задачей обучение японскому языку или квантовой механике,
но должна приоритетно решать оперативные задания.
Д) Иметь возможность интегрироваться в любом аппаратном исполнении. Это
означает, что программа должна в полной мере уметь «осознавать» свое местоположение
и тип системы, а также обучаться для того, чтобы уметь распоряжаться полученными
аппаратными ресурсами, оценивать ситуацию и перемещаться на другие аппаратные
ресурсы.
Один пункт отделяет эту систему от так называемого сильного искусственного
интеллекта (СИИ) и достижения сингулярности, для реализации которого можно было бы
поставить пункт «Е» — принимать самостоятельные решения». (Хотя, по всей видимости
и постановка целей также может быть частично связана с пунктом «Е»).
Как видно из описательной части программы типа 4, в данной книге мы фактически
занимаемся реализацией сильной логической машины и если не полным, то частичным
решением пунктов «А», «Б» и «В». Но даже эти три пункта даются очень нелегко. Это
противоречит устоявшемуся популистскому мнению о том, что машина может получить
некоторое свойство, которое позволит ей «умнеть» за миллисекунды и превращаться в некий
«супермозг». Да, скорости компьютера отличаются от человеческих, но чтобы
«переваривать» больше информации потребуется и больше времени. Что имеется ввиду?
Человек ориентируется на 1-2-3 фактора о каком-то понятии, он тратит время и спрашивает,
если что-то не понимает. Спрашивать и уточнять — это свойство, делающее нас умными. То
есть формулировать, генерировать конкретное свойство-уточнение и озвучивать его
доверенному собеседнику. Почему же считается, что с компьютером должно быть иначе?
Перефразируя, можно сказать, чтобы человек стал умнее — его нужно долго учить.
Различными методами, день за днем. Проводить практические занятия, сопоставлять
результаты экспериментов, и т. д. С роботом — не может быть иначе. Его тоже нужно учить
каждый день, следить, чтобы он ничего не «запорол» и правильно развивался.
Как вы уже успели заметить, в рассмотренных примерах с другими ботами мы
не требовали от них ничего экстраординарного. Все упомянутые вопросы, как то «Сколько
ног у льва», «Найди лишнее», и другие решаются с помощью технологии MSM, что делает
эту систему ближе к сильной логической машине.
Но есть некоторые культурные аспекты в понимании искусственного интеллекта,
которые мы не можем не затронуть.

Культурный феномен искусственного интеллекта


Когда мы говорим об искусственном интеллекте, многие оказываются в заблуждении из-за
культурного феномена, формирующего искаженное общественное мнение.
Сначала, попробуем разобраться в самом термине «Искусственный интеллект». Для
программистов все просто: это область науки, занимающаяся разработкой программ,
решающих некоторые интеллектуальные задачи. Что можно считать интеллектуальной
задачей? Например, распознавание образов, текста и голоса. Если обобщить, эта сфера
относится к вопросу принятия решений без участия человека. С этой позиции и электронный
калькулятор можно назвать искусственным интеллектом, однако этого никто не делает,
предполагая, что решение интеллектуальной задачи должно быть несколько сложнее
обычного алгоритма последовательных действий.

И
лл. 112. Механический калькулятор «Alpina», созданный инженером Окаром Милднером
в 1958 году, едва ли кто-то называл «Искусственным интеллектом» — по причине его
доступности и «овеществленности».
Не исключено также, что люди привыкли ставить вызовы искусственному интеллекту,
не называя таковым уже то, что было реализовано с помощью, например, механических
средств.
Так в понимании этого термина появились некоторые дополнительные критерии.
Во-первых, на принятие решений в системе должен влиять не один, а несколько (или много)
факторов, которые заранее сложно или невозможно предусмотреть; а во-вторых, электронная
система должна уметь самообучаться, совершенствоваться без участия или при
минимальном участии человека. Но и в этом подходе есть значительный пробел. С такой
позиции мы не можем рассматривать даже самого человека как интеллектуальную систему,
ведь на его обучение уходят годы и десятилетия, прежде чем появится возможность говорить
о наличии у него интеллекта. Поэтому нам следует сделать скидку на то, что
интеллектуальная система может длительное время обучаться с помощью учителя или
большой выборки обучающих корпусов, как в случае с искусственными нейросетями.
Между тем, с точки зрения обычного человека ассоциативные реакции рождают
несколько иное понимание. В первую очередь нам вспоминаются известные и яркие фильмы,
в которых авторы сценария воплотили свое видение этого феномена. Постараемся вспомнить
некоторые из них, наиболее известные.

И
лл. 113. Терминатор, персонаж одноименного фильма «The Terminator», 1984 г. Режиссер
Джеймс Кэмерон.
1. Терминатор.
Предыстория: Киборг прибывает в настоящее время из мрачного будущего, в котором
человечество оказалось в угнетении со стороны жестоких машин, поставивших себе целью
уничтожение всех людей на планете. В 1984 году у терминатора есть цель — уничтожить
мать будущего лидера человеческого сопротивления, Сару Коннор.
Проанализируем, какими человеческими (антропоморфными) и нечеловеческими
качествами наделили его авторы.
Человеческие качества: Терминатор умеет ориентироваться на местности и разделять
текущие задачи и главные. Например, его текущая задача — найти одежду и оружие,
а главная — уничтожить Сару Коннор. В процессе поиска одежды и оружия он также строит
и промежуточные задачи: обороняться, нападать, вести переговоры и не выделяться
в социальной среде. Он умеет планировать свои действия и успешно коммуницировать,
адаптироваться в социуме с целью достижения главной задачи. Умеет распознавать
образную информацию (например, рукописный текст в записной книжке).
Нечеловеческие качества: Отсутствие эмоций и необходимости в питании. Наличие
чрезвычайной силы и выносливости. Умение имитировать любой голос и управлять любой
техникой без опыта управления.
И
лл. 114. Демотиватор с использованием легендарной фразы компьютера Hal 9000 из фильма
«Космическая одиссея 2001» (1968 г., режиссер Стэнли Кубрик): «Мне жаль, Дейв. Я боюсь,
что не могу это сделать».
Компьютер «Хал 9000» из фильма «Космическая одиссея 2001» — суперкомпьютер,
управляющий космической экспедицией к Юпитеру.
Предыстория: Компьютер ошибочно оценивает угрозу для работоспособности одного
из модулей корабля. Но проверка людьми показывает, что модуль в порядке, — т.е. они
считают, что Хал допускает ошибку, что подтверждается при симуляции на аналогичном
компьютере на земле.
Поскольку компьютер управляет всеми функциями корабля, для предотвращения
возможной катастрофы участники команды принимают решение отключить компьютер.
Но сам Хал убежден, что не может принимать неверных решений и ошибку могут допустить
только люди.
Когда он понимает, что люди приняли решение об его отключении, то воспринимает это
как личную угрозу и начинает обороняться, — принимает решение убить всех членов
экспедиции для обеспечения собственного выживания.
Вот его рейтинг качеств:
Человеческие качества: — Умение адаптироваться к жизни в человеческой среде.
Высокая самооценка, самолюбие. Способность обманывать. Безжалостность
и изобретательность. Способность жертвовать второстепенными задачами (как например,
жизнью команды). Умение планировать.
Нечеловеческие качества: — Сверхнавыки: способность к беспроигрышной игре
в шахматы.
И
лл. 115. Персонаж с искусственным интеллектом Дэвид. Кадр из фильма «Искусственный
разум». 2001 г, режиссер Стивен Спилберг.
Искусственный мальчик Дэвид из фильма «Искусственный разум».
Предыстория: Действие происходит в недалеком будущем. В семье инженера
случилась беда: его единственный сын впал в кому из-за серьезной травмы. В то же время
на предприятии, выпускающем роботов, решили попробовать производить новую линейку
роботов-детей, испытывающих эмоциональную привязанность к родителям. Робот Дэвид,
опытный образец этой серии, оказывается в семье. И все бы хорошо, но настоящий сын
инженера выздоравливает, начинает ревновать и строить козни своему искусственному
конкуренту. В результате серии недоразумений электронный мальчик оказывается на улице
и ставит перед собой единственную цель, чтобы его мама полюбила его. Преодолев
множество препятствий и спустя 10 000 лет при самых странных обстоятельствах, Дэвид
достигает своей цели.
Человеческие качества: Эмоциональная привязанность. Социальная
адаптированность, отзывчивость. Целеустремленность.
Нечеловеческие качества: Способность жить вечно.

И
лл. 116. Кадр из фильма «Я, робот» («I, robot», 2004 г. Режиссер Алекс Пройас).
Робот Санни из кинофильма «Я, робот».
Предыстория: Разумные роботы прочно вошли в жизнь людей, как универсальные
помощники и успешно проникли во все сферы жизни. Поведением всех роботов управляет
функция универсальной защиты — три закона робототехники.[4] Однако ситуация выходит
из-под контроля и Вики, главный компьютер монополиста по производству роботов
компании «USR», принимает решение обеспечить безопасность людей с помощью
тоталитарного управления. Начинается революция, в которой роботы компании пытаются
полностью захватить власть над людьми. Необычный робот Санни, не имеющий в своей
операционной системе функции трех законов и системы получения обновлений, помогает
людям одержать победу над Вики и ее армией роботов.
Человеческие качества: Эмоциональный, сочувствующий. Любознательный.
Адаптивный в социальных отношениях. Видит сны. Интуитивно реагирует
на обстоятельства.
Нечеловеческие качества: Сверхсила и скорость.

Можно перечислять разумные машины из сферы киноискусства бесконечно долго,


но мы всегда найдем определенные закономерности.

Что общего у всех героев этих фильмов?

Все они существуют и адаптируются в социуме. Они адекватно реагируют в социальном


пространстве.
И следует заметить, это — главное чего ожидает обычный человек, когда слышит
об искусственном интеллекте. Он ожидает увидеть свою копию. Антропоморфный образ.
Культурные реакции человека, его поведение. Что это означает? Они хотят, встретив такого
робота или киборга, быть уверены не только в том, что он узнает их, будет помнить предмет
недавнего разговора; будет испытывать симпатию или сочувствие, помогать в личных делах,
испытывать сильные эмоции: гнев, страх или любовь.
В этом есть отличие научного подхода к искусственному интеллекту большинства
ученых и культурных ожиданий от этого.
Большинство ученых и разработчиков программного обеспечения прекрасно понимают,
что как раз разнообразные эмоции проще всего симулировать, особенно в диалоговых
системах. Поэтому тест Тьюринга может быть провальной идеей. Обычный,
незаинтересованный человек воспринимает реакцию узнавания и эмоциональную окраску
выражений, как антропоморфный признак и легко может быть сбит с толку такой реакцией,
признав ее «разумной».
Поэтому диалоговые системы представляют собой самое масштабное поле
всевозможных фальсификаций. Вспомните бота Митсуку. Он действует как раз по этому
сценарию: главная его функция — запоминать основную информацию о своем собеседнике
и эмоционально окрашивать свои ответы; а в случаях затруднений, отвечать вопросом
на вопрос, заставляя собеседника переключиться.

Но реальный признак разумности, это не эмоциональность, и не способность запомнить


имя или несколько географических названий. Это способность понимать смысл значений.
Смысл — это феномен относительности взаимосвязей одного понятия относительно
другого и сохранение стабильности а также принятие этих изменений при колебаниях
понятийных классов. Понимание смысла — это возможность делать схожие выводы при
применении различных операционных правил со смыслами.
Так смысл слова «корова» заключается в его относительности по отношению к «волк»
или «лев», а также в возможности оперирования им так же и в форме, например «буренка».
Понимание отношений и сохранение информативности классов составляет весь
комплекс значений и необходимую тяжесть для сознательного решения.
В свою очередь, комплекс решений MSM обладает достаточной функциональностью
для обеспечения всей сложности этих взаимосвязей; возможно только, что нам недостает
некоторых операционных правил. Впрочем, с учетом свойств операбельности кодов MSM
эта задача становится вполне достижима.

[1] Китайская комната (англ. Chinese room) — мысленный эксперимент, опубликованный


Джоном Серлом в 1980 году. «Представим себе изолированную комнату, в которой
находится Джон Сёрл, который не знает ни одного китайского иероглифа. Однако у него
есть записанные в книге точные инструкции по манипуляции иероглифами вида „Возьмите
такой-то иероглиф из корзинки номер один и поместите его рядом с таким-то иероглифом
из корзинки номер два“, но в этих инструкциях отсутствует информация о значении этих
иероглифов и Сёрл просто следует этим инструкциям подобно компьютеру.» В такой
ситуации наблюдатель может отправить в комнату любой осмысленный вопрос и получить
вполне осмысленный ответ, но Сёрл не понимает ни изначального вопроса, ни ответа,
который сам составил. Наблюдатель, в свою очередь, может быть уверен, что в комнате
находится человек, который знает и понимает иероглифы. Информация из Wikipedia.org.
[2] Премия Лебнера (англ. Loebner prize) — премия, присуждаемая победителю
ежегодного конкурса «AI Loebner» (проводится с 1990 г.), в котором соревнуются
программы в прохождении теста Тьюринга. Наиболее «человечной», по мнению судей,
вручается премия в $2000.Первой программе, которая пройдёт стандартный (текстовый) тест
Тьюринга, будет вручена серебряная медаль и вознаграждение в $25000. Первой программе,
которая пройдёт этот тест с использованием текстового, визуального и звукового
подтверждения, будет вручена золотая медаль и приз в 100,000$. После вручения золотой
медали конкурс будет закрыт. Информация — Wikipedia.org.
[3] Проекты CYC или IBM Watson можно считать хорошими, но не в полной мере
реализованными попытками. Cyc (произносится Сайк) — проект по созданию объёмной
онтологической базы знаний, позволяющей программам решать сложные задачи из области
искусственного интеллекта на основе логического вывода и привлечения здравого смысла.
Проект начал Дуглас Ленат в 1984 году. Типичным примером знаний в базе являются
«Всякое дерево является растением» и «Растения смертны». Если спросить «умирают ли
деревья?», машина логического вывода может сделать очевидный вывод и дать правильный
ответ. База знаний содержит более миллиона занесённых туда людьми утверждений, правил
и общеупотребительных идей. IBM Watson — суперкомпьютер фирмы IBM, оснащённый
вопросно-ответной системой искусственного интеллекта, созданный под руководством
Дэвида Феруччи. Его создание — часть проекта DeepQA. Основная задача Уотсона —
понимать вопросы, сформулированные на естественном языке, и находить на них ответы
в базе данных.
Watson состоит из 90 серверов IBM p750, каждый из которых оснащён четырьмя
восьмиядерными процессорами архитектуры POWER7. Суммарный объём оперативной
памяти — более 15 терабайт. Система имела доступ к 200 млн страниц структурированной
и неструктурированной информации объёмом в 4 терабайта, включая полный текст
Википедии. Определения Wiki.
[4] Три закона роботехники в научной фантастике — обязательные правила поведения
для роботов, впервые сформулированные Айзеком Азимовым в рассказе «Хоровод» (1942).
Законы гласят: 1. Робот не может причинить вред человеку или своим бездействием
допустить, чтобы человеку был причинён вред. 2. Робот должен повиноваться всем
приказам, которые даёт человек, кроме тех случаев, когда эти приказы противоречат
Первому Закону. 3. Робот должен заботиться о своей безопасности в той мере, в которой это
не противоречит Первому или Второму Законам.
Глава 4. Контекст и волны

Полисемия: волновое решение


Мы не станем углубляться в специальную терминологию и рассматривать теоретическую
базу по проблематике полисемии.[1]
Стоит только заметить, и подтвердить распространенную лингвистическую теорию
о том, что причиной возникновения полисемии у человека оказалась потребность экономии
языковых значений. Так, имея в своем обиходе достаточно ограниченный набор слов,
человеческий индивид пытался выразить смыслы, не находящие отдельного значения в своей
языковой базе. И чем более часты, употребительны слова в речи, тем чаще они становятся
носителями нескольких смыслов.
По существу, нас, как разработчиков программного обеспечения, не только механизм
адекватной реакции на определенные запросы, но и способы восприятия нужных смыслов,
а также их практическое использование.
Но как может происходить восприятие многосмысленных предложений в нашем мозге?
Очевидно, что мозг воспринимает многозначность слов параллельно, или иначе говоря,
одновременно. Но что означает эта одновременность? Она может означать, что на разных
«полках» мозга, в различных уголках коры, располагаются смыслы одного и того же слова,
и в момент когда мозг «получает» на вход предложение, в котором встречаются слова
многозначные, он моделирует варианты волн предложений, в которых те или иные слова
носят разные смыслы. Мозг не может рассматривать каждое слово в отдельности, ведь это
заняло бы у него слишком много времени, вероятнее всего, он моделирует варианты
ситуаций целиком, в которых нужный смысл либо откликается, либо теряется. Приведу
пример.
Когда одна девушка на пляже говорит другой «Ты не поверишь, меня сегодня ухватил
за ногу рак», она прекрасно понимает, что под словом «рак» имеется ввиду членистоногое
существо, а не тяжелое смертельное заболевание. Но мозгу второй девушки, к которой
поступила на вход эта фраза — немного сложнее.
В нем находят отклик по существу одновременно 8 вариантов фраз (жирным выделена
фраза, адекватная реальности):
— Ухватил (схватил) за (снаружи) ногу рак (ракообразное);
— Ухватил (схватил) за (сзади) ногу рак (онкология);
— Ухватил (схватил) за (сзади) ногу рак (ракообразное);
— Ухватил (образовался) за (снаружи) ногу рак (ракообразное);
— Ухватил (образовался) за (сзади) ногу рак (онкология);
— Ухватил (образовался) за (сзади) ногу рак (онкология);
— Ухватил (образовался) за (снаружи) ногу рак (ракообразное);
— Ухватил (схватил) за (снаружи) ногу рак (онкология).
Жирным — выделен объективный вариант произошедшего. И ее мозг на доли
миллисекунд атакует этот взвод вариантов. Мышление ставится перед выбором, на каком
варианте остановиться. Пользуясь накопленным опытом в виде образов и семантических
штампов похожих предложений, он склоняется к варианту случая с членистоногим.
Параллельно, большая часть вариантов может отметаться как абсурдные, невозможные, —
это предположение, что в ноге подруги обнаружили раковую опухоль. Но этому
противоречит весь накопленный опыт, — в частности, излишняя легкомысленность фразы,
поэтому вариант признается нежизнеспособным и угнетается. Весь это процесс может
занимать в коре мозга считанные миллисекунды, и он несознателен, поэтому его детализация
практически невозможна. Таким образом, мозг уловил нужный смысл и оперирует теперь
непосредственно только им, одним смыслом, а не несколькими. И он также будет
оперировать только одним смыслом, когда она ответит «Вот это да! Где ты его нашла?».
Сложно утверждать, что последовательность действий мозга является именно такой.
Но все же, как теоретический, такой вариант организации процессов вполне жизнеспособен.
Но как мы можем оцифровать этот процесс? Возьмем пример предложения, в котором
встречаются несколько многозначных слов:
«Мы подошли к развалинам старого замка.»
В данном случае из одного предложения может быть сгенерирована волна, в которой
в различном порядке встречаются различные смыслы. Поскольку в данном случае можно
отметить 3 слова, имеющих по 2 смысла, это многозначности «Мы», «Развалины» и «Замок»,
мы генерируем варианты, в которых встречаются все значения в любом возможном
порядке (вновь жирным выделены те варианты, которые имеют право на существование):
— Мы (двое) подошли к развалинам (старикам) старого замка (механизм).
— Мы (группа) подошли к развалинам (руинам) старого замка (постройка).
— Мы (двое) подошли к развалинам (руинам) старого замка (механизм).
— Мы (двое) подошли к развалинам (старикам) старого замка (постройка).
— Мы (группа) подошли к развалинам (старикам) старого замка (постройка).
— Мы (двое) подошли к развалинам (руинам) старого замка (постройка).
— Мы (группа) подошли к развалинам (руинам) старого замка (механизм).
— Мы (группа) подошли к развалинам (старикам) старого замка (механизм).
Как вы понимаете, жизнеспособны из всего вышеперечисленного только два варианта,
2 и 6. Но как понять это машине?
Здесь нам необходимо выбрать тот вариант, который подходит нам в рамках «опыта»
и контекста. Какие методики могут здесь использоваться?
Во-первых, это обучение. Мы должны обеспечить необходимой обучающей базой
смыслов (а не слов) систему, с той целью, чтобы устойчивое выражение «Развалины старого
замка» воспринимались предпочтительно в смысле «Руины старой постройки», путем
сохранения этих фразеологизмов смыслов в словарях. Конечно, этот путь долог и сложен,
однако не является невыполнимым. Второй путь более прост, но зыбок, — это позволить
анализировать текст программе самостоятельно. Здесь система может строить
предположения, исходя из схожести смыслов расположенных рядом слов. И отчасти этот
путь верен, вот только в приведенном примере слово «Развалина» может быть
интерпретировано как «Старик» по той причине, что рядом с ним находится слово «Старый»,
но с той же вероятностью может быть принят и верный вариант, на основании того, что
рядом с «Развалинами» (как постройка) находится и «Замок» (как постройка). Тем не менее,
с помощью этого метода мы можем сократить степень неопределенности волны, по крайней
мере, вдвое. И это тоже неплохой результат, который может быть улучшен с помощью
сохраненных моделей и накопленного «опыта».
«Опыт», как маленькая хитрость, может быть сохранен как в свойствах объектов, так
и в отдельном словаре контекста. Он будет подталкивать систему к верному выбору, чтобы
определять значения точно, или по крайней мере, с высокой долей вероятности.
Но начнем по порядку.

Генерация волны
Наша техническая задача на данном этапе состоит в том, чтобы при поступающем на вход
предложении на естественном языке система определяла многозначные элементы
и генерировала исчерпывающее количество вариантов закодированных предложений.
Рассмотрим, как превращается в волну предложений пример, рассмотренный выше (См.
илл. 117).
И
лл. 117. Из фразы «Мы подошли к развалинам старого замка» генерируется 16 предложений
волны. 16, а не 8, — поскольку слово «подошли» тоже трактуется двумя смыслами,
соответственно 2х8=16. Так из одного предложения на естественном языке было
сгенерировано 16 уникальных предложений на «языке» MSM с использованием различных
смыслов всех упомянутых слов.
Как вы помните, при сохранении дополнительных вариантов тех или иных значений слов,
мы добавляем к оригинальному написанию слова символы «|» и их число растет
в зависимости от количества добавленных значений. Из всех возможных генераций
различных смыслов рождаются такие «волны предложений».
Следует рассмотреть эту процедуру более предметно, поэтому приведем ее листинг
полностью.
Илл.
118. Листинг процедуры Readwave, генерирующей «волну предложений» из исходной фразы
на естественном языке.
Как видно, здесь мы использовали несколько еще незнакомых процедур: Formingtemp,
Findvariants и Randomcount с вложенными функциями Countit и Getcount.
Приведем также и их.
И
лл. 119. Листинг процедуры Formingtemp, которая создает временный словарь, который
затем и используется вместо обычного словаря. Это делается для ускорения работы всех
процессов, использующих словари слов-множеств.
И
лл. 120. Листинг процедуры Findvariants, генерирующей множества вариантов отдельных
значений слов-множеств.
И
лл. 121. Вспомогательная процедура countit и функция getcount, которые используются
в процедуре Randomcount.

И
лл. 122. Листинг процедуры Randomcount, производящей смешанные значения из исходных.
Теперь, поиграем с процедурой Readwave, составив небольшую программу.

И
лл. 123. Листинг программы с тестовой демонстрацией возможностей процедуры Readwave.
Посмотрим еще раз, как происходит генерация волны на практике с другими фразами.

И
лл. 124. В тестовой процедуре цветом выделены исходные фразы, ниже — генерация волны
предложений. К примеру, здесь в одном из значений фразы «Твои слова убивают меня»
самое длинное предложение обозначает что «Твои слова расстраивают меня»; вероятно,
данный смысл здесь и можно считать самым верным.
Рассмотрим логическую последовательность действий, происходящих в процедуре
Readwave:
A: «Читаем» предложение по словам, по умолчанию взяв первые значения слов.
B: Отмечаем наличие дополнительных значений, при их наличии.
С: В случае наличия дополнительных значений, генерируем предложения где значения
выбираются в случайном порядке.
D: Дополнительные значения берутся также и из отдельного словаря синонимов
в случайном порядке.
E: Если полученного в результате генерации предложения из кодов нет в списке
результатов, то добавляем его туда.
F: Повторяем процесс генерации до тех пор, пока из него не перестают «вываливаться»
новые предложения.
Вам может показаться, что вариантов может оказаться слишком много, но на самом деле
это не так. На практике большинство предложений «размножаются» не более чем
до 8—16 элементов, и лишь десятые доли процентов достигают значения 32-х. Так что их
анализ нельзя назвать «взрывом» или чем-то подобным; анализ «смысловой волны», как ее
можно назвать, получается достаточно рядовым, хотя и вероятностным явлением.
Говоря «вероятностное» здесь имеется ввиду две вещи.
Первая, это вероятность, хотя и ничтожно малая (примерно 1 к 800 000) того, что
нужный смысл не будет определен в качестве предположения.
Вторая — это вероятность «взрыва» числа вариантов, при котором выбор нужного
варианта будет затерян в огромном числе вариантов. Как могут сложиться предпосылки
такого прогноза? По существу, такая вероятность невелика. Как я уже говорил,
в большинстве предложений русского языка используется по 1—2, редко — 3, крайне
редко — 4 слова с несколькими значениями. Поэтому единственной возможностью
составить «невозможное» предложение с большим числом многозначных слов и их
синонимов остается тогда, когда это делается специально. Теоретически возможно, что
некий джентльмен с целью сломать систему специально впишет в предложение
20—30 многозначных слов, и составит из них вопрос для такой системы. А что такое
30 полисемичных слов, даже если они имеют только по 2 значения? Это 2 в 30 степени или
1 073 741 824 варианта предложений, каждое из которых требует анализа. Такое число
вариантов едва ли сможет «проглотить» и обработать за сколько-нибудь быстрое время даже
весьма мощный суперкомпьютер. И это может оказаться слабым местом такой
интеллектуальной системы, поэтому нам следует заранее предусмотреть и подобный
сценарий развития событий. Возможно, следует просто ограничить число вариантов
фиксированной цифрой, например, 40 или 100. Что же, если их больше, — со значительной
долей вероятности можно сделать вывод, что системе кто-то пудрит мозги.
Возможно, описанный алгоритм несовершенен и достаточно медлителен. Но он
работает.
Кстати говоря, помочь в уменьшении числа анализируемых предложений «волны»
может предварительный фразеологический анализ. Действительно, если нам понятно, что
в предложении использована поговорка «Делу время — потехе час» нам нет необходимости
производить анализ этой фразы, чтобы понять, использовалось ли слово «дело» как
«канцелярская папка» или как «труд», мы можем просто заменить ее на фразу «Работа — это
хорошо» и ничего не потеряем. «Если что-то можно упростить — упрощай». Это —
основной принцип, которым можно руководствоваться во фразеологическом анализе текста.
Конечно, русский язык чрезвычайно богат различными фразеологизмами. Но встретив
«Яблоко от яблони недалеко падает» — можно «перевести»: «Он такой же как родители»
или «Она такая же, как ее мать». «Семь бед — один ответ» — переводим «Одна причина
всех несчастий», и так далее.
Нам нет необходимости из одной сложности порождать другую, практическую пользу
будет иметь лишь упрощение этой сложности. Если что-то мы может пересказать короче
и недвусмысленно, то нужно это делать.
Но вернемся к более актуальной на данный момент проблеме.

Обработка данных для волнового анализа


В свете новых возможностей, которые предоставляет нам волновая обработка данных,
следует пересмотреть технологические процедуры работы с системой, начиная с самых
простых вопросов категории: «Что такое …?», «Найди общее:…» и другие. Однако пока что
нам интересно, как при помощи волн организовать процесс расширения словарного запаса
системы.
Для начала, нам требуется сформировать исходную, достаточно насыщенную базу
закодированных слов, чтобы достигнуть «первичного понимания». Здесь не обошлось без
дополнительных «костылей» в виде морфологического словаря и соответственно, генератора
морфологических элементов.
Что парадоксально в проблеме дополнения основного словаря, — это тот случай, когда
мы можем получать возможность знать больше, когда знаем больше. Почему так
происходит?
Первая проблема, к решению которой мы обращаемся при развитии классификатора, это
обилие морфологических форм, порожденных различными временами, падежами и числами.
И ради того, чтобы иметь возможность добавлять не единичное слово, а целый рой
из словоформ, образованных одним словом, была создана распределенная система
морфологических словарей. Что такое распределенные словари? Это простая система
файловой организации, в которой один большой словарь разбирается на несколько тысяч
небольших текстовых файлов для ускорения поиска и получения данных без применения
сложных алгоритмов поиска или хеширования. Можете критиковать эту систему, но это
довольно шустро работает без подключения дополнительных модулей или еще одного
«круга формализации» (типизации), что является немаловажным плюсом. В данном случае
нашим «библиотекарем» выступает файловая система, обеспечивающая быстрый доступ
к нужной информации, а не дополнительные надстройки.
Принцип формирования распределенных словарей следующий:
— Берется исходный словарь. В нашем случае, это был довольно увесистый
морфологический словарик объемом около 200 Mb в текстовом формате.[2]
И
лл. 125. Фрагмент представления данных использованного в программной модели
морфологического словаря.
В каждой строчке словаря есть указание на падеж, число, одушевленность и другие
характеристики. Пример записи: «ящур | сущ неод ед муж им |». (Дополнительные
характеристики нам тоже могут пригодиться в будущем, поэтому также имеет смысл их
сохранить, но предварительно следует подготовить обработчик этих записей.)
— Процедура обработки записей производит следующие операции: из первых
3 символов записи (пробел игнорируется) формируется имя файла на латинице. Запись
переводится в верхний регистр. Дополнительные характеристики переводятся в числовой
код длиной в 10 символов, каждый из которых кодирует отдельную характеристику
(например 1111111201 — единственное число, существительное, именительный падеж,
мужской род, одушевленное, настоящее время, совершенная форма, непереходное, первое
значение). При отсутствии характеристики, соответствующая числовая позиция помечается
цифрой 0.
Рассмотрим и процедуру для создания распределенных словарей Morpheus,
включающую вложенную процедуру Createname. Функция у Createname только одна —
получить из строки на русском имя файла в английской транслитерации, в котором хранится
нужный раздел данных.

И
лл. 126. Процедура преобразования строки в имя файла из трех символов в английской
транслитерации.
И
лл. 127. Процедура Morpheus, создающая из одного словаря базу из нескольких тысяч
распределенных словарей.
При обработке данных в процедуре Morpheus преимущество отдается наименьшему
числовому коду в полученном блоке. Если перед нами единственное число,
существительное, мужской род, оно ставится первым в списке строки. Описательный код
следует за записью слова. Так формируется запись типа: «ШОМПОЛ
1111200000 ШОМПОЛА 1121200000 ШОМПОЛУ 1131200000 ШОМПОЛОМ
1151200000 ШОМПОЛЕ 1161200000».
И
лл. 128. Фрагмент одного из созданных распределенных словарей, файл с названием "_KS»,
содержащий все известные слова и их словоформы, начинающиеся на «ЭКС». Объем
файла — 136 Kb.
При смене буквенного кода из 3 символов, создается новый файл. Так в файлы
распределенных словарей в компактной форме сохраняются морфологические формы и их
типовые описания. Итоговое число словарей составляет около 6000, по количеству вариаций
наименований из 3 первых букв слов.
Однако и этого оказалось недостаточно для создания наиболее полной генерации
потомков из производных форм слов, поскольку линии производных тоже являются своего
рода формализацией, основанной на правилах русского языка.
Распределенные словари морфологии дарят нам многие бонусы. В первую очередь, мы
имеем возможность получать морфологическую кучу слов из одного слова с помощью
процедуры Findmorfs.
И
лл. 129. Листинг процедуры Findmorfs для получения массива морфологических форм
с помощью распределенных словарей.
Кроме того, теперь мы получаем возможность добавлять новые слова в словари множеств
MSM с помощью процедуры Addwithmorfs.
И
лл. 130. Листинг процедуры добавления слов-множеств с помощью словоформ
распределенных морфологических словарей Addwithmorfs.
Между тем, словарь в результате содержит достаточно полное описание количества форм;
просто эти записи зафиксированы в разных строках словаря.
Для перебора дополнительных форм и генерации наиболее полного числа потомков
применялась и процедура Wordsextractor, носящая следующие функции:
— На стадии первоначального анализа слова, производится перебор максимума
возможных окончаний. Первичный приоритет отдается словам с окончаниями: «-ое», «-ого»,
«-ем», далее «-ии», «-ая», «-сть», «-ые», и тд. (Полный список окончаний, хотя он может
быть и не исчерпывающим, можно посмотреть в упомянутой выше процедуре). Исходя
из приоритетности окончаний, первый вариант становится главным в линии потомков. (То
есть по умолчанию в соответствии с этим принципом «Существенное» станет родителем,
слова-множества «Существенный», «Острота» станет родителем для «Острый», «Острая»,
и т.д.)
— Генерация возможных вариантов проверяется на наличие в морфологическом
словаре, также проверяется на наличие дубликатов (которые устраняются) и сохраняется
в выходном массиве процедуры.
— Впоследствии, данная генерация вариантов словоформ в виде массива списка
предлагается для проверки и формирования линии потомков слов-множеств в основных
словарях.
И
лл. 131. Процедура обнаружения дополнительных словоформ Wordsextractor, дополняющая
возможности Findmorfs.
Таким образом, при создании записей в словаре, предлагая для записи 1 слово, мы можем
получить до 20 новых записей вариантов его потомков. Эти дополнения оказались уже
достаточным прогрессом для «ручного» введения данных, но лишь небольшим элементом
для решения задачи ускоренной автоматизации дополнения базы основного словаря. После
длительного периода «ручного» введения, когда объем данных основного словаря достиг
около 20 000 наиболее употребимых слов, можно было приступать к созданию процедур,
обрабатывающих текстовые данные толкового словаря.
Но сначала требовалось произвести удобоваримую формализацию этих данных,
поскольку записи на естественном языке едва ли были доступны для полномасштабной
работы над ними. (Например, неформализованная запись: «ДОБРОЖЕЛАТЕЛЬНЫЙ, -ая,
-ое; -лен, -льна. Желающий добра, готовый содействовать благополучию других,
благожелательный. Доброжелательные люди.» Подобный текст требовал значительной
предварительной переработки.)
Итак, что же было сделано. С помощью дополнительной обработки, удалявшей
сокращения, спецсимволы, блоки примеров и склонений, был сгенерирован новый словарь,
где та же запись в нормализованном виде выглядела так: «ДОБРОЖЕЛАТЕЛЬНЫЙ —
ЖЕЛАЮЩИЙ ДОБРА, ГОТОВЫЙ СОДЕЙСТВОВАТЬ БЛАГОПОЛУЧИЮ ДРУГИХ,
БЛАГОЖЕЛАТЕЛЬНЫЙ.»
Причем, в случаях, когда в словаре описывались несколько значений, в блоке описаний
одного и того же слова, программа перегенерировала их в ряд коротких описаний
отдельными строками. Например, запись значений слова «добрый» в оригинале словаря
выглядела так:
«ДОБРЫЙ, -ая, -ое; добр, добра, добро, добры и добры. 1. Делающий добро другим,
отзывчивый, а также выражающий эти качества. Добрая душа. Добрые глаза. Он добр ко
мне. 2. Несущий благо, добро, благополучие. Добрые вести. Доброе отношение. 3. Хороший,
нравственный. Добрые дела, 4. Дружески близкий, милый. Наши добрые друзья. Мой д.
знакомый. 5. Хороший, отличный. В добром здоровье кто-н. (вполне здоров). Д. конь. Д.
товар. Д. молодец. Добрая традиция. Доброе старое время (о прошлом; ирон.). Оставить
по себе добрую память. 6. Безукоризненный, честный. Доброе имя. 7. Действительно такой
большой, не меньший, чем то, что указывается существительным или числительным
(разг.). Осталось добрых десять километров. Съел добрых полбуханки. * Будьте добры,
будь добр — 1) форма вежливого обращения с просьбой. Будьте добры, позвоните позже; 2)
выражение подчеркнутого и настойчивого требования. Будь добр, оставь меня в покое.
Доброго здоровья приветствие при прощании с пожеланием благополучия. В добрый час!
пожелание удачи. В добрый путь — пожелание отъезжающему, а также (перен.)
пожелание успеха в каком-н. начинании. Добрый малый (разг.) — о неплохом человеке.
Добрый день (вечер), доброе утро — приветствие при встрече. Люди доброй воли (высок.) —
честные, прямые люди, искренне стремящиеся к миру, к благу народа. По доброй воле — без
принуждения, по своему желанию. Чего доброго, вводн. сл. (разг.) — возможно, пожалуй
(при ожидании неприятного). Еще, чего доброго, явится с визитом. II сущ. доброта, -ы, ж.
(к 1 знач.). ДОБРЯК, -а, м. (разг.). Добрый человек. II ж. добрячка, -и. II прил. добряческий,
-ая, -ое.»
И
лл. 132. Исходный толковый словарь, подлежащий переработке.
В результате, этот текст был переработан на удобоваримый список из 6 записей.
«ДОБРЫЙ — ДЕЛАЮЩИЙ ДОБРО ДРУГИМ, ОТЗЫВЧИВЫЙ, А|| ТАКЖЕ
ВЫРАЖАЮЩИЙ ЭТИ КАЧЕСТВА.
ДОБРЫЙ — НЕСУЩИЙ БЛАГО, ДОБРО, БЛАГОПОЛУЧИЕ.
ДОБРЫЙ — ХОРОШИЙ, НРАВСТВЕННЫЙ.
ДОБРЫЙ — ДРУЖЕСКИ БЛИЗКИЙ, МИЛЫЙ.
ДОБРЫЙ — ХОРОШИЙ, ОТЛИЧНЫЙ.
ДОБРЫЙ — БЕЗУКОРИЗНЕННЫЙ, ЧЕСТНЫЙ».[3]
И
лл. 133. Фрагмент адаптированного, переработанного словаря Prepoj. txt.
Этим занималась процедура Textprepare.[4]
И
лл. 134. Textprepare, занятая подготовкой удобоваримого текста для упрощенного словаря.
Не стоит скрывать, что внешний вид методов такой обработки оставляет желать лучшего,
но нам ведь важен результат, не так ли?[5]
Также здесь участвовала еще не описанная процедура Delbrackets.
Это очень полезная вещь, занятая корректным удалением текста, находящегося
в скобках. Казалось бы, это просто, если скобок в тексте всего одна пара. Но если их
несколько, алгоритм их удаления значительно усложняется.
И
лл. 135. Листинг процедур Delbrackets и Delkvakets, корректно удаляющих круглые
и квадратные скобки с заключенным внутри текстом.
Но, так или иначе, был подготовлен «нормализованный» толковый словарь, с которым уже
вполне возможно работать, для решения задачи дополнения словарного запаса основных
словарей ALIK и ALIK2.
Теперь можно было приступить к выполнению промежуточной цели, непосредственной
записи «моделей чтения» словаря, основываясь на строках, в которых все слова
предложения — объяснения могли быть переведены в слова-множества на основании
имевшейся базы.
В чем состоит эта идея: мы предполагаем, что объяснение в словаре имеет смысл. Когда
вы видим запись типа «А — B, С D», можно сделать предположение, что одно из слов
оказывается ближайшим родственником определяемого слова в классификаторе. И если мы
сохраняем модель пунктуации с сохранением всей конструкции, описанной
словами-множествами, то объяснение похожих идей, смыслов, или даже просто принцип
организации этой конструкции может дать нам необходимую информацию, если например,
объясняемое слово нам не знакомо.
Самый простой пример «Резак — то же, что нож».
Перевод фразы с включением модели пунктуации и указанием на ключевое слово
(родителя или потомка) может выглядеть так:
«AAADAACAABBAE AAAAAAAAFN AAAAAAABAADAABAI AAAAAAAADB
AAADAACAABBA * -, *5»
Здесь цифра 5 означает что определяемое слово «Резак» (AAADAACAABBAE) является
потомком 5-го слова в этой фразе «Нож» (AAADAACAABBA).
Накапливая значительное количество этой информации, система может выдвигать очень
точные предположения относительно того, в какое место классификатора можно сохранить
информацию о том или ином определении.
Относительно упомянутого примера, зная подобное определение о резаке, система
может выдвинуть предположение относительно другого подобного определения, например
«Зонтик — то же, что зонт». Зная слово «зонт» и не зная слова «зонтик», на основании
положения и сходства, программа предположит, что искомое слово является родственником
«Зонта», 5-го слова в этой фразе.
Но вы можете справедливо поинтересоваться, каким образом должен происходить
выбор, кем станет определяемое слово, запишется в родители, «дяди», «тети» или в «дети»
родственника?
В этом нам поможет такой инструмент, как связь.

Связи элементов
Связь — это код, имеющий длину самого длинного из двух сравниваемых слов-множеств,
который несет в себе информацию о том, как один код может быть преобразован в другой.
Код связи образован вычислением разницы между числовым кодом сравниваемых символов.
Например, связь между двумя кодами AAAA и AAAB (в направлении от AAAA) выглядит
как «AAAB». Но связь между AAAB и AAAA (в направлении от AAAB) будет выглядеть как
«AAA@». Здесь, @- это символ, предшествующий A в таблице ASCII и говорящий о том,
что необходимо перейти от текущего символа («B») к предыдущему («A»).
Если записать этот код в виде числовой последовательности, эта запись имела бы вид
«0 0 0 -1».
Но что мы будем делать, когда столкнемся с ситуацией, где связь определяется между
строками разной длины? Например, «AAA» и «AAAB»?
В процедурах чтения и записи связей Readsum и Createsum происходит следующее.
Здесь мы проводим сравнение строк, используя длину самого длинного и записывая весовую
разницу между ними, а в случае ее отсутствия, симулируем присутствие символа «точки
отсчета», «А».
И
лл. 136. Процедуры Readsum и Createsum отвечают за создание и чтение связей между
словами-множествами.
Точно такой же процесс происходит и в обратной процедуре, Createsum, за исключением
того, что там происходит сложение а не вычитание ординального значения символов.
В качестве теста, процесс нахождения связей и их проверки выглядит так:

И
лл. 137. «Code A» и «Code B» — коды, между которыми проводится связь, «Link A-B» —
получаемый код связи от кода «А» к коду «B» в результате работы процедуры Readsum;
«Check» — строка проверки восстановления кода «B» с помощью кода «A» и кода связи, что
осуществляется с помощью процедуры Createsum* (см. Приложение).
Но в вопросе о связях существуют некоторые оговорки. Предположим, что связь была
корректна для двух слов кода длиной в 4 символа, и нам необходимо ее применить
в прогнозировании поведения кода для слова-множества длиной в 6 символов. Как нам
поступить тогда? В данном случае, «в поведении» связи мы можем предположить, что нас
интересуют изменения, касающиеся «хвоста» слова-множества, и отбросить первые
недостающие символы, применяя изменения к «Хвосту». То есть, мы отбрасываем значения
относительно первых символов и применяем изменения, относительно последних 4. Это
«отбрасывание» только на первый взгляд может показаться некорректным, однако,
в практике оно применяется только в отношении схожих объектов, как «Красный»
(AAAAAAABACALA) и «Синий» (AAAAAAABACADA), «Сладкий»
(AAAAAABABAAAABBA) и «Соленый» (AAAAAABABAAAABDA), и т. д.
На рисунке 138 показан еще один пример работы процедур Readsum и Createsum.

И
лл. 138. Нахождение связей и проверка восстановления кодов из связей слов «Мысленное»
и «Простое»; «Красный» и «Синий»; «Сладкий» и «Соленый».
Как видно из приведенных примеров, близкородственные связи дают
малодифференцированный (наиболее монотонный) код связи. В данном случае код связи
между «Красным» и «Синим» выглядит как AAAAAAAAAAA9A, а код связи между
«Сладкий» и «Соленый» — AAAAAAAAAAAAAACA. Жирным шрифтом — выделены
фрагменты «головы» связи, которые могут быть отброшены в случае применения связи для
кода другой длины (более короткого или более длинного).
По существу, связь оказывается своего рода транспортным средством, которое помогает
восстанавливать или дублировать последовательности строк слов-множеств, что
соответственно, помогает переносить «поведение отношений» между двумя
словами-множествами в определенных ситуациях. И прежде всего для нас представляет
интерес поведения двух родственников, когда один из них является объясняющим
определением, ключевым родственником для другого. Конечно же, для того, чтобы
максимизировать результирующее попадание в нужный код, мы должны соблюдать принцип
комплементарности в организации классификатора. Это значит, что если мы вкладываем
значение «Синий» в обобщающее понятие «Синего», то значение «Красный» мы вкладываем
соответственно в обобщающее понятие «Красного»; так же и значение «Маленький» логично
сделать потомком «Маленькое», когда значение «Большой» оказывается потомком
«Большое». То есть, в идеале, равностепенные понятия должны иметь равное число
символов кода и недалеко расположенного общего предка (а точнее, пра- пра- пра- предка),
располагающегося на расстоянии 2—5 символов от хвоста.
Здесь следует сделать отступление для уточнения терминологии. В лингвистике есть
хорошие термины «препозиция» и «постпозиция», обозначающие расположение одного
слова (или фразы) относительно другого, соответственно, «до» и «после». В данном
контексте, препозицией связимы можем назвать применение связи в направлении кода «А»
к коду «B», а постпозицией связи — направление «В» к «А» (если изначально они
располагались в другом порядке). Таким образом, если нам известна препозиция связи и мы
можем из «А» получить «B», мы можем вычислить и постпозицию связи, — из «B» получить
«А», лишь изменив «знак» направления позиции. То есть, в приведенных выше примерах
с кодами «АААА» и «АААВ» препозицией связи будет «AAAB», а постпозицией —
«AAA@».
Итак, подведем предварительные итоги относительно работы со связями.
— При первичной записи моделей информации о связях, мы работаем, ориентируясь
на необходимую препозицию или постпозицию, в зависимости от требуемого результата.
И здесь возможны варианты, когда один код оказывается длиннее другого, что будет
отражено в записи связей.
— При чтении моделей со связями, в частности, при реконструировании посредством
связи незнакомого понятия, но близкого по родству с известным, при столкновении с кодом,
отличающемся по длине от кода связи, мы отбрасываем (или доращиваем) «голову»
исходного кода, и применяем к нему связь «с хвоста», до момента стабильного совпадения
(«АААА…”). В этом случае мы можем рассчитывать на близкое попадание в искомый код.
Что в данном случае означает «близость»? Она означает высокую вероятность
попадания нового понятия в требуемую ветку, однако не исключает и вероятность ошибки.
Для минимализации ошибок, мы можем отнестись к предположению, выдвинутому
с помощью модели связи, как к приблизительной оценке расположения искомого понятия;
грубо говоря, мы поймем в каком «районе» смотреть, и здесь нам могут помочь:
А) Дополнительный морфологический анализ объектов, расположенных на данной
ветке, ниже, или выше нее. В этом случае мы можем привлечь на помощь метод сложного
процентного сравнения, с целью найти наиболее близкую словоформу, либо словоформу,
являющуюся «представителем» обобщающего понятия, исходя из его окончания. Так мы
определим, какой из объектов уже имеющихся в классификаторе станет с наибольшей долей
вероятности будущим «отцом» незнакомого ранее слова. И это совершенно определенно
увеличивает шансы на успешный подход к полной автономизации системы в будущем.
Б) Записи свойств объектов с описаниями. В этом случае, к описанию незнакомого
слова мы можем отнестись как к форме загадки, и уточнить кандидата на «отцовство»,
статистически коррелируя показания связей и морфологии.
В) Значения-антагонисты, синонимы и весовые значения.
Итак, мы вплотную подошли к перечню задач, которые необходимо выполнить при
полуавтоматическом (как задача-минимум) и автономном (задача-максимум) получении
первичных знаний с помощью толкового словаря.

Алгоритм и процедуры полуавтоматического расширения понятий


классификатора
Теперь попробуем суммировать вышеизложенное и максимально кратко изложить этот
алгоритм:
— Прочитать новую запись в словаре, подготовленном для машинной обработки.
— Удостовериться, что определяемое слово не имеет записи в классификаторе.
— На основании полученного предложения, сгенерировать волну
предложений из слов-множеств, в которых различные смыслы слов-множеств встречаются
во всех различных сочетаниях.
— Просмотреть словарь сохраненных моделей, где каждая запись включает в себя: А)
Вариант записи предложения из слов-множеств, имеющий смысл (с этой целью они так же
предварительно отбираются из сгенерированной волны предложений). Б) Модель
пунктуации в данном предложении. В) Указание в числовом виде на связь определяемого
слова и родственника — определения. Г) Запись связи между ключевыми
словами-родственниками в формате постпозиции.
— Выбрать модель записи, имеющую максимальное сходство с одним из вариантов
предложения-волны и превышающую показатель всех прочих записей.
— Сделать предположение о родственности с каким-либо из понятий классификатора,
на основании связи в данной модели, которое корректируется с помощью морфологии
и прочих свойств предполагаемого родственника.
— Подтвердить предположение.
— Сгенерировать линию родственников на основании подтвержденных
морфологических вариантов.
— Предложить дополнительный вариант записи и в других смысловых направлениях
в случае, если «родитель» имеет другие смысловые значения.
— Записать новую ветку потомков в классификатор и их свойства — в первого
родителя. (Свойства берутся из описательной части определяемого термина).

Начнем с самого начала. Для поиска строк, модели записи которых мы можем брать,
нам понадобится процедура быстрой проверки на наличие всех слов в словарях. Этим
занимается процедура Trylines. Проверяя строки, она возвращает строку проверки,
состоящую из нулей и единиц. В этой строке каждое слово по порядку обозначается
наличием (1) или отсутствием (0) в словаре.

И
лл. 139. Листинг процедуры Tryline, в которую на вход подается строка определения
на естественном языке S, а на выход получаются: — S2 — строка проверки предложения
(в формате «01101111..»»; — Good — указание на соответствие условию (true/false); —
SM80 — массив, содержащий разбитое на слова предложение; и J — количество элементов
этого массива.
В описанном выше алгоритме нам требуется следующая картина состава этой строки S2:
«011111111..» То есть, первое значение строки определения нам должно быть неизвестно,
а все остальные — известны и в этом случае переменная Good вернет значение из процедуры
True, если это соответствие обнаруживается.
Теперь, нам потребуется процедура Writetype, осуществляющая запись моделей
в словарь моделей определений Types.
И
лл. 140. Листинг процедуры Writetype, осуществляющей запись моделей чтения
определений. Здесь S — входная строка на естественном языке, EXIT — ответ
на корректность запроса (true — если запись отсутствует и все в порядке, а false — если
запись присутствует или отсутствуют слова для записи в модели.
Использовать процедуру Writetype для получения первоначального набора моделей,
дополненного волнами предложений можно в небольшой программе по чтению
подготовленного толкового словаря Prepoj. txt. Соответственно, здесь S и S2 — строки, F50:
Text, Exit: Boolean.

И
лл. 141. Мини-программа для формирования первоначального набора моделей определений
с помощью процедуры Writetype.
Что из этого получается: первоначально мы сохраняем словарь моделей, в которой волной
генерируются все возможные смыслы и сохраняются в файл types. txt.

И
лл. 142. Содержимое словаря моделей, сформированное из волны предложений
по определениям в которых известны все слова в классификаторе.
В словаре моделей используется следующий формат записи:
— Фрагмент до символов $$ — частная запись варианта волны, например
ABABACAAAACBJ ABABACAAAACB AAAAAAAAHKIA AAAAAAAAFFEPEA
(Как видно, следующий вариант отличается написанием одного слова.
ABABACAAAACBJ ABABACAAAACB AAAAAAAAHKIA AAAAAAACCBBBBABA)
— Символы в $$ — это код связи в состоянии постпозиции, позволяющий
реконструировать слово — определение из слова-родственника в данном предложении.
— Цифры после символа «*» -порядковый номер родственника в тексте записанной
модели определения.
— В символах ^^ заключается модель пунктуации.
После чего нам следует произвести проверку корректности отдельных определений. Для
этого нам понадобится редактор моделей определений, реализуемый
в процедуре Testmodels, с использованием вспомогательной
процедуры WriteColored, которая будет помогать нам подсвечивать нужные понятия
и процедуры Trycsline, которая будет модифицировать исходное предложение в кодах
в линию предков.
И
лл. 143. Процедура проверки сохраненных моделей Testmodels, использующая
вспомогательную процедуру «подсвечивания» нужных значений WriteColored.
И
лл. 144. Процедура Trycsline обрабатывает исходное предложение из кодов слов-множеств S,
получая S2 — перевод предложения на естественный язык, S6 — генерацию всех предков
предложения S, переведенную на естественный язык.
Работа процедуры тестирования моделей достаточно удобна. В данном случае, в первой
строке — приводится оригинальное предложение, второе — то же предложение, в котором
каждое слово-множество «подрезано» с хвоста, что позволяет уточнять смысловую ветку
нахождения конкретных слов. Каждое предложение тестируется по одному. Цветом
подсвечены слова, на которые указывается связь, а пользователь подтверждает каждый
вариант символом «1», если предложение корректно.
И
лл. 145. Интерфейс процедуры проверки моделей Testmodels.
Здесь пользователь определил верными два варианта из пяти предложенных «волной
предложений». Первые три варианта не должны учитываться в моделях, поскольку в них
были даны некорректные формы употребления слова «самого» (как потомок «большой»
и дважды как «степень»). В данном случае верными формами «самого» становятся
варианты потомков «собственное» и «себя».
Таким образом, сохраняя корректные варианты моделей, мы имеем в распоряжении эталон,
который «вылавливает» корректные варианты генерации волн при выдвижении
предположений.
То есть, с одной стороны, модель предостерегает нас от того, чтобы включить
в «понимание» лишний смысл от волны, а с другой стороны сама волна гарантирует то, что
нужный смысл не будет утерян.
Для этого оптимально использовать механизм предварительного согласования
с пользователем, поскольку некоторые смыслы, сгенерированные волной, могут являться
неадекватными. Модель — должна быть идеальна и лишена лишних смыслов, которые могут
только запутывать систему.

Теперь, когда мы сохранили только корректные варианты моделей в словаре TypesR


(содержимое которого затем следует перенести в основной словарь Types. txt), нам
понадобится конструкция полуавтоматического пользовательского интерфейса, который
будет заниматься чтением толкового словаря, с предложением набора необходимых
функций: получением предположений и обработки новых данных с полноценным
использованием морфологии.

Главное действующее «лицо» здесь — процедура Readtype, которая будет читать


модель данных из словаря моделей и пунктуацию.
И
лл. 146. Листинг процедуры Readtype, читающей запись модели данных.
Здесь мы используем неописанные процедуры Percmasscheck, Readlinks и Findfantom.
Percmasscheck используется для «оптовой» проверки совпадения кодов слов-множеств,
когда в строке используется серия таких слов (предложение). В качестве ответа используется
переменная ball, содержащая оценку сходства предложенных фраз.
И
лл. 147. Листинг процедуры Percmasscheck, сравнивающей сходство фраз и слов-множеств.
Readlinks — читает закодированную строку S модели определения и преобразовывает ее
в необходимые переменные.
И
лл. 148. Листинг процедуры Readlinks, где S — входящая закодированная строка;
выходящие: sm90 — массив кодов связей множеств, smcc — числовые указания
на слово-родителя из определения, j — количество элементов массивов.
Findfantom — находит фантомные предположения о родителях определяемого из описания,
указанного в связях. Здесь: S — «фантомный» код, получаемый из предполагаемой связи
между предположенным родителем и связью, S2 — код известной части родства, Name —
исходное определяемое значение, S3 — предположение.
И
лл. 149. Листинг процедуры Findfantom, вычисляющей «фантомного» родителя для
определения, исходя из описания связи и исходного кода слова-множества.
После описания всего этого, мы первоначально строим конструкцию, которая
самостоятельно будет находить в упрощенном толковом словаре определения без известного
первого слова, но с известными остальными.
Также нам понадобится процедура Trytoget, организующая проверку исходного
предложения на наличие модели совпадения и генерирующая волну предложений.
И
лл. 150. Листинг вспомогательной процедуры Trytoget, организующей проверку
и использующей модель пунктуации и описанную выше Readtype.
Нам понадобится еще пара мелочей. Это процедуры Findcode2, со вспомогательными
вложениями Getcode и Getword. Findcode2 делает то же самое, что и Findcode, но к тому же,
находит не только слово искомого кода, но и его «отца» и «дедушку».
И
лл. 151. Findcode2 — находит кроме искомого кода еще и его предков.

И
лл. 152. Вспомогательная процедура Getword копирует слово на естественном языке
из словаря Alik.
И
лл. 153. Вспомогательная процедура Getcode копирует код из строки словаря Alik.
Теперь произведем сборку всего необходимого в нашей окончательной процедуре этого
рабочего процесса.
И
лл. 154. Процедура Reader, осуществляющая чтения толкового словаря и добавление новых
значений под контролем пользователя.
Как это выглядит? Ниже — скриншот интерфейса рабочего фрагмента программы,
работающего на основе описанной процедуры, (за исключением того, что программа
на данном этапе не читает свойства объектов и не сравнивает весовые свойства
родительского и дочернего понятия для максимизации результата). Тем не менее, даже
в таком, усеченном формате, стратегия оказывается довольно успешной.
И
лл. 155. Программа осуществляет поиск незнакомых терминов в толковом словаре. Строки
«Unknown» — незнакомые слова, «n» — число проверенных морфологических генераций,
полные строки — текущие определения словаря. В данном случае, прочитано определение
«Сопредельный», отсутствующее в основном классификаторе, где на основании словаря
моделей чтения определений и их связей выдвинуто предположение, что родительскими
элементами могут быть слова «Погранична» (вариант 1) и «Пограничный» (вариант 2).
Удачный вариант (2) выбран пользователем, на основании которого записана
морфологическая генерация из 5 потомков — «Сопредельный», «Сопредельного»,
«Сопредельному», «Сопредельным», «Сопредельном».
В данном случае полезно сохранить и второе значение сопредельный как «смежный»,
и ничто не мешает сделать это вручную в параллельно запущенном окне основной
программы.

И
лл. 156. Второе значение «Сопредельный|» указано вручную с отсылкой к родительскому
понятию «Смежный». В данном случае программой сгенерировано 5 потомков, из которых
«Сопредельный|» — прямой потомок от «Смежный», а другие 4 — «Сопредельного|»,
«Сопредельному|», «Сопредельным|», «Сопредельном|» — становятся потомками
«Сопредельный|».
Пока данный алгоритм несовершенен, но в случае статистически удачной работы механизма
и в процессе накопления большой массы моделей, пункты 7 и 9 из задачи реализации
сильной логической машины впоследствии могут быть устранены; то есть, дополнение
словаря новыми знаниями может происходить без человеческого участия.
В процессе реализации механизма запоминания нового мы также применяем
и механизмпростого дополнения морфологическими формами незнакомых слов.
Например, встретив в тексте незнакомое слово «Пришла», находящееся без связи
с определением, программа может проверить, является ли слово одним из известных
склонений. Для этого производится генерация форм данного слова, проверяемая с помощью
морфологического словаря: «Прийти», «Пришли», «Пришел», … «Пришла». Одна
из обнаруженных форм соответствует найденной с помощью генерации из известного
понятия «Прийти». Соответственно, сгенерированные термины, не обнаруженные
в основном классификаторе, мы и должны записать, как потомков известного, а в случае
наличия дополнительных смыслов, продублировать это действие в параллельную ветку.
«Прийти» — «Пришла», «Прийти|» — «Пришла|», «Прийти||» — «Пришла||» и так далее.
Это — дополнительный и более простой путь к увеличению объема знаний классификатора,
который применяется параллельно с основным.

И
лл. 157. Пример поиска новых знаний в адаптированном толковом словаре по типу
алгоритма 2, — простого сравнения морфологии и генерации словоформ, а также
дополнения параллельных веток. Здесь незнакомое слово «Народный», встреченное в одном
из предложений оказалось родственником известного «Народное». Пользователь подтвердил
предлагаемую линию потомков символом «+». (В случае некорректного предположения,
пользователь может перечислить те варианты, которые необходимо исключить из линии
генерации, указав их номера). Также программой обнаружено и второе значение слова
«Народное», — здесь линия потомков сохраняется и в нее с дополнением служебного
символа «|».
Стоит привести и примеры не совсем удачного предположения. На следующем рисунке мы
видим, как программа предполагает, что «Соскучиться» это «Качество» (1) / «Состава» (2) /
или «Состояние|» (3). (Второе значение «Состояния» в данном случае это «Состав»
в значении «Измеряемое»/ «Качество»). И если слово «Соскрести» было определено точно,
то в данном случае можно понять, что программа была сбита с толку пространной
формулировкой и малым набором моделей подобного типа.

И
лл. 158. Пример ошибочного предположения родственной связи понятия «Соскучиться», как
«Состояние|»/ «Качество»/ «Состава».
В случае, обозначенном на иллюстрации, если мы сохраним модель с упомянутой
конструкцией «Соскучиться — прийти в тоскливое состояние, почувствовать скуку», где
ключевой родственник «Скуку», являющийся потомком «Скука», будет использовать связь
с «Соскучиться», то при попадании в похожее определения, например «Обрадоваться —
прийти в возбужденное состояние, испытать радость», связь будет направлена
на ассоциацию «Обрадоваться» с «Радостью». То есть, в данном случае наша проблема
состоит только в недостаточном числе коллекции определений.

Теперь вновь вернемся к нашему основному вопросу, почему волновое представление


многозначности в MSM может быть эффективным? Ответ становится очевидным.
Имея многозначность «на входе» мы получаем однозначность — «на выходе»,
и оперируем с данной однозначностью так, как нам необходимо.
То есть, если мы имеем на вход предложение А+B+C, где C является также синонимом
D или E, нам необходимо изучить каждый случай, где предложение выглядит ABC, ABD
и ABE и определить, какие зависимости принесут определенные результаты. Конечно,
казалось бы, мы могли бы сохранить эти модели и на естественном языке. Но здесь
возникает одно большое «НО», — сложность составления зависимостей моделей,
и отсутствие комплементарного кода связей элементов, что усложняет данную модель
до невероятности. Таким образом, например, вместо того чтобы описать всех предков
элемента «привлекательность» в форме одного кода из 17 символов, (как в многомерном
множестве), если мы захотим сохранить всю глубину его смысла, нам придется
рекомбинировать с помощью объектного программирования, минимум, 17 слов. 17 слов или
17 символов — это большая разница, в среднем — десятикратная. Но в случае
с многомерным множеством мы имеем возможность дополнительно оперировать с каждым
из вариантов, сравнивать, и применять их в дополнительных правилах, которые могут быть
созданы как на этапе построения моделей, так и позднее — что, кроме того, не помешает
обработке и не потребует «перестройки» всей конструкции программы.

Представим себе вполне конкретную ситуацию. Допустим, программе, использующей


MSM известно всего несколько фраз, предложений по конкретной тематике. Разберем эту
ситуацию подробно, представив, что эта программа находится в операционной системе
робота, способного перемещаться и оперировать объектами. То, что робот видит с помощью
камер, он фиксирует в виде фраз-предложений, описательного характера (в настоящее время
это уже умеют делать ИНС) типа «Я нахожусь в комнате. Напротив два стула и стол. На полу
лежит замок».
В памяти робота присутствует ситуативная фраза «Возьми гвоздь» на которую
программа должна ответить «Хорошо», если гвоздь присутствует в обозримом пространстве,
и подобрать его.
Пользователь просит «Подними замок», но на данную фразу отсутствует ситуативная
фраза. В этом случае программа генерирует волну предложений из двух вариантов
«Подними замок (механизм)» и «Подними замок (здание)».
Поскольку в обозримом пространстве отсутствует замок (здание) но присутствует замок
(механизм), являющийся родственником объекта гвоздь, а слово-множество «Подними»
является родственником слова «Возьми», то робот легко поймет, что от него требуется,
скажет «Хорошо» и выполнит ряд операций, чтобы поднять предмет.
В описанной ситуации хороши следующие вещи: во-первых, то, что нам не пришлось
обучать робота тому, как поднимать замок — он просто знает, что это делается похожим
образом. Во-вторых, поднятие замка, как предмета не вызвало у него когнитивного
диссонанса или порождения философствований на тему «замок поднять нельзя, он слишком
тяжелый».
Можно привести в пример и другой вид контекста, когда имея ввиду предыдущую
информацию, собеседник дополняет ее новой.
Например фраза «Его зовут так же, как и меня». Предполагает, что робот уже знает
часть информации и должен произвести некоторые логические действия. Фразы «И я тоже»,
«Как все прошло вчера?» или например «Она вернулась?» — просто обозначает нахождение
основной информации выше в листинге разговора с данным собеседником. И это не является
предельным ограничением или препятствием.

[1] Полисеми́я (греч. πολυσημεία — «многозначность») — многозначность,


многовариантность, то есть наличие у слова (единицы языка, термина) двух и более
значений, исторически обусловленных или взаимосвязанных по смыслу
и происхождению. Определение из Wikipedia.
[2] В примере здесь и ниже приведен следующий словарь: « М. Хаген. Полная
парадигма. Морфология. Частотный словарь. Совмещенный словарь.» Словарь содержит
4 372 660 словоформ. Этот и подобные словари находятся в свободном доступе по ссылке:
http://www.speakrus.ru/dict/.
[3] Кстати, в 1 строке к союзу «А» добавлены уже внутренние служебные символы «||»
нарочно, поскольку из-за особенностей настройки работы процедур текстового парсинга,
слова короче 3-х символов в них не обрабатываются. Из серии «Это интересно»: долгое
время короткие слова из 1—2 букв периодически вызывали критические сбои из-за процедур
сложной обработки, в связи с чем решение пришло само — вместо переделки десятка
процедур, принято правило, в котором во внутренней обработке все слова с 1 или
2 символами дополняются соответственно 2 или 1 служебными «пустышками». С тех пор
ошибки пропали. Воистину, так временное решение становится постоянным.
[4] Просьба извинить за громоздкий и длинный код в ее реализации. В данном случае
желание быстрого получения результата возобладало над здравым смыслом, ввиду чего код
может быть похож на морского ежа, рожденного акулой, но все же, он работает.
[5] В частности, в процедуре много строк занимает алгоритм механического удаления
вариантов принятых в словаре сокращений, служебных разделителей, и т.д., где многие их
варианты пришлось описать явным образом.

Глава 5. Теория познания

Модель символьной логики


Это парадоксальная ситуация: люди излагают, заключают и кодируют модель мышления
в языке. Но не могут изложить его на бумаге. Простота, но противоречивость изложения
модели мышления пугает и отталкивает. Она принимается «в штыки» и мы можем вести себя
как капризные дети, отрицая ее. Но она не изменится только по нашему капризу или
стремлению подчинить ее жестким правилам логики. Она существует вне зависимости
от нас, — ее слишком долго вынашивала человеческая культура, воспитывая на ней все
новые и новые поколения «людей разумных».
Простые связи в сознании человека формируются с самого раннего детства. Этим
занимаются все родители, начиная с момента, когда например, говорят: «Это мама. А кто
к нам пришел? Папа. Смотри, какой большой. Пойдешь к папе на ручки?» и так далее.
Ребенок постоянно присутствует в определенной системе координат, которые задаются
простыми объяснительными формулами по типу «Это «A», «Это «B», «Не трогай «C»,
«Красивый «D», «Ужасный «E», «Хороший «F», «Плохой «G»…
Ребенок запоминает объекты и их свойства по упрощенной объяснительной модели
языка, преподаваемой родителями, воспитателями и родственниками. Да, в этих «уроках»
присутствует и элемент личного участия, когда ребенок осознает форму, цвет, запах, вес,
скорость, поведение незнакомого ранее предмета. Но все эти характеристики он
впоследствии может описать, а став описательной языковой моделью, название предмета
и серия его свойств включается в классификатор, выстроенный в голове. И поскольку одни
качества и названия объектов связываются с другими, они приходят в состояние
взаимозависимости в рамках языковой системы. Так слова-символы «обрастают»
свойствами, составленными из слов-символов. Разве нам трудно объяснить что-либо
словами? Для любого события, предмета, понятия всегда находятся те слова, которые могут
их объяснить, и эти слова выстраиваются в рамках правил языка. И если мы можем
зафиксировать на словах, записать рецепт пирога или правила вождения автомобиля,
не есть ли это зафиксированная логика мышления? Хочется акцентировать этот момент. Мы
непрерывно фиксируем происходящее в форме фраз языка, сознательно или бессознательно,
но это происходит. По всей видимости, оперируя фразами языка нам легко находить между
ними зависимости и искать ответы. Мы можем представить, что понятие, слово, «упаковано»
в мозге, в контейнере из некого кода, содержащего информацию о взаимосвязях с другими
кодами, а также свойствами, связанными с третьими и четвертыми кодами, — и это могло бы
означать, что мы можем оперировать этими кодами. И по существу, это не праздное
предположение, что мозг может оперировать данными кодами и делать на основе данных
операций предположения и выдавать нужные ответы. А это означает, что мы вновь
возвращается к тому, что язык и мышление становятся неотъемлемыми элементами друг
друга и в языке фактически «зашито» мышление. Но как мы могли бы объяснить это
на физическом уровне?
Если постараться, то можно привести аргументы для естественных, физических
предпосылок модели мышления, формализованной на страницах книги.
Итак, несколько перефразируем идею и попробуем представить, почему, например,
модель многомерного множества может иметь физическое обоснование.
Не будем ставить под сомнение, что мозг человека каким-то образом приспособлен
к систематизации данных. (При этом не стоит выделять отдельные элементы мозга, будь то
кора, подкорковые структуры, лимбическая система и т. п., — мы сейчас не говорим
о конкретном месте или механизме). Представим, как это выглядело бы в абстрактной
модели. На номинальном уровне фрагмент мозга, отдельная зона здесь может иметь некий
«потенциатор», серию разностных величин «напряжения», допустим, от 1 до 24, как число
букв в английском алфавите. Тогда их мы можем символически обозначить как шкалу,
на которой вместо цифр указываются их позиции. 0 <A <B <C <D <E <F <G <H <I <J <K <L
<M <N <O <P <Q <R <S <T <U <V <W <X <Y <Z <25.
Причем, мы можем допустить, что они находятся не обязательно на переднем фронте
и не должны быть сконцентрированы в одном месте.

И
лл. 159. Возможная схема расположения «вариатора напряженности» в абстрактной модели.
Схематично эта реализация может выглядеть так, как на рисунке 159.
И в данном случае, например, символ «А» не обязательно равен целой единице. Он
также может быть равен, например, 0,8 или 1,2, или даже 0,01. Главное в данном случае —
рамки одной позиции по отношению к другой и их устойчивость. Эти значения, условные
единицы могут быть, например и такими:
0 <1,105 <4,02 <4,43 <4,76 <4,9 <6,03 <8,4 <8,451 <15,2 <16,4 <16,63 <18,2 <18,28 <18,7
<18,82 <19,1 <19,39 <20,06 <20,4 <20,502 <20,611 <22,1 <23,83 <24,1 <24,9 <24,97 <25
(Почему? Наша абстрактная модель может оперировать разностными, условными
потенциалами). Еще раз, о том, что означают эти цифры. Это передаваемый импульс
напряжения или частота сигнала, или особенность соединения, или комбинация всех этих
элементов, — характеристика передаваемого «нейроном» в модели сигнала.
Тогда, каждое поступающее на вход «впечатление», (которое имеет некую разностную
градацию) производит некоторый ответ, вызывает реакцию, идентичную одной
из обозначенных позиций. Тогда, каждая напряженность или их серия будет «поселяться»
по определенному адресу. Например, первое «впечатление» будет равным позиции «А».
Но при получении второго «впечатления», которое похоже на первое «A», следует
«задуматься» о различии. И когда различие в деталях найдено, ему следует «найти место»,
например, в кортикальной колонке, этажом ниже. (Отсутствие различия в данном случае —
только сигнализирует об уже «известном»).
На уровне ниже, вероятно также есть вариант выбора определенного уровня
напряжения.

И
лл. 160. Под управлением вариатора новые значения обнаруживают свою позицию.
(Но у следующих этажей «нейронов» показатели градаций могут различаться. Например,
серия градаций «А» может колебаться в диапазоне от 0,3 до 4,8. Но следующий нейрон
будет «знать» по своему опыту, что «имеет в виду» предыдущий. Так на импульс
4,8 условных единиц он может «понять», что употреблен «А» по его «персональной» шкале
градаций).
Так «этажом ниже» могут «записаться», например «АА» и «AB», как
на иллюстрации 160.
При этом, скорее всего, какой-то «нейрон» может являться носителем длинной серии
таких позиций, а другой — короткой или единичной, что может крайне затруднять
формализацию живого процесса. То есть, например код ABABABFFACDN может храниться
в 3 последовательных нейронах — часть ABABA — в одном, BFFAC — в другом, а CDN —
в третьем.
Можно представить эту модель и несколько иным, но более живым образом.
Проведем мысленный эксперимент. Предположим, у нас есть колония из 24 муравьев,
которая поселилась на теле мертвого слона, качающегося на волнах в море. Для этих
муравьев сама ситуация устроила неординарную задачу:
1. Они не могут уйти со слона, иначе погибнут.
2. Каждый из муравьев вынужден есть слона, но каждый свой обед им нужно
производить очень короткое время, (скажем, 1 минуту), чтобы не увязнуть в теле слона,
и за это время муравей прорывает ход, в котором может разместиться полностью, — так
получается «Этаж».
3. Выйдя на поверхность, муравей умывается, высыхает и через какое-то время сможет
поесть еще раз, но только в ходе, уже «вырытом» в теле слона, (который также успевает
подсохнуть).
4. С поверхности кожи слона им доступен единственный первичный ход — рана в теле
слона, сделанная чайкой, а под кожей — их ходы могут разветвляться.
5. Муравьи не могут перегрызать стенки между ходами, иначе гарантированно гибнут,
но они чувствуют, где тонко и отступают перед опасностью; тем не менее, при этом они
теряют время и остаются голодны.
6. Слон «бездонен», однороден, не «убывает» и не портится. Но муравьи не могут
погружаться слишком глубоко — это удлиняет время их пребывания в теле слона
и оставляет меньше времени на еду. Также, муравьиный ход не может углубляться слишком
глубоко, поскольку плотность нор на глубине многократно повышается.
7. Каждый отдельный муравей не может съесть один «этаж» одновременно с другим —
им мешают челюсти и конечности.
Спустя несколько десятков обеденных циклов муравьи могут сделать для себя
замечательное открытие, выигрышную стратегию. Каждый из них может выбрать для
себя одно направлениеи следовать ему, а также делать «коридоры» определенной длины
(не слишком длинные и не слишком короткие) — в этом случае, он не пересекает ходы
других муравьев и это экономит им время.

И
лл. 161. Самоорганизация ходов муравьев в мысленном эксперименте о слоне и муравьях.
Что мы получаем.
Назовем вход в нору символом А.
Тогда первый подземный этаж, прорытый муравьем «А» получит название «АА»,
второй «ААА», третий «АААА», четвертый «ААААА», и так далее. Второй муравей,
опускающийся в общую нору «А», выроет нору «B», так его первый этаж станет носить
название «АB», второй «ABB», третий «ABBB», четвертый «ABBBB» и так далее,
до момента, например, когда достигнут предел и 9 этаж — «ABBBBBBBBB».
Итак, каждый из них прорыл ходы в соответствии со своим направлением и они
достигли предела плотности ходов «в глубину», когда очередной ход прорыть невозможно,
не наткнувшись на стенку другого хода. Но всем муравьям все еще хочется есть, и нехотя,
избегая голодной смерти, они немного изменяют своей стратегии. Так первым начинает обед
в первом этаже муравья «B» муравей «А» и с удивлением обнаруживает, что под этажом
муравья «B» он может продолжить рыть свои ходы «А». И так же муравей «B», оказавшийся
на этаже «А», может начать рыть ходы «B». Со временем они «привыкают» к таким
переходам между этажами, но каждый все равно продолжает грызть ход в своем
направлении.
Самоорганизованная таким образом естественная структура появилась
«самостоятельно» — как приспособленность к определенным начальным условиям среды, —
даже если этот пример и является только мыслительным экспериментом. Но что мешает
появиться подобной структуре в мозге, где неоткрытые знания мы можем представить как
«мертвого слона», а отдельные элементы мыслей, — как муравьев? Свои мысли мы
привыкли оформлять словами и предложениями, а значит элементы «дерева» ходов могут
являться не только образами, но и словами естественного языка, и в данном случае
география хода будет равна географии смысла. Так новое знание (или «ход»=«смысл»)
не может углубляться слишком далеко от известных «ходов», иначе оно «завязнет» в нем
и «погибнет». И так же, чтобы развиваться, мысли вынуждены постоянно «питаться»
новыми смыслами.

Методология мышления
Чем еще хороши операции с многомерными множествами, это тем, что мы имеем
возможность отслеживать логику решения на любом ее этапе и получать «разумное»
объяснение и соответственно, исправлять его. И это — принципиальное отличие
от поведения искусственной нейросети, результат в которой практически невозможно
коррелировать с исходными данными.

И
лл. 162. Возможный принцип подхода к реализации системы обработки данных.
Здесь возникает вопрос об унификации подхода к реализации правил обработки данных.
На иллюстрации 162 мы можем представить процесс анализа любой дискретной задачи как:
1. Нахождение «ключа вхождения», специфических маркеров, определяющих тот или
иной тип задания.
2. Определение стратегии для применения определенных правил с целью вычисления
решения.
3. Чтение данных и применение выбранной стратегии.
Набор стратегий может быть самым различным, но на первом этапе выбора ключа
вхождения нам также необходимо разделять 3 элемента предложения-задания: собственно,
ключ, условие и переменные. Например, в следующем вопросе: «Найди самого сильного
морского жителяиз них: краб, тюлень, собака, паук, ромашка?» обычным шрифтом
выделен ключ вхождения («Найди из них»), жирным жрифтом выделено условие для выбора
(«самого сильного морского жителя»), а курсивом — переменные для поиска («краб,
тюлень, собака, паук, ромашка»).
Но задание может быть перефразировано, в результате чего ключ вхождения может
быть записан, как «Выбери», «Определи», «Исключи», «Вычисли», «Какой из них», «Кто
из них», «Кто из этих существ», и так далее. На помощь приходит свойство гибкости кодов
множеств, поэтому записав наибольшее число условий из возможных вариантов, ключом
вхождения может оказаться не точное условие, а наиболее близкое к данному условию.
Оформление условия вхождения (для записи «Какой из них») может иметь
следующий вид:
>> AAAAAAAADAA AAAAAAAAAAA AAAAAAAAFGB
Тогда, при вопросе, содержащем «Какие из этих», мы получим фразу-множество,
имеющую значительное попадание в оригинал:
AAAAAAAADAAB AAAAAAAAAAA AAAAAAAAAABBA
И в данном случае, при отсутствии прочих близких условий программа примет
к исполнению ключ, ведущий к стратегии поиска по соответствию переменных условию
задания.
Стоит заметить полезное свойства ключа: определив его нахождение во фразе, мы
можем его удалить из нее и получить набор условия и переменные в «голом» виде. В данном
случае, разделителем условия и переменных является знак пунктуации «:», а указанием
на переменные — символы запятых. Но в любом случае мы можем оперировать лишь
вероятностями, признаками усиливающими или ослабляющими вероятность отношения того
или иного описательного блока к тому или иному объекту описаний.

Глава 6. Информация, язык и интеллект

Материальная природа информации


Споры вокруг материальности информации никогда не затихали. Но я только сделаю
предположение, а как вам к нему следует относиться — уже ваше дело.
Может быть, мы сбиты с толку идеей бита? «Включено-выключено». «Да — нет».
«Имеется — отсутствует». «1—0». Это состояние традиционно называют минимальной
единицей хранения и передачи информации. Из битов образуются байты, килобайты,
мегабайты, и так далее. Их обрабатывают разного рода электронные машины. Для этих
машин такая система является привычной.
Но… Никто не задумывается, что состояние вещества, подобное состояниям бита,
противоречит законам природы и физики. Почему? Потому что бит, существующий
в современной двоичной системе представления информации является прообразом идеи
традиционного позиционного переноса, который осуществляется в любой счетной системе.
Это делается только «для удобства» записи, обеспеченной состоянием ограниченности
визуальной человеческой памяти, ее неспособности хранить последовательности большой
емкости. То же самое происходит и в любых других счетных системах.
Для примера, мы можем сфокусировать внимание и на символе, который изменяется
по мере счета в десятичной системе. Вот он, символ числовой единицы: «1».
Теперь он меняется: «1, 2, 3, 4, 5, 6, 7, 8, 9»… Пока все хорошо. Но с прибавлением
единицы он становится ничем, нулем «0», а рядом с ним появляется его родственник, «1»,
который по значению больше стоящего справа, но по существу, меньше предыдущего
значения последнего.
Посмотрите еще раз, как отличаются «9» и «10», абстрагировавшись от арифметических
правил. Представьте «9», например, железной скобой. Да, при определенном усердии, мы
могли бы выгнуть ее в «0», или перевернуть ее и получить «6»… Но с какой стати ей
«вздумалось» размножаться? Почему операционное правило заставляет нас изменять
интуитивному, разумному чувству сохранения единицы материи? Есть простое
объяснение — мы учили правила математики в раннем детстве. Нас приучили так
обращаться с арабскими цифрами.
Однако, это слишком сложно для природы. В физике так не происходит. Ничто
в природе мгновенно не теряет свой вес, долю излучения или энергию; и не порождает нечто
рядом, размножившись.
Но если мы представим единицу информации, как материальный атом, ненулевое
значение, физический объект, — все становится на свои места. Если значение этой единицы
меняется, например, она начинает излучать больше тепла (или меняется любой другой ее
характерный показатель), то для нее не будет никаких оснований совершать фазовый
переход из большого значения в знак пустоты. Также, совершенно очевидно, что она
не породит себе подобного рядом, «разрядившись», или исчезнув до нуля. Даже
с электрическим разрядом такое невозможно.
Теперь, вспомните, как выглядит молекула ДНК. Это грандиозная, совершенно
сумасшедшая физическая последовательность элементов соединений, но между ними нет
пробелов, пустот. Нет нулей и единиц. Каждый элемент в ней обладает различными
свойствами, и мы могли бы их представить как символы с градациями от 1 до 4… Но они
имеют смысл только тогда, когда сцеплены друг с другом.
Единицы информации в ДНК не перепрыгивают с одного места в другое; да, между
ними могут возникать «ошибки» при делении, которые называются мутациями, но это
исключение, а не правило.

И
лл. 163. Схематическое изображение фрагмента нити ДНК и его кода в форме символов «a»,
«g», «t» и «c».
Можно взглянуть и шире на окружающий мир. Если бы мы могли «нажать на паузу»
вселенную, как герой фильма «Брюс Всемогущий», то могли бы увидеть нечто
ошеломительное. Используя томограф, мы рассмотрели бы, как отдельные нейроны внутри
чьей-то головы светятся яркими звездочками, оставаясь на одном месте. Они виделись бы
нам материальными. Вероятно, мы бы убедились, что информация материальна. Мы
могли бы изучать их, сравнить друг с другом их заряды… Но вновь «запустив вселенную
на воспроизведение» мы опять рискуем потерять веру в материальность информации, ведь
все происходит слишком быстро и неуловимо.
С позиции материальности информации — все сущее становится на свои места. Каждый
символ, как единица информации, сохраняет свое равновесие. Возможно, меняется его
внешний вид, его характеристика, но не меняется единство, внешняя целостность «атома»
информации.
Если рассуждать в этом направлении, получается, что наша общепринятая концепция
информации абсолютно синтетична и неестественна. Беспорядочные переходы элементов
этой «синтетической» информации из одного состояния в другое совершаются лишь из-за
ограниченности своих условий. Счет и предложения из слов любого естественного языка
на бумаге, как и в любой электронной машине, работают против законов физики; но мы
находимся в этой парадигме информационного представления мира как в ловушке
и не можем выйти из нее.
В природе этого не происходит. Здесь все постепенно. Здесь нет состояния «Ничего»
и состояния «Все», что предлагается двоичной или любой другой системой счисления. Но,
как тогда считывается эта естественная информация, спросите вы?
Примеров можно привести сколько угодно. Допустим, речь может идти об информации,
которую несет электромагнитное излучение. Она может обладать настолько плотной
потенциальной емкостью, что легко приближается к возможностям бесконечной символьной
последовательности. Вспомните об астрономии. Чем занимаются астрономы
со спектральным анализатором, когда ловят излучение далеких звезд? По существу, они
получают единственный символ, атом информации в виде луча света, но расшифровывают
его с помощью спектра, получая колоссальное количество информации — в первую очередь,
о содержании массы различных химических элементов… Не говоря уже, что применяя
дополнительные методы исследования, они получают сведения о расстоянии, приближении
или удалении звездного объекта, его размере, массе, составе атмосферы… и это все может
быть получено из единственного однородного луча света. По сути, единичного символа
бесконечной символьной последовательности, атома информации. Разве это не потрясающе?
Информация не преодолевает законы сохранения энергии, поскольку она и есть материя
и энергия, заключая два состояния в одном. Это то, что изменяется и сохраняется, но не то,
что внезапно исчезает или так же молниеносно размножается.
Какой из всего вышеописанного следует вывод? Информация по своей глубокой
природе соблюдает единство своей материальной составляющей. Любой элемент
информации сохраняет свою целостность, а хорошим алгоритмом обработки информации
должен быть такой, который не нарушает этой целостности, соблюдает условия его
существования.
Помните выражение «Наши мысли материальны»? Похоже, что это не фантазия. Это
буквальное, атомарное состояние нашего мышления. Состояние, которое скорее можно
назвать течением, колебанием, передачей энергии, механикой. Но не двоичным кодом.
Так идея материальности, механистичности информации и идея бесконечной
символьной последовательности идеально дополняют друг друга. Можно сказать даже, что
их брак свершился на небесах. В буквальном смысле.
Но каким может быть практическое применение симбиоза из этих двух идей? Давайте
рассуждать дальше. С увеличением последовательной емкости единицы передачи
информации до числа, приближенного к бесконечности, мы получаем фантастические
возможности.
Кстати говоря, сегодня у нас в распоряжении есть достаточные технические мощности,
чтобы получить симуляцию если не бесконечной, то приближенной к бесконечности
символьной последовательности. Если ее решение окажется воплощено на аппаратном
уровне процессора, она может быть лучшим архиватором документов, сжимающим большие
файлы в десятки, в сотни и даже в тысячи раз. Представьте, что вы могли бы записать
на флешку, емкостью 16 гигабайт, объем данных, эквивалентный одному террабайту?
И главное, вы могли бы читать эти данные без потери скорости.
То же самое может произойти и с процессом передачи данных, который может быть
ускорен в сотни и в тысячи раз. Смартфоны с подобной архитектурой процессора могли бы
позволить настолько снизить нагрузку на базовые станции, что даже 100 000 абонентов,
подключенных одновременно, в одном месте к сети — не почувствуют проблем со связью.
В то же время, мы могли бы повысить надежность зашифрованной передачи данных
настолько, что любые идеи создания квантового компьютера, способного сломать эти коды,
покажутся смешными.
Впрочем, это уже совсем другая история.

Формы языка
Возможно я рискую в чем-то повториться, но мне хотелось бы еще раз остановиться на теме
человеческого интеллекта и его связи с языком. Для начала давайте разберемся в том, что
такое язык? Языком обычно называют систему символов, которая позволяет выражать
некоторые абстрактные понятия и передавать информацию.
Какими бывают языки:
1. Язык жестов, в большей степени основанный на визуальной передаче информации.
2. Язык вербальный, от латинского «Verba» — слова. Те которые образуются звуковыми
и письменными комбинациями.
Что мы можем выразить языком жестов? Глухие люди способны пользоваться языком
жестов достаточно хорошо настолько, чтобы передавать абстрактные, математические
понятия, формулы и сложные описания. Однако глухие, особенно те, которые глухи
с рождения, очень тяжело воспринимают письменную речь: они делают очень много ошибок
и научить их правописанию значительно сложнее. С чем это связано? Письменный и устный
язык состоит из одних и тех же элементов, звуков, которые переносятся на буквы и их
сочетания. Читая, вы мысленно или вслух произносите буквы, которые складываются
в слова. У глухих такой возможности нет. Они не знают как произносятся слова, поэтому им
сложно детализировать написанное слово. Для таких людей каждое написанное слово это
просто некий абстрактный набор элементов, которые только в определенном сочетании дают
какой-то смысл. Слышащие же знакомы с каждой отдельной буквой как с определенным
звуком или его сочетанием, поэтому для них письменная речь дается легче.
Теперь представим картинку. Перед нами два необитаемых острова, на котором мы
оставили двоих разных людей с топором и поставили перед ними простую задачу: построить
лодку. Один из них, это слышащий. Второй — глухой с рождения. Кто из них быстрее
справится с задачей?
На самом деле шансы и у того и у другого будут примерно одинаковы и оба они
одинаково хорошо могут построить лодку. Но есть одно условие, при котором ни тот ни
другой — никогда не построят лодку, даже если они проведут на острове сотню лет.
Ни тот ни другой не построят лодку никогда, если они окажутся там в возрасте
до 3 лет, — даже если вы оставите им подробные чертежи этой лодки и все детали.
И проблема не в том, что их могут съесть дикие звери, или они умрут от голода, утонут,
упадут или покончат с собой от депрессии. Вы можете оставить им много тонн
непортящегося провианта или сбрасывать его с вертолета; вы можете поместить их в теплые
и безопасные дома и оставить в качестве развлечения миллион различных игрушек, вы
можете огородить все побережье и скалы, сделав их безопасными, однако результат будет
один и тот же, — они состарятся и умрут, так и не выполнив задание.
В чем же разница между первым и вторым случаем?
Возраст в разнице результатов — лишь вторичная причина. Основная причина состоит
в том, что устойчивая, настроенная на основе значительного опыта «впитывания»
человеческой культуры и языка «логическая машина» достаточно быстро достигает нужного
результата, тогда как несформированная подобным образом — проваливает эксперимент.
Вам должны быть известны случаи «детей Маугли», которые оказались (некоторые
в возрасте 5 или 7 лет) оторваны от воспитания в человеческой культуре и становились
полностью неспособны решать даже простейшие интеллектуальные задачи.
Самый простой вывод, который следует из этого — интеллект невозможен без языка,
его понимания и осознания, как глубокой, сложной, символьной системы.

Язык и письменность — не одно и то же


Люди привыкли не замечать некоторые очевидные вещи. Например, разницу между смыслом
языка и письменностью. Письменность — это система фиксации звуков, произносимых
человеком, своего рода зрительный ассоциативный образ, вызывающий определенный набор
реакций, ограниченный определенными правилами.
Если мы обратимся к истории зарождения письменности, то многое станет понятным.
Около 4 тысяч лет до н.э. в древнем Шумере в качестве символов-указателей начали
использоваться небольшие глиняные предметы различной формы, а затем — с простыми
единичными символами, обозначавшими конкретные объекты: лошадей, коров, людей, зерно
и еще некоторых других. Затем люди придумали записывать группы этих объектов,
составляя из пиктограмм некое послание, как например, опись имущества, находящегося
в аренде. Позднее люди догадались записывать имена — используя близкие по звучанию
слов известные пиктограммы. И лишь около 700 лет спустя они стали записывать отдельные
звуки и слоги абстрактными символами и из них получались слова. И так мы поступаем
по сей день — записываем на бумаге произносимые звуки. Но звуки не являются носителями
смысла. Все они — случайны. Звуки и письменность это случайные наборы образов,
организованные некоторыми правилами, но в целом — хаотичные.
Смысл языка — сложнее, чем письменность. Его скорее можно отнести к набору
объектов, находящихся в рамках системы классификаций. Мы не видим этот классификатор,
не тренируемся его называть или описывать. Между тем, им все пользуются. У каждого
человека он может отличаться, в зависимости от воспитания, среды, в которой он находится.
Некоторые фрагменты этого классификатора все же интуитивно «просачиваются» в язык
и могут называться «система ценностей», «сфера знаний», «предметная среда» и так далее.
По похожему принципу работают все магазинные каталоги или системы классификаций
склада, профессий и другие вещи. Но они чрезмерно упрощены в отличие от того
классификатора который при помощи языка оказался в нашей голове. Классификатор мозга
является логическим указателем на взаимосвязи объектов окружающей действительности
или абстрактных понятий.
Поэтому, путая язык с письменностью, у нас ничего не получится с интеллектом. Мы
не можем в качестве оперируемых объектов использовать слова естественного языка. Вся эта
затея в конечном итоге ни во что не выльется, даже если мы будем пытаться организовывать
связи «вокруг» этих слов.
Записывая слова на естественном языке люди оказываются в плену иллюзии, что
компьютер их поймет, и пытаются строить какие-либо конструкции с этими наборами
символов. Но нет! Для компьютера они так и останутся наборами символов.
И
лл. 164. «Что означает семантическая сеть?»

И
лл. 165. «Что компьютер понимает.»
На картинках 164 и 165 наглядно показывается, что такое описание традиционной
семантической сети на естественном языке для компьютера.
Что из этого следует? Это означает, что мы неверно описываем семантические сети. Сам
принцип подхода к ним в корне неверен, хотя интуитивно правилен. Письменность может
быть только промежуточным звеном и не может быть указателем. Письменность это ярлык,
внешний образ, который не несет в себе никакой смысловой нагрузки.
Семантические сети хороши для восприятия людей, но не компьютеров.
Промежуточные классификаторы, (каким является классификатор MSM) хорош для
компьютеров, но не для людей. Между тем, людям и не следует пытаться его считывать или
работать в нем. Но обратите внимание, как конструкции, которые мы с детства привыкли
воспринимать очень «глубокомысленными» и сложными, — могут детализироваться
до простых и понятных.
Как, например, поговорки и пословицы могут возвращаться к обыденному смыслу?
Взгляните на иллюстрацию 166.

И
лл. 166. Поговорка «Делу время — потехе час» легко детализируется в набор привычных,
не книжных смыслов.
Здесь мы разобрали «генный состав» поговорки «Делу время — протехе час» с помощью
классификатора MSM. Заметьте, что она может быть вполне адекватно понята, как
необходимость уделять долгое время набору полезных действий и короткое время —
развлечению или увлечению.
Возьмем еще один пример, поговорку «Счастливые часов не замечают».

И
лл. 167. «Генный разбор» состава поговорки «Счастливые часов не замечают».
Что мы видим в этом разборе состава предложения? Буквально на поверхности
обнаруживается ее смысл, в том что в радости, позитиве, время отрицается как видимое
свойство. Ее можно пересказать например, как «Веселый времени не видит», — здесь
сохраняется общий смысл исходной поговорки но и порождается новый, в форме некоторого
обобщения. И это — поразительное качество MSM в переносе и «размножении» смыслов,
которое мы просто обязаны использовать.

Интеллект из пустых банок


Хочется привести здесь еще одну идею. Не важно, из чего мы построим компьютер, лишь бы
эти части были достаточно устойчивы и не теряли своих свойств со временем. Он может
быть механическим, как например, первые арифмометры, или ламповым, — это не имеет
значения. Так, например, мы можем построить компьютер из пустых алюминиевых банок.
Он будет очень большим, (вероятно, может занять целый стадион) и очень медленным,
но если перед нами будет стоять задача сложить несколько чисел, — мы получим нужный
результат, пускай и не так быстро как это сделает, допустим, электронный калькулятор.
В данном случае устройство — не имеет значения, важен сам принцип и итоговый верный
результат.
Я процитирую еще раз Марвина Мински, из его книги «Эмоциональная машина»:
«…Чтобы построить части любой машины, мы можем использовать любое достаточно
сильное и стабильное вещество: все, что имеет значение, — это то, что делает каждая
отдельная часть, и как эти части соединяются. Например, мы можем создавать разные
компьютеры, которые выполняют одни и те же вещи, используя либо новейшие электронные
чипы, либо используя деревянные, струны и скрепки для бумаги, размещая их части так,
чтобы снаружи каждый из них выполнял те же процессы»…
Но здесь мы сталкиваемся с очень занимательным противоречием. Вместо того, чтобы
разбираться в механике мышления ученые продолжают настойчиво разбираться в механике
мозга. Это очень парадоксальная ситуация. Тот же Мински говорил, что исследовать
нейроны в мозге — это то же самое, что исследовать транзисторы в компьютере. Что мы
можем получить, изучая транзистор? Напряжение на входе и на выходе? Но даже это
не совсем корректный пример, поскольку любой компьютер достаточно жестко
формализован, и тем не менее мы не в состоянии оценить и смоделировать работу всего
процессора, исходя из этих разрозненных данных.

Далее мы постараемся рассмотреть некоторые теоретические аспекты моделирования


картины мышления, с целью реализации окончательной структуры представления данных.
Мы не будем рассматривать то, что невозможно реализовать простыми и доступными
средствами того же Паскаля. Но, в конечном счете, в этом деле не имеют значения средства
реализации, главное, — это перенос смысла и назначения. Даже если это будет работать
не так хорошо, как хотелось бы, но практика может подсказать перспективное направление.

Гештальт-цикличность
Несомненно, в своей практической работе мы должны разделять понятия «думать»,
«размышлять», «говорить» и «действовать». Все эти вещи — это не одно и то же. Но есть
в них нечто общее, что в данный момент хотелось бы обсудить, размышляя
о гештальт-психологии и бихевиоризме.

Гештальт — форма объекта, его целостный смысл или завершенный процесс, как
единица сознания, психики.

Цикл — набор действий, инструкций, который может быть повторен определенное


количество раз и/или до момента исполнения определенного условия.
Содержание человеческого бытия состоит из циклов, которые можно было бы разделить
на общие, естественные (например, час, день, неделя, месяц, сезон, год, десятилетие) так
и специфические, относящиеся к специфике восприятия. Так, мы можем назвать
гештальт-циклом любое действие с определенной задачей, как то: «написать письмо»,
«позавтракать», «сдать экзамен», причем каждый крупный гештальт-цикл может быть
разбит на множество мелких, которые могут включаться в цикл в процессе его исполнения.
Приведу простой пример. Задача, оформленная как гештальт-цикл «заказать
пиццу» может выглядеть следующим образом:
1. Уточнить наличие денег
1.1. Проверить кошелек.
1.1.1. Открыть сумку.
1.1.2 Достать кошелек.
1.1.3. Открыть кошелек
1.1.4. Посмотреть на содержимое
1.1.5. Сосчитать содержимое. При отсутствии наличных, перейти к пункту 1.2.
1.2. Проверить состояние счета в Интернет-банке.
1.2.1. Уточнить доступность компьютера и интернет-соединение. При отсутствии,
перейти к пункту 1.3.
1.2.2. Вспомнить адрес интернет-банка.
1.2.3. Открыть браузер.
1.2.4. Вписать адрес интернет-банка в строку браузера
1.2.5. Вписать данные логина и пароля.
1.2.6. Достать свой телефон.
1.2.7. Посмотреть СМС из банка.
1.2.8. Подтвердить вход кодом из СМС.
1.2.9. Открыть вкладку «счета» в интернет-банке.
1.2.10. Оценить наличие денег на счетах.
1.3. Если условие 1.2 не исполнено, исполнять те же действия, что и в 1.2, используя
телефон.
1.4. Если условия 1.1—1.3. не исполнены, спросить компаньона о наличие денег.
2. Выбрать пиццерию.

3. Ждать.
4. Впустить доставщика пиццы.
5. Расплатиться за пиццу.
Как вы заметили, каждое мелкое действие в подобной инструкции и есть ни что иное
как гештальт-цикл, то есть, необходимое действие, которое должно быть исполнено
хотя бы 1 раз для реализации общего гештальт-цикла.
В примере с заказом пиццы мы могли бы назвать этот процесс и сценарием; однако,
здесь есть отличие от простого перечисления последовательности действий.
Представляя каждое действие как гештальт-цикл, который делится на подмножество
гештальт-циклов мы можем получить возможность их гибкой корректировки в процессе
исполнения.
Постараюсь объяснить, что имеется ввиду.
Гештальт-циклы могут выполняться параллельно, и если гештальт высшего порядка
исполняется быстрее, нижние гештальты прекращаются.
В приведенном примере, если в кошельке отсутствуют деньги (п.1.1.) и/или если
ожидание соединения с интернет-банком происходит довольно долго (п.1.2), можно сделать
попытку перейти сразу к пункту 1.4 — спросить о наличие денег у своего компаньона и если
он окажется результативным, перейти к пункту выбора пиццерии. И в этом — существенное
отличие от линейной формы исполнения обычных циклов в программировании.
Как этот процесс можно было бы формализовать?
Приведу один из возможных способов. Мы могли бы представить каждый
гештальт-цикл как набор элементов массива и обрабатывать их в общем цикле. Например,
переведем в форму трех гештальт-циклов альтернативные программы по определению
наличия отчества в слове. Первая подпрограмма будет проверять на наличие мужских
окончаний в слове, это «-ВИЧ» и «-ЫЧ»; вторая подпрограмма — будет искать женские
окончания «-ВНА», «-ЧНА»; третья подпрограмма — искать слова «Отчество», «Ф.И.О.»,
«ФИО» в предложенной строке. Нам важен результат, поэтому неважно, какая из трех
стратегий сработает быстрее, главное, что они будут обрабатываться как параллельно
работающие гештальт-процессы. Кроме того, срабатывание третьей программы может
усилить одну из первых и «обнадежить» нас.
Для простоты, будем считать, что каждый элемент описываемого гештальт-процесса
симбиотичен с другими, поэтому мы будем производить лишь одно действие — сравнение
поиском подстроки в строке, и нам не нужно их формализовывать отдельно. По существу,
мы заполняем массив переменными, но помним и о том, что он может быть заполнен
и командами.

Подпрограмма 1:
S [1]:= «ВИЧ ‘; s [2]:=«ЫЧ»;

Подпрограмма 2:
S2 [1]:=«ВНА ‘; s2 [2]:=«ЧНА»;

Подпрограмма 3:
S3 [1]:=«Отчество»; s3 [2]:=«Ф.И.О»; s3 [3]:=«ФИО»;

Наша задача — обнаружить совпадение в одном из трех вариантов. Так или подобным
образом может выглядеть запись работы программы с тремя включенными
гештальт-циклами.

I:=0;
Readln (P);
Repeat
Inc (i);
Until (pos (s [i],P) <> 0) or
(pos (s2 [i],P) <> 0) or
(pos (s3 [i],P) <> 0) or
(i> 3);

Но и здесь наша стратегия оказывается несовершенна, ведь фактически программа


действует линейно, последовательно определяя «победителя». Выход из этой ситуации
может быть только один — запускать каждый гештальт-цикл в виде отдельного процесса или
программы одновременно, и победителем становится тот, который сработает быстрее или
эффективнее. По итогу работы одного из подпрограмм должна принять решение
об остановке других процессов в этой ветке.
Так можно сделать следующее предположение:
Симуляция процесса мышления, как суммы гештальт-циклов может быть
осуществлена только как организованное взаимодействие нескольких запускаемых
одновременно программ, объединяемых общим интерфейсом и коммуникациями.
Эти запускаемые программы должны иметь схожие возможности и единый «язык»
общения между собой. Но как они могут «договориться»? Предположим, речь идет о том же
определении отчества. В данном случае нам не следует усложнять ситуацию, — каждая
из подпрограмм будет самостоятельно выполнять работу в соответствии со своей стратегией,
но «отчитываться» о результате будет лишь успешная.
Предположим, в качестве входящего значения получена строка «Николаевна». В данном
случае первая и третья программа «промолчат», а вторая может сделать запись в логе
выполнения вроде:
«Отчество=Николаевна, пол=женский». После чего основная программа принимает
эти данные и в данном случае нам будет неважно, какими средствами достигнут этот
результат.
Разберем же более сложный пример с заказом пиццы. В данном случае форма
реализации может выглядеть как серия запущенных программ исполняемых
гештальт-циклов, подчиняемых иерархическому принципу:
— Низшие гештальт-циклы (вроде «открыть кошелек» или «проверить сетевое
соединение») будут запущены высшими (вроде «Проверить наличие денег»), а в свою
очередь высшие будут «отчитываться» о своих результатах основной программе (или
программам).
Так мы можем достигнуть ускорения и своевременного принятия нужных решений
по стратегии человеческой модели мышления — путем фактического распараллеливания
этого процесса. Более того, в случае когда гештальт-циклы отключаются в определенном
порядке по своему завершению, по картине их отключения можно получить дополнительную
информацию, картину, которую можно использовать как вспомогательный инструмент
прогнозирования.
Поскольку встраивание одних ГЦ в другие может происходить в процессе выполнения,
нам следует рассматривать возможность контроля исходного кода, и если его содержание
изменено, то программе ГЦ требуется перезапуск для исполнения перестроенного кода.

И
лл. 168. Рисунок из книги Марвина Мински «Эмоциональная машина». Здесь элементы,
называемые «Селекторы» вызывают активность других, которые в свою очередь
активизируют следующих, вызывая крупномасштабный каскад из активных элементов.
Несомненно, идея о работе мозга как о наборе серии различных программ или компьютеров,
работающих в системе сети, перекликается с идеями Марвина Мински,[1] в частности,
в книге «The Emotion Machine». В ней он приводит схемы этого процесса, когда одна
«программа» запускает серию других, — этот процесс он называет «каскадом».
Книга, к большому сожалению, не переиздавалась на русском языке, но ее
англоязычный оригинал доступен в сети.[2]

Я приведу цитату из его книги «Эмоциональная машина».


«Мы можем добиться прогресса, спросив о том, как мозг мог бы поддерживать
эмоциональные процессы — и сегодня мы знаем, что каждый мозг содержит очень много
разных отделов, каждый из которых выполняет определенные специализированные
функции. Некоторые могут распознавать различные шаблоны, другие могут
контролировать различные действия, третьи — формулировать цели или планы,
а отдельные могут привлекать разные знания. Этот способ предлагает возможность
представить разум (или мозг) как совокупность сотен или тысяч различных ресурсов».
Конечно, в данном случае речь идет о человеческих чувствах и эмоциях, но впрочем, это
описание вполне подходит и как полноценный инструмент организации мышления, который
в совокупности с простыми принципами классификатора и волновым подходом, как
к обработке контекста, так и работы с гештальт-циклами, могут иметь смысл.
Но вернемся к нашим гештальт-циклам и сфокусируем внимание на том, что требуется
для организации подобной картины.
Прежде всего, нам необходим протокол для организации взаимодействия между
элементами.
Несомненно, он должен содержать описания, сформулированные в кодировке МСМ,
и соответствующие названия для файлов-исполнителей.
Например, запуск одного или нескольких гештальт-циклов может осуществляться
внутренней командой «AAAAAAACHAADAPA» (Начинай) и блоком описаний.
Команда следующего вида: AAAAAAACHAADAPA AAAAAAACJAAAJFC
AAAAAAACIAABKA, звучит как «Начинай проверку правописания», после чего может
быть запущен ГЦ с именем «AAAAAAACJAAAJF AAAAAAACIAABKA» («Проверка
правописания»), в блоке описаний которого могут содержаться вложенные ГЦ с именами
«AAAAAAAAFFFQH AAAAAAACGKF» («Расстановка переносов»), «AAAAAAACJAAAJF
AAAAAACB» («Проверка языка»), «AAAAAAAAECFA AAAAAAAAGDBIB» («Поиск
неизвестных») и другие.
Каждый из них должен не просто рапортовать о произведенных изменениях текста,
но и учитывать изменения, внесенные своими «коллегами» ранее. То есть, он должен
прочитать лог действий, записанных после поступления команды, и если там уже содержатся
некоторые данные об изменениях, то учесть и их, и заново произвести проверку
в соответствии со своим назначением.
Таким образом, получается, что какие-то из ГЦ будут работать с разной скоростью:
одни будут «притормаживать» тогда, когда другие уже закончат. При этом, например, если
пользователь торопится получить исправленный текст, и у него нет слишком много времени,
он может получить промежуточный, почти полностью проверенный текст в любой момент,
не дожидаясь завершения работы последнего гештальт-цикла. В этом есть очевидное
преимущество такой системы организации, но пример с проверкой правописания, вероятно,
не слишком очевиден и показателен.
Вернемся к заказу пиццы. В этом случае типовой процедурой ГЦ может стать «Начинай
заказ пиццы»: «AAAAAAACHAADAPA AAAAAAACFIKN AAADBADCCAB», содержащей
уже упомянутый ГЦ «Проверить наличие денег» «AAAAAAACJAAAJG AAAAAAAEBEGJ
AAAAAAACRELF», включающий в себя «Открыть сумку» AAAAAAACHAABC
AAADAACDKIEB, «Взять кошелек» AAAAAAACa’JG AAADAACDKIEE, и другие.
Но что интересно, если например, кошелек уже лежал рядом, ГЦ «Открыть кошелек»
это сразу обнаружит и остановит бессмысленное в данном случае действие по поиску сумки.
Так произойдет мгновенное переключение — то качество, которое мы так ценим в людях,
и которого нам так не хватает в компьютерах. Также и фраза собеседника «Я сегодня заплачу
за пиццу» может остановить выполнение прочих действий, и переключить систему на работу
по следующим пунктам.
Что же из себя может представлять типовая программа гештальт-цикла?
Каждая из них может иметь набор типовых процедур внутри и список
команд-инструкций в собственном внешнем «словаре». Кроме того, основной программе
и программам ГЦ высшего порядка требуется иерархический список программ ГЦ с их
именами и способами вызова. Конструирование программ ГЦ должно быть упрощено при
помощи набора типовых стратегий, например, в их инструкциях может содержаться: «найди
общее в перечислении», «перейди к младшему значению по свойствам», «выбери слабого»,
«выбери имя пользователя» и так далее. В качестве передаваемого параметра в общем
диалоговом логе может употребляться время, строка вызова ГЦ, параметры вызова,
в качестве последних могут употребляться как слова естественного языка, так и коды МСМ.
Для того, чтобы держать под контролем общий лог системы одна из подпрограмм
должна быть включена постоянно, и она будет выполнять роль диспетчера, раздавая
«заказы» гештальт-циклам; основная же программа будет формулировать лишь пространные
пожелания и считывать результаты работы систем ГЦ, передавая их пользователю (или
куда-то еще). Программа-диспетчер в системе должна иметь возможность создавать новые
ГЦ и инструкции для них в фоновом режиме. Она должна также иметь возможность
обучаться в случае, если основная программа явно информирует о неудаче и диктует
правильный вариант, либо варианты. Диспетчер может уточнить дополнительные параметры
которые привели к неудаче и создать альтернативный список инструкций для ГЦ,
подходящий к нужному результату. Со временем списки старых ГЦ и инструкций могут
удаляться, если они не употребляются либо вызывали конфликт с новыми инструкциями,
показавшими себя хорошо. За этими «регламентными работами» может следить еще один
ГЦ, который будет зависеть от конкретного времени суток (или дня недели, например). И так
может образоваться потребность системы во «сне» — процессе исправления списка
инструкций для ГЦ и их содержания, поскольку весьма вероятно, что этот процесс будет
довольно длительным и включать в себя детальный анализ «пережитого» в течение дня.
Какие еще ГЦ могут запускаться «в штатном» режиме? Например, ГЦ «Приветствие»,
«Знакомство». Пожелание доброго утра или доброго вечера в ГЦ «Новый день», уточнение
интересов пользователя в ГЦ «Что ему нужно». Кстати говоря, этот ГЦ может включать
в себя работу с базой данных пользователей, которых следует помнить.
Здесь поможет и ГЦ «Светская беседа» или например «Игра в загадки» при включении
ГЦ «Скучно». При встрече с давно знакомым, доброжелательным пользователем должен
вызываться ГЦ «Друг» или «Подруга» в которых можно пробовать подшучивать или
выражать эмоции в зависимости от привычек собеседника. В ГЦ «Мечта», «Цели» могут
формулироваться долгосрочные или краткосрочные цели и мечты. ГЦ «Эмоции» можно
включить и проанализировать эмоциональные высказывания пользователя, соотнеся их
с «собственными». Многие из упомянутых ГЦ могут работать постоянно, однако задача
основной программы будет состоять в том, чтобы избегать избыточности в общении,
и отсекать, частично блокировать полученную информацию, а может быть и делать из них
какие-то выводы, которые могут передаваться другим ГЦ, например «Мысли» или
«Выводы». Диспетчер должен регулярно анализировать сценарии вызовов различных ГЦ,
формируя например инструкции к ГЦ «Привычки».
Так может быть смоделирована сложная система восприятия, реакций и даже эмоций,
подобных человеческим, и все это в комплекте с гибким анализом данных может
эмулировать, а во многом и быть адекватным конкурентом человеку.

Метафоры об MSM
В виду общей рабьей складки умов, аллегория всё ещё имеет шансы быть более понятной
и убедительной и, главное, привлекательной, нежели самая понятная и убедительная речь.
Михаил Евграфович Салтыков-Щедрин (1826–1889) — русский писатель
Немного отвлечемся и представим, как мы можем определить место классификатора MSM,
как аналогию чего-либо в современной информационной науке? Отчего бы не попробовать
взглянуть на него языком метафоры?

Метафора 1
Конструктор-вселенная
Представим, что у нас есть конструктор. Например, готический замок. Но необычный.
На каждой детали есть несколько вариантов соединений. Допустим:
Кирпич
На кирпиче написано:
Желтый
Бетон
Строительный
Твердый
Маленький
Большой
Каменный
Песчаный
Рыхлый

Много? Но подождите, мы только начали. Теперь представьте, что на одном «кирпиче»
написано несколько тысяч значений. И на каждом из этих значений так же написано
по нескольку тысяч значений. Сложно? Вы думаете, что компьютеру легко перебрать их,
в поиске нужных сочетаний? А ведь именно так выглядит традиционный алгоритм сборки
классов в объектно-ориентированном программировании или семантическая сеть. Есть и еще
вариант, когда на этих же запчастях написаны и дополнительные условия сборки, где
указывается, как необходимо обследовать другие элементы и найти соответствия. Так
устроены и действуют многие экспертные системы.
А теперь предложим другой вариант. Вы вынимаете конструктор из очень большой
коробки, думая, что там лежит нечто еще сложнее. Но к своему удивлению видите, что в нем
находятся 5—7 уже собранных, готовых, соединенных из множества деталей, но больших
блоков, где все сочленения по поверхности комплементарны. У их подножия вы сразу
видите «бетонные» блоки, под ними — прикреплена земля, сверху трава и цветочки, стена,
окна.
Соединив два больших куска — вы сразу получили целую стену кирпичей с бойницами
на верхушке. А видя, что несколько элементов башни несоответствуют рисунку — вы легко
заменяете башню. Так, вам удается собрать весь конструктор, всего в несколько простых
действий, вместо того, чтобы создавать по невероятно сложной и фрагментированной
инструкции вселенную из атомов.
Как вы поняли, первый вариант это некомплементарная конструкция любого
действующего ООП, которое трудно как конструировать, так и упаковывать в одну коробку;
ведь чем больше раздельных деталей, тем больше шанс ошибиться, что-то забыть или
добавить слишком много.
В MSM мы укладываем не атомы кирпичей, мы укладываем последовательности, цепи,
стены из смыслов большими блоками, и не беда, если «кирпичи» сверху — не совпадают,
отсоединив верхний кусок мы легко получим другой, подходящий.

Метафора 2
Лабиринт отчаяния
Теперь представим, что вы оказались в огромном лабиринте. И чтобы выбраться из него,
у вас есть инструкция. В ней несколько тысяч страниц и она непоследовательна. На каждой
странице в ней написан ряд условий в соответствии с которыми вы должны менять
направление движения. Ее фразы оторваны от какой-либо логики и силясь ее понять, вы
только больше сходите с ума. Например: «На правой стене есть мох, внизу слева лежит
кирпич. Когда солнце светит справа в полдень, на стене слева сидит белая бабочка. Под
ногами песок? Поверните налево».
Вы сравниваете обстановку, находите несоответствие и листаете страницы
дальше. «На вас упал паук? Положите его в левый карман. Если паук шевелится, значит
скажите „да“ в мегафон. У вас нет мегафона? Проверьте страницу 511 и если она мокрая,
идите вперед». Страница за страницей вы перечитываете условия вашего движения,
но постоянно находите несоответствия, поэтому вынуждены делать долгие паузы и стоять
на месте. Да еще и книга очень тяжелая, вы сильно устаете. Вы едва ли успеете выбраться
из лабиринта дотемна, и уже почти на выходе столкнетесь, к примеру, с несоответствием.
На очередном повороте сидит жирная мышь и ест сыр. Но в инструкции об этом ничего
не сказано.
Эта толстая, бессмысленная, тяжелая книга полностью выводит вас из себя и вы
начинаете двигаться наугад, забросив ее.
Теперь мысленно перенесемся к началу лабиринта. Но в ваших руках уже другая
инструкция, всего на одном блокнотном листочке. В ней находится одна-единственная
надпись. «Идите в направлении таблички выход». Теперь вы замечаете, что почти на каждом
повороте есть знак «выход» и число в процентах, но также некоторые перекрестки и лишены
этой таблички. Оказавшись на новом перекрестке, (когда на предыдущем не было таблички),
вам остается только сравнить большее и меньшее значение, и отправиться в направлении
увеличения процентного показателя. Здесь вы не связаны с дополнительными условиями
и не успеваете даже устать, как покидаете лабиринт. Вас совсем не смущает жирная мышь
на выходе, она вам не помеха.
Все потому, что условия для вашего путешествия в лабиринте
были организованы до того, как вы оказались в нем. Элементы, (а именно таблички
со словом «Выход» и процентными данными), появлялись на вашем пути, как бы «сами
собой», по причине «предрешенности», вашего направления. Еще до своего появления
каждый «выход» может «найти» длину своего кратчайшего пути, а мы лишь оцениваем
величину расстояния в отношении с другими выходами и принимаем решение, — хорош
этот выход или плох.
Можно было бы обвинить эту систему в «избыточной» простоте. В связи с этим,
вероятность того, что все путешественники по лабиринту пойдут по одному пути, следуя
указателям, будут зашкаливать. Но в этом нет проблемы у системы, есть проблема —
у человеческого восприятия.

Принципиальная разница подхода к решению задач в MSM состоит в том, чтобы


формулировать новые правила обработки данных, а не решать задачу методом
комбинаторики связей и условий взаимодействия. То есть, чтобы описать условие, например,
закипания воды при температуре 100° C, нами будет записана обычная фраза-модель «Вода
закипает при температуре больше ста градусов Цельсия», но идея состоит в том, чтобы
научиться извлекать из таких обычных и подобных им фраз зависимости и конструировать
решения из записанных вами ранее слов-множеств.
Этот подход категорически отличается от стратегий, предложенных на сегодняшний
день другими онтологическими системами и методами программирования.

Сингулярность неизбежна
Сингулярность — это ситуация при которой общий искусственный интеллект, электронная
машина, станет разумнее среднестатистического человека. Футурологи называют это
явление «горизонт событий» по аналогии с явлениями, протекающими в глубоком космосе
рядом с черных дырами, где перестают действовать законы физики и невозможно
предсказать, что случится дальше. Различные авторы описывают эти события с разной долей
драматизма, но насколько эта ситуация может соответствовать действительности? И здесь
мы можем найти место нечеткости, субъективности в оценках. Прежде всего, нам следует
определиться, по каким критериям мы могли бы оценить разумность? По умению
обыгрывать человека в игры, обгонять по скорости выполнения ручного труда,
контролировать сложные процессы, делать изобретения?
Не стоит забывать, что интеллект — это адекватная реакция внешнему воздействию
с целью улучшения своей позиции, выживания и процветания. Поскольку сценой действий
интеллекта является социум, то отличие его от «глупости» будет состоять не только в жажде
жизни, но и в способности реконструировать чужое поведение, планировать сложные
действия, уметь договариваться и реагировать в соответствии со своим планом и выбранной
стратегией.
Как его можно отличить? Дальше уже зависит, насколько вы требовательны.
«Среднему» интеллекту достаточно одеть ботинки чтобы не замочить ноги, уметь вовремя
купить булку хлеба, чтобы не умереть с голода и не подраться с соседом на 9 мая. Для жизни
этого вполне достаточно. Такому интеллекту пригодится и умение «гуглить» текущие
проблемы и решать их с помощью других людей или электронных систем.
«Сильный» интеллект — это такой, который превосходит способности среднего
человека. Он уже будет способен сам найти себе работу и оформить загранпаспорт,
а по вечерам строчить по 40 постов в соцсетях на актуальные темы, зарабатывая на рекламе.
Может быть и не следует усложнять эти критерии?

Единство MSM как единство чисел


Меня всегда тревожила невозможность обратиться к слову естественного языка не как
к объекту, предмету, а как к смысловой переменной. Ведь мы хорошо научились обращаться
с числами тогда, когда появились цифры, которыми мы смогли оперировать
с использованием довольно строгих, но очень множественных правил. Почему же мы
не можем оперировать смыслами с той же легкостью? Потому, что у нас не было смысловой
переменной и правил обращения с ними.
Заметьте одну вещь: цифры сами по себе ничего не означают кроме разницы «веса»
между ними. Но стоит нам написать числа рядом, допустим число «97» и число «5», как мы
сразу можем сказать, какое из них больше, а какое меньше. Почему мы можем это сказать?
Потому что у нас есть правила. Мы не «изобретаем» их на ходу, эти правила
совершенствовались веками и тысячелетиями. Мы научились писать их в таком порядке
и таким образом, чтобы нам было удобно обращаться с ними.
Какой из этого следует вывод? Математическое действие это не есть операция разума,
(хотя для простейших вычислений это и не вполне очевидно), это операция правила. Набора
шаблонов действий.
И вот уже из этой удобной формы представления рождается нечто новое. То, что можно
делать с этими формами. Так, кроме элементарных операций сложения и вычитания у нас
уже появляется умножение и деление. Затем мы находим способы составлять простые
формулы, появляются константы вроде числа Пи… Затем появляются геометрические
формулы, синусы, косинусы, алгебраические уравнения, матрицы… Теперь эти формулы
применимы везде. Но, казалось бы, с чего это все началось?
С простой формы представления числа и там, где мы можем находить общее и различие.
Если бы эти формы не отвечали правилам стабильности и операбельности, человечеству
был бы неведом счет. Мы бы обращались с математикой, как аборигены экзотического
острова, вся способность которых на операции с числами заключена в принципе «Один»,
«Два» и «Много». Почему они не имеют математики? Потому, что у них не было
письменности и унифицированной формы, системы представления данных.
В многомерном строковом множестве мы научились представлять смысловые данные
в такой форме, в которой они являются унифицированными, стабильными
и комплементарными. Самыми легкими правилами по обращению с ними стали правила
нахождения общего и лишнего, — разницы между любыми переменными этого типа. Мы
научились агрегировать эти данные, находить зеркальные формы ответов, находить связи
между ними. Мы научились формализовать данные из естественного языка, находя смыслы,
переменные для незнакомых слов. Это не так уж и мало. Но если проводить аналогии
с математикой и MSM, по существу мы стоим на одной из первых ступеней развития, когда
только что было совершено открытие простейших операций, сложения, вычитания,
умножения и деления. Алгоритм волнового представления предложений из слов-множеств
мы могли бы сравнить, например, с функцией синуса. Это хорошее достижение, но сколько
их еще, этих правил, простых и сложных не открыты? Это сложно, практически невозможно
предсказать. Главное в том, что теперь у нас есть эта операбельная единица. Есть
унификация. Есть система.
Правила будут усложняться, но они будут обладать свойствами универсальности,
какими обладают правила в математике. И это дает большую надежду на то, что путь
по «осознанной» работе с данными естественного языка приведет нас к раскрытию загадок
сознания и созданию сильной логической машины, предшественника сильного
искусственного интеллекта.

Трое в лодке, не считая автора


По странному стечению обстоятельств, три человека, фамилии которых имеют польское
происхождение, уже сделали очень многое для поддержки теории, описываемой
на страницах этой книги.
Этих ученых можно назвать могучей кучкой нейронауки: Ноам Хомски, Марвин
Мински и Роберт Сапольски.
Попробуем суммировать наиболее важные тезисы их понимания процесса мышления
и (в случае с Марвином Мински) подходов к построению искусственного интеллекта.

Язык =Интеллект

Ноам Хомски — лингвист и нейрофизиолог говорит о том, что язык является не только
неотъемлемой частью коммуникации, но и составляет суть мышления. То есть, информация,
заложенная в смыслах языка, не может только «передаваться», она, в форме языка и является
носителем смысла. Соответственно, мышление невозможно без языка, как и язык без
мышления. Получается, что между интеллектом и языком мы можем поставить знак
равенства.

Изучать не мозг, но мышление

Марвин Мински — создатель нейросетей и гуру искусственного интеллекта дал нам


основную идею в том, что нам нет необходимости изучать мозг, исследуя отдельные
нейроны для того чтобы получить модель мышления. Эта задача схожа с попыткой изучать
процессор, исследуя отдельные транзисторы или группы транзисторов. Сложность
процессора сама по себе не позволит построить его модель на основании данных отдельных
паттернов его составляющих. В данном случае целое — не есть сумма частей, а попытка
восстановить действующий мозг в виртуальном пространстве и является примером этой
задачи.

Не реконструировать машину, но реализовывать метод

Еще одна замечательная идея Марвина Мински состоит в том, что принципы, идеи
и методики должны превосходить технологию конкретной структуры и частностей
физических взаимодействий. К примеру, компьютер — это не есть сумма элементов: как то,
конкретной материнской платы, с конкретной памятью, процессором, видеокартой; но —
машина для выполнения задач, построенная на методах обработки информации.
«…Чтобы построить части любой машины, мы можем использовать любое
достаточно сильное и стабильное вещество: все, что имеет значение, — это то, что
делает каждая отдельная часть, и как эти части соединяются. Например, мы можем
создавать разные компьютеры, которые выполняют одни и те же вещи, используя либо
новейшие электронные чипы, либо используя деревянные, струны и скрепки для бумаги,
размещая их части так, чтобы снаружи каждый из них выполнял те же процессы»…[3]
В итоге, для нас не имеет значения, из каких материалов будут сделаны определенные
элементы и микросхемы, на какой частоте работает процессор, с каким напряжением
подается ток на тот или иной транзистор или даже в какой разрядности чисел он работает;
мы могли бы построить отдельные его элементы, выполняющие определенные задачи
из дерева, стекла или пластика, шестеренок или консервных банок, — главное, это
правильно воплотить сам принцип работы для получения конкретного результата. Другими
словами, этот подход может называться так — «не важно, на чем это работает, важно,
что оно приносит результат».

«Не голова, а Дом Советов»

Третья замечательная идея Мински состоит в специфическом подходе к пониманию


человеческого сознания и функционирования мозга. Он говорит о множественности
раздельных процессов в мозге. Одновременное функционирование серии процессов он
сравнивает с функционированием различных компьютеров, связанных единой сетью. Эта
мысль была также высказана в 6 главе, и она хорошо дополняет идею работы
гештальт-циклов.

Неуникальное сознание

Роберт Сапольски — известнейший американский нейроэндокринолог, профессор


биологии, неврологии и нейрохирургии Стэнфордского университета подтверждает
многочисленные факты неуникальности того, что мы называем явлениями сознания
и мышления у животных. Так, Сапольски говорит об умышленных, жестоких, групповых
убийствах в среде шимпанзе; о распространенном у большинства млекопитающих
иерархическом поведении; этике у летучих мышей-вампиров; оценочном отношении
у стайных рыб; и многих других поведенческих явлениях, которые изначально
приписывались исключительно «человеку разумному». Он подтверждает идею, что
от природы мозг человека не является «умным», и вообще не отличается от мозга шимпанзе.
На генетическом уровне разницы между мозгом человека и мозгом шимпанзе фактически
нет: человек имеет только большее количество нейронов, обеспечиваемое дополнительными
тремя циклами деления нервных клеток.
— У нас (человека) примерно в три раза больше нейронов. В нашем геноме изменено
количество циклов делений в процессе формирования мозга в эмбрионе. По сути это
говорит о том, что если взять мозг эмбриона шимпанзе и дать ему три дополнительных
цикла деления, то мы получим мозг человека, и результат: симфонии, идеалогии, игру
в классики, и другое. И это нам говорит, что достаточное количество создает качество.
Просто количество. И уже из него происходит в этом нелинейном, необратимом процессе
все то, что делает нас людьми. Эти гены — о создании мозга. О мозге человека, об уровне
качества. Но в них нет ничего о том, какими именно эти качества будут. — отмечает
профессор Сапольски.[4]

[1] Марвин Ли Мински (Marvin Lee Minsky) (1927—2016), сооснователь Лаборатории


искусственного интеллекта в Массачусетском технологическом институте (США).
[2] http://you-books.com/book/M-Minsky/The-Emotion-Machine
[3] Цитата из книги «The emotional machine».
[4] Цитата из Видео YouTube «The Brights» «Роберт Сапольски. Мы особенные?»
от 22.02.2018, канал Agora Pogoda

Заключение
Завершая вторую книгу, посвященную строкам и MSM, хочется поблагодарить отважного
читателя, который перенес все тяготы ее содержания. В утешение предстоящему долгому
расставанию замечу, что на этом все только начинается.
В будущем нас еще ждет путешествие к анализу временных явлений, который позволит
рассматривать каждый объект классификатора, как динамическую модель; к адаптивным
циклам, которые могут стать универсальными «решателями» заданий;
к бихевиористическому поведению моделей; к явлениям «озадаченности», устойчивым
последовательностям и еще многим другим полезным вещам в безграничном мире
символьных последовательностей.
На прощание мне хочется привести одну цитату, которая за много лет не утратила своей
актуальности:
«Программист — это создатель вселенных, вседержителем которых он сам
и является. Ни один драматург, режиссер или император в истории не обладал такой
абсолютной властью при постановке спектакля или на поле боя, и не имел в своем
распоряжении таких неукоснительно преданных делу актеров или воинов.»
Джозеф Вейценбаум, профессор Массачусетского технологического института,
автор программы «Элиза».

У вас уже появилось желание создавать что-то новое? Значит, все это было не зря.
С. В. Соболенко, 11.02.2019 г.

Вам также может понравиться