Pull to refresh

Alan Platform

Reading time13 min
Views1.3K
Приветствую уважаемых профессионалов и просто любителей Искусственного Интеллекта. Давненько я не отваживался написать сюда ничего значительнее комментария. Дальнейшее копание в теории и философии выглядело бы бессмысленно без намека на практику. Пришло время сделать этот намек. Но для начала не мешало бы освежить память.

В предыдущих сериях.


.… Дело было в далеком 1956 году (к этому времени уже существовала серия книг Азимова о роботах). В США, в Стэнфордском университете состоялся семинар, на котором и предложили термин Искусственный Интеллект… Сейчас речь идет скорее о «некоторых характеристиках Искусственного Интеллекта», нежели о самом ИИ... [1]

… На основании данных о строении нейронов, клеток нашего мозга, они пытались воссоздать их структуру. Это было за несколько лет, до того самого семинара, где впервые заговорили об ИИ… Скажем прямо, что хотим, чтобы Искусственный Интеллект был максимально приближен к человеческому... [2]

… Создать что-то функционирующее в точности как наш интеллект куда проще, чем изображать из себя бога и с нуля изобретать систему, которая смогла бы с момента запуска автономно (без вмешательства в архитектуру) развиваться… Признаюсь, сначала у меня была идея использовать виртуальный мир, созданный на компьютере в виде трехмерной интерактивной модели... [3]

… Процесс мышления сводится к работе с информацией… Искусственный интеллект – это вопрос умения увидеть нужное и отбросить все лишнее... [4]

… Это я только раньше думал, что возьму толстый справочник по физиологии человека и найду там ответы на все вопросы… На самом деле, на низком уровне между мотивациями и эмоциями существует прямая связь... [5]

… Если мы хотим, чтобы он развивался как человек и думал как человек, то нужно создать для него мир, максимально соответствующий реальному. Иначе мы получим интеллект уровня пришельца с Альфы Центавра… Для этого во время обучения, когда она будет заползать на освещенные области, ее будет «бить током» – это ей очень не понравится... [6]

Немного философии


Память освежили — можно приступать к делу. Начнем с того, что подытожим философские рассуждения, начатые в предыдущих заметках. Одной из главных линий там была идея о том, что нужно определиться со сторонами и качествами человека, которые мы хотим видеть в ИИ, и сосредоточиться на их реализации. А все остальное нужно просто отбросить. Я понимаю, что у каждого есть собственное мнение на этот счет. Именно поэтому единого определения ИИ не существует. Каждый сам выбирает, насколько точной и детализированной должна быть модель интеллекта.

Я свой выбор сделал в пользу воссоздания основных функций мозга в контексте работы с информацией, таких как: восприятие информации, ее эмоциональная оценка, формирование образов объектов, принятие решений о совершении действий, выявление закономерностей и прочее. В общем все базовые функции, которые связаны с информацией и памятью. Вроде бы ничего особенного, но идея в том, чтобы заставить все это работать сообща и автономно. Это можно сравнить с игрой, в которой нужно построить водопровод между точками А и Б. Все будет работать только тогда, когда все фрагменты системы идеально подогнаны друг под друга. И обычно среди огромного множества возможных комбинаций только одна является верной.

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

Пока что сосредоточимся на цифровой форме информации и подумаем над интерфейсами мозга. Однозначно у него должны быть вход и выход. Можно, конечно, придумать какие-нибудь хитрые форматы, в которых информация будет поступать в мозг и выходить из него, но это только лишь усилит связанность системы и затруднит добавление новых каналов информации. Универсальным решением в данной ситуации будет простой массив значений с двойной точностью, допустим, от 0 до 1. В таком виде можно представить все, что угодно. Если это запах, то значения будут говорить об интенсивности различных оттенков этого запаха. Если это зрение, то о величине освещенности, дальности, цвете — зависит от сложности зрения. Осязание — интенсивность для различных зон чувствительности и т. д. Исходящая информация также легко интерпретируется — в значениях закодированы, допустим, импульсы вращения костей в суставах. Вообще то, что информацию можно легко интерпретировать очень важно. Это очень поможет, когда мы захотим сделать дамп мозга и понять, о чем он думал в тот момент.

Немного практики


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

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

Ну все, хватит пустых слов. Намного проще все показать на примерах. Начнем с создания объекта с определенными свойствами.

var apple = new Component(new PropertySetInfo {
  Name = "Circle",
  OperatorName = "Some2DLayout",
  Properties = new PropertyInfo[] {
    new PropertyInfo { Name = "Radius", Value = 0.5 },
    new PropertyInfo { Name = "CenterX", Value = 0.0 },
    new PropertyInfo { Name = "CenterY", Value = 0.0 }
  }}, new PropertySetInfo {
  Name = "RGB",
  OperatorName = "ColorOperator",
  Properties = new PropertyInfo[] {
    new PropertyInfo { Name = "Red", Value = 1.0 },
    new PropertyInfo { Name = "Green", Value = 0.0 },
    new PropertyInfo { Name = "Blue", Value = 0.0 }
}});


* This source code was highlighted with Source Code Highlighter.

Этим кодом мы создали яблоко… Ладно, плоскую модель яблока — круг красного цвета. Что можно сказать интересного, глядя на этот код? Во-первый, не видно никакой реализации работы указанных свойств. Компонент является лишь контейнером, который содержит названия своих свойств и их значений. Он нужен лишь как абстракция для различных объектов. Во-вторых пока не понятно, что означает свойство OperatorName. Операторы занимаются тем, что управляют свойствами. В одной модели их может быть несколько, по одному на тип информации. Например, в приведенном коде Some2DLayout отвечает за расположение в пространстве и размеры, а ColorOperator — за информацию о цвете. Вот, как может выглядеть код ColorOperator:

[PropertySet("RGB", "Red", "Green", "Blue")]
[PropertySet("GrayScale", "Value")]
public class ColorOperator : Operator { }


* This source code was highlighted with Source Code Highlighter.

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

Итак, что делает оператор? Сперва он ищет, какие объекты объявили, что содержат его свойства. Затем он для каждого такого свойства создает у себя внутри объект PropertyData, который и будет хранить реальную информацию о свойстве. Это также сделано для удобства, чтобы все свойства всех объектов с одним типом информации были в одном месте — так ими проще управлять.

Следующий фрагмент кода:

var root = new Component();
root.Add(apple, plate, table);
root.Add(new ColorOperator, new Some3DOperator());


* This source code was highlighted with Source Code Highlighter.

Как видим, компонент является не только контейнером для свойств, но также и для других компонентов и операторов. У самого компонента root нет каких-то особых функций — он просто объединяет все элементы модели мира в одно дерево.

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

Сенсоры — это аналоги органов чувств, а действия — своеобразные функции организма, которые он может выполнять над объектами. Первые будут преобразовывать свойства объектов в массив значений double, который пойдет в мозг, а вторые — использовать информацию, поступившую от мозга (double[]) для изменения значений свойств объектов. Так как каждый сенсор и действие работают с информацией определенного типа, то они должны быть связаны с одним из операторов. Следующий фрагмент кода демонстрирует, как может выглядеть реализация сенсора.

[AssociatedOperator("ColorOperator")]
[ChannelsCount(3)]
public class ColorSensor : Sensor
{
  public override void Update(IEnumerable<PropertyData> data)
  {
    // Определяем, какие из свойств находятся в поле зрения сенсора
    // Допустим, что он видит только то, что находится у него под ногами.
    var layout = this.Parant.Parant.Layout; // будет ссылаться на Some2DLayout
    
    // Выбираем только те свойства, которые принадлежат объектам,
    // пересекающимся с самим организмом.
    VisibleProperties = data
      .Where(x => layout.GetBounds(x.ComponentId)
        .Intersect(layout.GetBounds(this.Parent.Id)))
      .ToArray();
  }
  
  public override void Transmit()
  {
    // Так как под ногами может быть несколько объектов, а разрешение у сенсора
    // не ахти какое, то придется найти среднее значение для каждого канала.
    double red = 0;
    double green = 0;
    double blue = 0;
    
    var redValues = VisibleProperties
      .Where(p => p.PropertyName == "Red" || p.PropertyName == "Value")
      .ToArray();
    if (redValues != null)
      red = redValues.Aggregate((sum, val) => sum + val) / redValues.Length;
    
    // ... (аналогично для green и blue)
    
    double[] data = { red, green, blue };
    ConnectedBrain.Update(this.Name, data);
  }
}


* This source code was highlighted with Source Code Highlighter.

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

Первый метод Update нужен для того, чтобы из множества свойств оператора выбрать только те, которые должны находиться в «поле зрения» сенсора. Этот метод переодически вызывается оператором, когда один из объектов перемещается в пространстве. Второй метод Transmit преобразует информацию из свойств в некую универсальную форму и передает результат в мозг. Он вызывается оператором каждый раз, когда изменяется значение одного из свойств, видимых сенсору. Действия реализуются схожим образом, только вместо метода Transmit у них есть DoAction, который производит обратную операцию — поступившие данные double[] datа используются для изменения VisibleProperties. Именно на этом этапе и реализуются законы мира, которые разрешают или запрещают изменения свойств в определенных ситуациях.

В представленном выше коде есть одна интересная строчка: «var layout = this.Parant.Parant.Layout;». Насчет двойного обращения к родителю — это должно быть понятно, если вспомнить, что все элементы объеденены в дерево. Первый раз мы получим ссылку на организм, к которому принадлежит сенсор, а во второй — на объект root, к которому был добавлен организм. А вот про Layouts я еще ничего не сказал. Исправляюсь.

Layout — это особый тип операторов, который управляет информацией о расположении объектов. Он нужен для того, чтобы отслеживать факт перемещения объекта (изменения свойств, отвечающих за координаты), изменения его размера и ориентации в пространстве. В каждом дереве элементов должен присутствовать один Layout, так как практически все сенсоры и действия будут прибегать к его услугам. Определение Layout выглядит примерно так:

[PropertySet("Circle", "Radius", "CenterX", "CenterY")]<br>[PropertySet("Rectangle", "Left", "Top", "Right", "Bottom")]<br>public class Some2DLayout : Layout<br>{<br>  const int radius = 0;<br>  const int centerX = 1;<br>  const int centerY = 2;<br>  const int left = 0;<br>  const int top = 1;<br>  const int right = 2;<br>  const int bottom = 3;<br>  <br>  public TestLayout()<br>  {<br>    /* Для каждого набора свойств добавляем метод, вычисляющий<br>     * координаты центра объекта по этим свойствам.<br>     * Здесь р - это массив со значениями свойств из одного набора,<br>     * а индексы - это порядковые номера свойств.<br>     */<br>    this.AddCenterMethod("Circle", p => new Center(p[centerX], p[centerY]));<br>    this.AddCenterMethod("Rectangle", p => new Center(<br>      (p[left] + p[right]) / 2,<br>      (p[top] + p[bottom]) / 2<br>    );<br>    <br>    // Аналогично добавляем методы для вычисления границ объекта.<br>    // В данном случае границами будет описанный прямоугольник.<br>    this.AddBoundsMethod("Circle", p => new Bounds(<br>      p[centerX] - p[padius],<br>      p[centerY] - p[radius],<br>      p[centerX] + p[radius],<br>      p[centerY] + p[radius]<br>    );<br>    this.AddBoundsMethod("Rectangle", p => new Bounds(p[left], p[top], p[right], p[bottom]));<br>  }<br>}<br><br>* This source code was highlighted with Source Code Highlighter.

Атрибуты — в точности как у оператора, константы — чтобы было проще читать следующий далее код. В конструкторе Layout обязательно нужно указать методы, по которым будут вычисляться координаты центра и границ для каждого набора свойств. Если выбрать достаточно хитрые наборы, для которых эти методы будут одинаковы, то можно добавить только один с именем «Default» в качестве имени набора свойств.

Итак, методы AddCenterMethod принимают два аргумента — имя набора свойств и делегат. Делегат имеет вид: Func<double[], Center> method. На вход он ожидает массив, состоящий из значений всех свойств набора, а на выходе должны быть координаты центра (Center) или границ (Bounds). После этого можно в любой момент времени получить данные координаты, вызвав соответствующие методы Layout: GetCenter и GetBounds, и передать им id компонента, расположение которого вас интересует.

Что это было?


Это были некоторые из возможностей Alan Platform. Большинство из них уже работает, некоторые ожидают, пока их кто-нибудь реализует. За кадром оказалось моделирование внутреннего времени системы, так как обоснование необходимости его реализации заняло бы довольно много места и времени. Чтобы как-то собрать воедино всю эту информацию, я опишу, что из себя будет представлять работа с этой библиотекой. Сначала это разработка библиотек расширений. Создание различных операторов, Layouts, сенсоров и действий — всего, что отвечает за работу с информацией. Затем — конструирование с помощь этого различных объектов и организмов и объединение их в одну замкнутую систему — искусственное окружение. Последнее можно осуществлять с помощь XML (частично реализовано), а в будущем можно добавить какой-нибудь GUI для этого.

Данная платформа принципиально не содержит никакого GUI. Она лишь позволяет формировать различные деревья из компонентов, операторов и т. п… Предполагается, что взаимодействие с системой должно осуществляться в рамках ее законов. Для этого можно сконструировать отдельный организм, которым будет управлять не модель мозга, а пользователь. Это будет что-то вроде модели бога. Его сенсоры могут охватить весь мир целиком и преобразовать информацию о свойствах объектов для вывода ее на экран. Аналогично с действиями — они могут «дотянуться» до любого объекта и изменить его свойства. Действия также могут быть подключены к интерфейсу. При этом данный организм будет иметь нулевые размеры и существовать везде и одновременно нигде. Организмы, заселяющие искусственный мир смогут лишь догадываться о его существовании по косвенным признакам: спонтанному исчезновению стен, появлению еды, ударам молний…

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

Вот здесь можно посмотреть исходники, все пока что разбросано по различным бранчам. Внутренностей мозга еще нет. Наверное это не дотягивает даже на Technical Preview, но проследить некоторые идеи уже можно. Если кому-то данный проект покажется интересным и возникнет желание принять в нем участие — прожалуйста, напишите мне в личку. Если все будет хорошо, то в самом ближайшем будущем будет материал по реализации одной из особенностей мозга — формирование и распознавание образов.
Tags:
Hubs:
+16
Comments60

Articles

Change theme settings