воскресенье, 21 ноября 2010 г.

Doctrine 2 - Getting Started XML-Edition на русском

Наконец-то окончил перевод Getting Started XML-Edition на русский язык.. Это руководство, которое позволяет быстро ознакомиться с Doctrine 2 и ее возможностями и сразу после прочтения руководства начать использование.

Перевод вы можете скачать более удобном для вас виде:

      

А также в онлайн виде на Google Docs - это версия всегда будет самой свежей, а остальные я буду периодически обновлять.

Огромная просьба, если вы заметите ошибки в переводе или знаете как его можно улучшить сообщите мне об этом в комментариях здесь или на email - krasun.net@gmail.com. Также если вы узнаете об обновлении руководства раньше, чем я сообщите мне об этом.

Только вместе мы сможем сделать перевод руководства лучше.

пятница, 19 ноября 2010 г.

Модульное тестирование при использовании SWI-Prolog

В императивных языках программирования, таких, например, как C#, Java или C++ программисты часто используют модульное тестирования. Суть подхода заключается в том, что сначала пишется тест для некоторой функциональной единицы (модуля), а после чего уже пишется код самого модуля. Мы просто поменяли процесс, если раньше мы сначала писали код, потом тестировали, то сейчас мы сначала пишем тест, потом пишем код, а потом тестируем (уже автоматизированно). Конечно, полная автоматизация тестирования это миф, но все же большую часть кода можно покрыть тестами.

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

Такой подход к разработке, называется разработка через тестирование (Test Driven Development) и я считаю, он себя оправдывает при написания проектов, где будет вноситься много изменений в код или проект, просто должен быть создан за короткие сроки. Не думайте, что вы потеряете время на написание тестов, пройдете время и вы поймете, что на самом деле вы только выигрываете.

Теперь о SWI-Prolog, в ПроЛоге мы с вами используем предикаты для реализации логики. И значит, тестировать мы будем предикаты. Идея такая: мы создаем предикат test_p, который тестирует наш предикат p. Как будет проходить тест?

Все очень просто. Для тестирования, мы будем задавать заранее известные входные параметры (термы) и сверять результат исчисления предиката с заранее известным правильным ответом. Если ответы совпали, все в порядке идем дальше, если нет выдаем информативное сообщение.

Для наглядности покажу простой пример, используя SWI-Prolog, заранее оговорюсь, эти же идеи применимы для любой другой версии компилятора ПроЛога.

Напишем предикат max(X, Y, Max), вычисляющий максимальное значение из 2-ух элементов, для начала опишем тест, затем реализацию:

% сперва напишем тест
test_max1 :- 
    max(3, 2, X), 
    X = 3 , !.
test_max1 :- 
    write('max(3, 2, X) вычислен не правильно!'),  
    nl.

test_max2 :- 
    max(2, 3, X), 
    X = 3, !.
test_max2 :- 
    write('max(2, 3, X) вычислен не правильно!'), 
    nl.

test_max3 :- 
    max(2, 2, X), 
    X = 2, !.
test_max3 :- 
    write('max(2, 2, X) вычислен не правильно!'), 
    nl.

run_tests :- 
    test_max1, 
    test_max2, 
    test_max3.
    
% теперь опишем предикат, max 
max(A, B, B) :- 
    A < B, 
    !.
max(A, _, A).

Запустим программу и вот, что увидим:



Изменим, чуть код, не важному почему, допустим случайно, или так надо было:

% ...    

% теперь опишем предикат, max 
max(A, B, B) :- 
    A > B, 
    !.
max(A, _, A).

И вот, что мы увидим в результате.



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

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

понедельник, 15 ноября 2010 г.

Определяем уравнение прямой при помощи искусственных нейронных сетей

Я начал изучать иск. нейронные сети, первая книга с которой я познакомился была Калан. Р. - Основные концепции нейронных сетей. Прочтя эту книгу за 2 дня признаюсь честно, я так ничего и не понял. Решил начну еще раз сначала, после чего прочитал серию статей. И пришел к выводу, что без практики я мало, что пойму. Вот собственно, почему я и начал этот пост. Теперь ближе к теме.

Советую, вам для начала ознакомиться с материалом при приведенным выше ссылкам. После чего, вам уже не сложно будет понять о чем пойдет речь. Задачу, которую я буду решать, я взял из книги Калана Р., звучит, она примерно так - найти уравнение прямой для заданных точек (скриншот):



Нам будет дан набор точек и на основе него, необходимо найти коэффициенты с и m - в уравнение прямой y = mx + c. Для обучения сети будем использовать дельта-правило - (правило Видроу-Хоффа). Если вкратце, то суть правила такова, мы на вход сети (в нашем случае перцептрон)  подадим значение координаты X, сеть вычислит значение координаты Y, мы сравним вычисленное сетью значение с ожидаемым и получим отклонение, то есть ошибку E. После чего мы полученную ошибку умножим на норму обучения n (она задается вручную) и на сигнал приходящий к Y, в результате мы и получаем отклонение весов dw1, dw2 и так далее. Остается только скорректировать весы w1 = w1 + dw1, w2 = w2 + dw2, ... 

Архитектура сети, также взято из Калан. Р., не удивляйтесь на то, что я привожу материалы из источников, моя задача запрограммировать сеть с использованием C#: 



До каких пор обучать сеть? Здесь, все просто до приемлемого уровня заданной точности, например, до 0.05 или просто провести обучение определенное количество раз, например, 10000. Теперь приведу, код программы, которая имитирует данный перцептрон:


// задаем начальное значение весов случайным образом 
// в интервале от [-0.3, 0.3] 
double[] w = new double[] 
{ 
    ((rD = r.Next(-100, 100) * 0.003) == 0) ? 
        0.3 : rD,
    ((rD = r.Next(-100, 100) * 0.003) == 0) ? 
        0.3 : rD
};

double[] w1 = new double[2]; 
w.CopyTo(w1, 0);

// входные сигналы
double[] x = new double[]
{
    1.0, 
    0.0
};

// норма обучения или скорость обучения 
double n = 0.1; 

double[,] pairs = new double[,] 
{
    {0.2, 1.3},
    {0.25, 1.3},
    {0.4, 1.4},
    {0.48, 1.52},
    {0.6, 1.6},
    {0.8, 1.6},
    {0.9, 2},
    {1, 2.1}
};
            
for (int i = 0; i < 10000; i++)
{
    for (int j = 0; j < pairs.GetLength(0); j++)
    {
        // для x на входе
        x[1] = pairs[j, 0];     
        // ожидаемый y на выходе
        double d = pairs[j, 1];
        // сумматор
        double y = x[0] * w[0] + x[1] * w[1];
        // вычисляем ошибку
        double e = d - y;
        // отклонение весов 
        double dW0 = e * n * x[0];
        double dW1 = e * n * x[1];
        // кооректируем весы 
        w[0] = w[0] + dW0;
        w[1] = w[1] + dW1;
    }
}

Console.WriteLine("w0 = {0}, w1 = {1}", 
    w1[0], w1[1]);
Console.WriteLine("m = {0}, c = {1}, |m - c| = {2}", 
    w[1], w[0], Math.Abs(w[1] - w[0]));
// m = 0.993801..., c = 1.03101...

В результате после выполнения выше приведенного кода, мы получим значения m и c, в следствии чего сможем построить уравнение прямой. 

Проект для Visual Studio 2010 Premium вы можете скачать отсюда. Спасибо, за внимание! Если у вас возникли вопросы, то задавайте. Либо если вы заметили ошибку, то сообщите мне об этом. Я мог здесь ошибиться, ибо я новичок в искусственных нейронных сетях.