ВСЕ ЗДЕСЬ!!!!
Календарь новостей
«  Сентябрь 2011  »
ПнВтСрЧтПтСбВс
   1234
567891011
12131415161718
19202122232425
2627282930
Друзья сайта
           


Форма входа
Поиск
Мини-чат
200
Статистика

Сейчас на сайте: 1
Гостей: 1
Пользователей: 0
Суббота, 04.05.2024, 03:31
Приветствую Вас Гость | RSS
Главная | Регистрация | Вход
Главная » 2011 » Сентябрь » 25 » Привет, SkyNet!
Привет, SkyNet!
14:11



Пока руководство Foxconn закупает металлических работников, суровые японские ученые готовят замену, видимо, старшим инженерам и маркетологам подобных компаний. Робот SOINN (что расшифровывается как self-organizing incremental neural network, то есть «самоорганизующаяся возрастающая нейронная сеть») способен учиться, анализировать окружающую обстановку и самостоятельно принимать решения. Получая новое задание, SOINN поступает точно также, как поступают лучшие представители человеческой расы: использует весь свой накопленный опыт, изучает окружающие его предметы и экспериментирует.



Фактически, перед тобой очень ранний прототип искусственного интеллекта. И, по всей видимости, в будущем мир изменится куда радикальней, чем это представляется большинству писателей-фантастов.


Робота научили решать задачи на основе базовых знаний

В Японии, в лаборатории Hasegawa Lab, учёные использовали «самоорганизующуюся инкрементную нейронную сеть» (Self-Organizing Incremental Neural Network — SOINN), для управления роботом HIRO (Kawada Industries).


SOINN(Self-Organizing Incremental Neural Network) — это неконтролируемый метод онлайн-обучения, способный к дополнительному обучению, основанному на Росте Нейронного Газа (Growing Neural Gas (GNG)) и самоорганизующихся картах (Self-Organizing Map (SOM)). Нестационарные онлайн-данные, имеют сложное распределение, но можно приблизительно распределить входные данные и оценить соответствующие число классов — это и является основой самоорганизации сети. 
Кроме того, сеть имеет следующие особенности:
* отсутствие необходимости предопределения структуры сети,
* высокая устойчивость к шумам.
Т.о. методология SOINN может быть очень эффективна для использования в реальных приложениях.



 Оперируя базовыми знаниями и навыками, робот «решает» как ему налить, а затем подать человеку стакан воды


5555


Пример работы самоорганизующейся инкрементной нейронной сети SOINN

Учёные использовали «самоорганизующуюся инкрементную нейронную сеть» (Self-Organizing Incremental Neural Network — SOINN), для управления роботом HIRO (Kawada Industries) с целью решения задач на основе базовых знаний ( т.е. алгоритм ИИ делает предположения и принимает решения на основе своего предыдущего опыта).

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

И всё бы ничего — в новостных лентах часто появляются новости про очередные мега-достижения в науке и технике, но зайдя на сайт Hasegawa Lab можно обнаружить статьи в формате PDF про их исследования и, что ещё более важно, проект на C++:
SOINN (C++) — Microsoft Visual Studio 2005 solution
с пояснительной PDF-запиской How to Use the SOINN Software

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

Если попробовать собрать проект под Visual Studio 2008 express edition, то сразу не получится — выпадает ошибка:
fatal error RC1015: cannot open include file 'afxres.h'

— ошибка в отсутствии afxres.h (в файле Application\resource.rc)):
Причина — нет MFC и чтобы решить эту проблему нужно просто отредактировать resource.rc и заменить «afxres.h» на <windows.h>

В стандартной сборке Visual Studio Express не хватает двух файлов winres.h и afxres.h. Их можно скачать и распаковать в C:\Program Files\Microsoft SDKs\Windows\v7.0A\Include — для экспресса 2010 или v6.0\Include — для 2008.


Под обычной версией Visual Studio 2008 всё собирается с одного клика и в директории
soinn-project-vs2005\Application\Release\
появляется файл Application.exe


Сразу же бросается в глаза, что код написан очень хорошо и понятно. Собственно сам SOINN содержится в одноимённом проекте и состоит всего из 6 файлов (soinn-project-vs2005\SOINN\):
CEdge.cpp
CEdge.h
CNode.cpp
CNode.h
CSOINN.cpp
CSOINN.h

CSOINN — реализует алгоритм SOINN
CNode — узел (нейрон) в сети
CEdge — связь между двумя узлами


SOINN API:

CSOINN::InputSignal(const double *signal)
— реализует алгоритм SOINN для входных данных (signal).

CSOINN::Classify(void)
— присваивает идентификатор класса для всех узлов в соответствии с текущей структурой сети.


CSOINN::Reset(const int dimension=NO_CHANGE, const int lambda=NO_CHANGE, const int ageMax=NO_CHANGE)

— сбрасывает параметры SOINN (размер, счётчики удаления узлов). В текущей реализации, все узлы и связи сети, также удаляются.

CSOINN::GetNodeNum(const bool ignoreAcnode=false)
— возвращает текущее количество узлов в сети.

CSOINN::GetClassNum()
— возвращает текущее число классов в сети.

CSOINN::GetNode(const int node)
— возвращает экземпляр CNode с id, переданным в качестве аргумента функции.


CSOINN::GetClassFromNode(const int node)
— возвращает идентификатор класса из CNode с id, переданным в качестве аргумента функции.

CSOINN::SaveNetworkData(const char *fileName)
— сохраняет текущее состояние сети в заданный файл.

CSOINN::LoadNetworkData(const char *fileName)
— загружает сеть из заданного файла.
CNode::GetSignal()
— возвращает вес вектора экземпляра CNode.


CNode::GetClass()
— возвращает идентификатор класса экземпляра CNode.


при добавлении нового сигнала через
CSOINN::InputSignal(const double *signal)
проверяется существующее количество узлов в сети и если их меньше двух, то сигнал просто добавляется как новый узел сети, во всех остальных случаях — сначала выявляются два узла сети, ближайших к поступающему сигналу — метод
CSOINN::FindWinnerAndSecondWinner(int &winner, int &secondWinner, const double *signal)
Затем, производится проверка относится ли сигнал к новым данным с помощью метода
CSOINN::IsWithinThreshold(const int winner, const int secondWinner, const double *signal)
— внутри него просто вычисляется расстояние от двух ближайших узлов до заданного сигнала и если оно больше, чем порог подобия ( CSOINN::GetSimilarityThreshold(const int node) ), то сигнал добавляется в качестве нового узла сети, в противном случае формируется связь между двумя полученными узлами.

классификация — CSOINN::Classify(void)
— это рекурсивный обход сети и назначение id-ка класса (CSOINN::SetClassID(const int node, const int classID)) всем узлам, которые связанны между собой.

Попробуем запустить этот алгоритм :)

создадим проект, в настройках проекта укажем:
С/C++ - Code Generation - Runtime Library - /MT

в противном случае при сборке проекта появится ошибка:

LINK : warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs; use /NODEFAULTLIB:library

пропишем путь до заголовочных файлов и путь до готового SOINN.lib

мой тестовый проект на основе примера из руководства:

//
// тестовый пример работы с SOINN
// http://haselab.info/soinn-e.html
//
// http://robocraft.ru
//

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

#include "CSOINN.h"

#define DIMENSION 2
#define REMOVE_NODE_TIME 200
#define DEAD_AGE 100

// показать информацию о SOINN-сети
void show_SOINN_info(CSOINN* pSOINN);

// расстояние между двумя сигналами
double Distance(const double *signal1, const double *signal2, int dimension=DIMENSION);

int main(int argc, char* argv[])
{
printf("[i] Start...\n");

CSOINN* pSOINN = 0;

// создание объекта SOINN
pSOINN = new CSOINN ( DIMENSION , REMOVE_NODE_TIME , DEAD_AGE );

if(!pSOINN){
printf("[!] Error: cant allocate memory!\n");
return -1;
}

// для хранения входных данных
double signal[DIMENSION];

int i=0;

//-----------------------------------------
for(i=0; i<10; i++){
signal[0] = 0;
signal[1] = i;

// добавляем данные в сеть
pSOINN -> InputSignal ( signal );
}

// классификация данных
pSOINN -> Classify ();

// поcмотрим информацию о SOINN-сети
show_SOINN_info(pSOINN);
//-----------------------------------------
double delta = 0.9;

#if 1
for(i=0; i<10; i++){
signal[0] = i;
signal[1] = i;

// добавляем данные в сеть
pSOINN -> InputSignal ( signal );
}

// классификация данных
pSOINN -> Classify ();

// поcмотрим информацию о SOINN-сети
show_SOINN_info(pSOINN);
#endif
//-----------------------------------------

// 1-NN algorithm .
double minDist = CSOINN :: INFINITY ;
int nearestID = CSOINN :: NOT_FOUND ;

// тестовый сигнал
double targetSignal[DIMENSION];
targetSignal[0] = 1+delta;
targetSignal[1] = 1+delta;

for(i=0; i < pSOINN->GetNodeNum(); i++ ){

double* nodeSignal = pSOINN -> GetNode ( i )-> GetSignal ();
double dist = Distance ( targetSignal , nodeSignal );

if ( minDist > dist ) {
minDist = dist ;
nearestID = i;
}
}

int nearestClassID = pSOINN -> GetNode ( nearestID )-> GetClass ();
printf ("[i] SOINN: Nearest Node ID : %d, Class ID : %d.\n", nearestID , nearestClassID );

if(pSOINN){
delete pSOINN;
pSOINN = 0;
}

printf("[i] End.\n");
return 0;
}

// показать информацию о SOINN-сети
void show_SOINN_info(CSOINN* pSOINN)
{
if(!pSOINN){
return;
}

// покажем информацию о сети
printf("[ ] SOINN info: \n");
printf("[i] Dimension: %d\n", pSOINN->GetDimension());
printf("[i] NodeNum: %d\n", pSOINN->GetNodeNum());
printf("[i] EdgeNum: %d\n", pSOINN->GetEdgeNum());
printf("[i] ClassNum: %d\n", pSOINN->GetClassNum());
printf("----------------------------\n");

}

// расстояние между двумя сигналами
double Distance(const double *signal1, const double *signal2, int dimension)
{
int i;
double sum;

if (signal1 == NULL || signal2 == NULL || dimension<=0) return 0.0;

sum = 0.0;
for (i=0; i<dimension; i++){
sum += (signal1[i]-signal2[i])*(signal1[i]-signal2[i]);
}

return sqrt(sum)/(double)dimension;
}

вывод:

[i] Start...
[ ] SOINN info:
[i] Dimension: 2
[i] NodeNum: 10
[i] EdgeNum: 0
[i] ClassNum: 10
----------------------------
[ ] SOINN info:
[i] Dimension: 2
[i] NodeNum: 19
[i] EdgeNum: 1
[i] ClassNum: 18
----------------------------
[i] SOINN: Nearest Node ID : 11, Class ID : 10.
[i] End.

угу — как-то работает :)

Попробуем как-нибудь применить эту сетку :)
Например, подружим её с OpenCV :)

в качестве сигнала я использую координаты ненулевых пикселей бинарной картинки (в данном примере — это границы, полученные после детектора границ Кенни).

при попытке её приладить возникли трудности с доступом к переменным класса CEdge и CNode, которые в программе японцев решается friend-доступом, но я решил пока просто перетащить исходники SOINN в свой проект и дать public-доступ закрытым переменным (m_from и m_to из CEdge, m_signal из CNode), которые нужны для отрисовки :(

На одной картинке мы не увидим почти ничего интересного, но если обернуть процедуру обработки сигнала в цикл, то всё будет намного интереснее (и это не удивительно — жизнь это движение ;)


основа:

CSOINN* pSOINN = 0;

// создание объекта SOINN
pSOINN = new CSOINN ( DIMENSION , REMOVE_NODE_TIME , DEAD_AGE );

if(!pSOINN){
printf("[!] Error: cant allocate memory!\n");
return -1;
}

unsigned int round = 0;

while(cvWaitKey(33)!=27){
// для хранения входных данных
double signal[DIMENSION];

// пробегаемся по всем пикселям изображения
for( int y=0; y<bin->height; y++ ) {
uchar* ptr = (uchar*)(bin->imageData + y * bin->widthStep);
for( int x=0; x<bin->width; x++ ) {
// если пиксель белый
if(ptr[x]>0){
signal[0] = x;
signal[1] = y;
// добавляем данные в сеть
pSOINN -> InputSignal ( signal );
}
}
}


// классификация данных
pSOINN -> Classify ();

// покажем номер итерации
printf("[i] round: %d \n", round++);
// поcмотрим информацию о SOINN-сети
show_SOINN_info(pSOINN);

show_SOINN(pSOINN, soinn);

cvShowImage("SOINN", soinn);

}

функция отображения сети (адаптированый вариант функции COutputWindow::Refresh()):

// показать сеть SOINN на картинке :)
void show_SOINN(CSOINN* pSOINN, IplImage* img)
{
if(!pSOINN || !img){
return;
}

int i, f, t, nodeNum, edgeNum;
double x, y, x0, y0, x1, y1;
CNode* node;
CEdge* edge;

// очистим картинку
cvZero(img);

edgeNum = pSOINN->GetEdgeNum();
for (i=0; i<edgeNum; i++){
edge = pSOINN->GetEdge(i);
f = edge->m_from;
node = pSOINN->GetNode(f);
x0 = node->m_signal[0];
y0 = node->m_signal[1];

t = edge->m_to;
node = pSOINN->GetNode(t);
x1 = node->m_signal[0];
y1 = node->m_signal[1];

cvLine(img, cvPoint((int)x0, (int)y0), cvPoint((int)x1, (int)y1), CV_RGB(250,250,250), 1, 8);
}

nodeNum = pSOINN->GetNodeNum();
for (i=0; i<nodeNum; i++){
node = pSOINN->GetNode(i);

x = node->m_signal[0];
y = node->m_signal[1];

cvCircle(img,cvPoint((int)x, (int)y), 2, m_color[node->m_classID%MAX_COLOR], -1, 8);
}
}

1-й раунд:


132-й:


а вот какую gif-ку (3.3Mb) у меня получилось замутить:


забавно — прямо возникло чувство сопричастности к передовым разработкам в области ИИ для роботов :)))

SOINN.zip — архив проектов (с exe-ками):
SOINN\soinn-project-vs2005
SOINN\test
SOINN\soinn2cv


UPD
добавил в архив проект SOINN\soinn2cv2, в котором в качестве входного сигнала в сеть подаются координаты клика мышкой

обратите внимание, что для программы soinn2cv требуется OpenCV версии 2.1


Оригинал статьи

Просмотров: 2226 | Добавил: sonic | Рейтинг: 0.0/0 |
Всего комментариев: 0
Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
Copyright MyCorp © 2024
Сайт управляется системой uCoz