以倒傳遞類神經網路來解決傳統的 XOR 問題。本套程式共包括鏈結值資料庫、學習程式、回憶程式三部份 --
- 加權值資料庫 :儲存各類已計算出的加權值 (Weight) 資料。
- 學習程式 (for Learning Phase) :此程式會依輸入數值及預期結果,計算出該類資料的各種鏈結值,並儲存於上述資料庫中;下次學習或回憶功能時便可使用。
- 回憶程式 (for Retrieving Phase) :依照資料庫中存在的鏈結值,推算出欲查詢的資料。
加權值資料庫 (Weight Database)
if object_id('TEST') is null
create database TEST
go
use TEST
go
if object_id('Weight_Input_Hidden') is not null
drop table Weight_Input_Hidden
if object_id('Weight_Hidden_Output') is not null
drop table weight_hidden_output
create table Weight_Input_Hidden (
IH_Group_ID int,
IH_No int,
I_No int,
H_No int,
Weight_Value float
constraint PK_Weight_Input_Hidden primary key (IH_Group_ID, IH_No)
)
create table Weight_Hidden_Output (
HO_Group_ID int,
HO_No int,
H_No int,
O_No int,
Weight_Value float
constraint PK_Weight_Hidden_Output primary key (HO_Group_ID, HO_No)
)
go
學習程式 (Learning Phase)
於 TEST 資料庫中 Compile 以下程式碼,再依程式碼第 20 ~ 23 行的說明執行四次學習程序。
Create Proc usp_BPN_Learning @prm_input_item_1 int,
@prm_input_item_2 int,
@prm_expecting_value int,
@prm_eta float
/*-----------------------------------------------------------------------------------+
| Author: Wei-jie Yang |
| Date: 2012/06/19 |
| All Rights Reserved |
| |
| [Description] |
| Backpropagation training program for XOR problem |
| |
| [Parameters] |
| - @prm_input_item_1 Training Value No.1 |
| - @prm_input_item_2 Training Value No.2 |
| - @prm_expecting_value Training Target Value |
| - @prm_eta: Learning Rate |
| |
| [Usage] |
| (1). exec usp_BPN_Learning 1, 1, 1, 0.5 |
| (2). exec usp_BPN_Learning 0, 0, 1, 0.5 |
| (3). exec usp_BPN_Learning 1, 0, 0, 0.5 |
| (4). exec usp_BPN_Learning 0, 1, 0, 0.5 |
+-----------------------------------------------------------------------------------*/
as
declare @current_ho_weight numeric(38, 2),
@current_ih_weight numeric(38, 2),
@delta_1 float,
@delta_2 float,
@delta_3 float,
@exec_counter int,
@exit_main_procedure char(1),
@group_id varchar(10),
@h int,
@hidden_item_amount int,
@hidden_value float,
@ho_weight_1 float,
@ho_weight_2 float,
@ho_weight_matched char(1),
@i int,
@i_value float,
@ih_weight_matched char(1),
@input_item_amount int,
@o int,
@ones int,
@output_item_amount int,
@output_value float,
@pre_ho_weight numeric(38, 2),
@pre_ih_weight numeric(38, 2),
@record_counter int,
@stop_value float,
@temp_hidden_value float,
@temp_output_value float,
@total_exec_times int,
@Y1 float,
@Y2 float,
@zeros int
declare @input_layer table (
i_no int,
i_name varchar(20),
i_value float
)
declare @hidden_layer table (
h_no int,
h_name varchar(20),
h_value float
)
declare @weight_input_hidden table ( -- Weights between Input & Hidden Layers
ih_group_id int,
ih_no int,
i_no int,
h_no int,
weight_value float
)
declare @temp_weight_input_hidden table (
ih_group_id int,
ih_no int,
i_no int,
h_no int,
weight_value float
)
declare @weight_hidden_output table ( -- Weights between Hidden & Output Layers
ho_group_id int,
ho_no int,
h_no int,
o_no int,
weight_value float
)
declare @temp_weight_hidden_output table (
ho_group_id int,
ho_no int,
h_no int,
o_no int,
weight_value float
)
set nocount on
-- Initialization (begin) =============================================================================================
select @input_item_amount = 2
select @hidden_item_amount = 2
select @output_item_amount = 1
select @total_exec_times = 100
if @prm_input_item_1 = @prm_input_item_2
select @group_id = 1
else
select @group_id = 0
-- Get Weights (between Input & Hidden Layers) ----------------------------------------------------
select @record_counter = count(*)
from Weight_Input_Hidden
where IH_Group_ID = @group_id
if @record_counter > 0
begin
insert into @weight_input_hidden (ih_group_id, ih_no, i_no, h_no, weight_value)
select IH_Group_ID, IH_No, I_No, H_No, Weight_Value
from TEST.dbo.Weight_Input_Hidden
where IH_Group_ID = @group_id
end
else
begin
select @i = 1
while @i <= @input_item_amount
begin
select @h = 1
while @h <= @hidden_item_amount
begin
insert into @weight_input_hidden (ih_group_id, ih_no, i_no, h_no, weight_value)
values(@group_id, @i * 100 + @h, @i, @h, round(rand(), 2))
select @h = @h + 1
end
select @i = @i + 1
end
end
-- Get Weights (between Hidden & Output Layers) ---------------------------------------------------
select @record_counter = count(*)
from Weight_Hidden_Output
where HO_Group_ID = @group_id
if @record_counter > 0
begin
insert into @weight_hidden_output (ho_group_id, ho_no, h_no, o_no, weight_value)
select HO_Group_ID, HO_No, H_No, O_No, Weight_Value
from TEST.dbo.Weight_Hidden_Output
where HO_Group_ID = @group_id
end
else
begin
select @o = 1
while @o <= @output_item_amount
begin
select @h = 1
while @h <= @hidden_item_amount
begin
insert into @weight_hidden_output (ho_group_id, ho_no, h_no, o_no, weight_value)
values(@group_id, @h * 100 + @o, @h, @o, round(rand(), 2))
select @h = @h + 1
end
select @o = @o + 1
end
end
-- Initialization (end) ===============================================================================================
-- Generate Input Items (begin) =======================================================================================
insert into @input_layer (i_no, i_name, i_value) values(1, 'X1', @prm_input_item_1)
insert into @input_layer (i_no, i_name, i_value) values(2, 'X2', @prm_input_item_2)
-- Generate Input Items (end) =========================================================================================
-- Main Procedure (begin) =============================================================================================
select @exec_counter = 1
select @output_value = 99
select @exit_main_procedure = 'N'
WHILE (@exec_counter <= @total_exec_times) and (@exit_main_procedure = 'N')
BEGIN
select @ih_weight_matched = 'N'
select @ho_weight_matched = 'N'
-- Generate Hidden Items (begin) ---------------------------------------------------------------
delete from @hidden_layer
where 1 = 1
select @h = 1
while @h <= @hidden_item_amount
begin
select @temp_hidden_value = sum(i.i_value * w.weight_value)
from @weight_input_hidden w,
@input_layer i
where w.i_no = i.i_no
select @hidden_value = 1 / (1 + exp((-1) * @temp_hidden_value))
delete from @hidden_layer
where h_no = @h
insert into @hidden_layer (h_no, h_name, h_value)
values (@h, 'Y' + cast(@h as varchar(10)), @hidden_value)
select @h = @h + 1
end
-- Generate Hidden Items (end) -----------------------------------------------------------------
-- Generate Output Item (begin) ----------------------------------------------------------------
select @temp_output_value = sum(h_value * w.weight_value)
from @weight_hidden_output w,
@hidden_layer h
where w.h_no = h.h_no
select @output_value = 1 / (1 + exp((-1) * @temp_output_value))
-- Generate Output Item (end) ------------------------------------------------------------------
-- Delta Calculation (begin) -------------------------------------------------------------------
select @delta_3 = (@prm_expecting_value - @output_value) * @output_value * (1 - @output_value)
select @Y1 = h_value
from @hidden_layer
where h_no = 1
select @Y2 = h_value
from @hidden_layer
where h_no = 2
select @ho_weight_1 = weight_value
from @weight_hidden_output
where h_no = 1
select @ho_weight_2 = weight_value
from @weight_hidden_output
where h_no = 2
select @delta_1 = @Y1 * (1 - @Y1) * @delta_3 * @ho_weight_1
select @delta_2 = @Y2 * (1 - @Y2) * @delta_3 * @ho_weight_2
-- Delta Calculation (end) ---------------------------------------------------------------------
-- Adjustment (begin) --------------------------------------------------------------------------
-- Input - Hidden Weights ........................................
delete from @temp_weight_input_hidden
where ih_group_id = @group_id
insert into @temp_weight_input_hidden (ih_group_id, ih_no, i_no, h_no, weight_value)
select w.ih_group_id, w.ih_no, w.i_no, w.h_no, w.weight_value + @prm_eta * @delta_1 * i.i_value
from @input_layer i,
@weight_input_hidden w
where i.i_no = w.i_no
and w.h_no = 1
and w.ih_group_id = @group_id
insert into @temp_weight_input_hidden (ih_group_id, ih_no, i_no, h_no, weight_value)
select w.ih_group_id, w.ih_no, w.i_no, w.h_no, w.weight_value + @prm_eta * @delta_2 * i.i_value
from @input_layer i,
@weight_input_hidden w
where i.i_no = w.i_no
and w.h_no = 2
and w.ih_group_id = @group_id
select @pre_ih_weight = weight_value
from @weight_input_hidden
where ih_group_id = @group_id
delete from @weight_input_hidden
where ih_group_id = @group_id
insert into @weight_input_hidden (ih_group_id, ih_no, i_no, h_no, weight_value)
select ih_group_id, ih_no, i_no, h_no, weight_value
from @temp_weight_input_hidden
where ih_group_id = @group_id
order by ih_no
select @current_ih_weight = weight_value
from @weight_input_hidden
where ih_group_id = @group_id
if @pre_ih_weight = @current_ih_weight
select @ih_weight_matched = 'Y'
-- Hidden - Output Weights .......................................
delete from @temp_weight_hidden_output
where ho_group_id = @group_id
insert into @temp_weight_hidden_output (ho_group_id, ho_no, h_no, o_no, weight_value)
select w.ho_group_id, w.ho_no, w.h_no, w.o_no, w.weight_value + @prm_eta * @delta_3 * h.h_value
from @hidden_layer h,
@weight_hidden_output w
where h.h_no = w.h_no
and ho_group_id = @group_id
select @pre_ho_weight = weight_value
from @weight_hidden_output
where ho_group_id = @group_id
delete from @weight_hidden_output
where ho_group_id = @group_id
insert into @weight_hidden_output (ho_group_id, ho_no, h_no, o_no, weight_value)
select ho_group_id, ho_no, h_no, o_no, weight_value
from @temp_weight_hidden_output
where ho_group_id = @group_id
order by ho_no
select @current_ho_weight = weight_value
from @weight_hidden_output
where ho_group_id = @group_id
if @pre_ho_weight = @current_ho_weight
select @ho_weight_matched = 'Y'
-- Adjustment (end) ----------------------------------------------------------------------------
if (@ih_weight_matched = 'Y') and (@ho_weight_matched = 'Y')
select @exit_main_procedure = 'Y'
select @exec_counter = @exec_counter + 1
END
-- Main Procedure (end) ===============================================================================================
-- Save Result (begin) ================================================================================================
delete from TEST.dbo.Weight_Input_Hidden
where IH_Group_ID = @group_id
insert into TEST.dbo.Weight_Input_Hidden (IH_Group_ID, IH_No, I_No, H_No, Weight_Value)
select ih_group_id, ih_no, i_no, h_no, weight_value
from @weight_input_hidden
where ih_group_id = @group_id
delete from TEST.dbo.Weight_Hidden_Output
where HO_Group_ID = @group_id
insert into TEST.dbo.Weight_Hidden_Output (HO_Group_ID, HO_No, H_No, O_No, Weight_Value)
select ho_group_id, ho_no, h_no, o_no, weight_value
from @weight_hidden_output
where ho_group_id = @group_id
-- Save Result (end) ==================================================================================================
set nocount off
return
回憶程式 (Retrieving Phase)
於 TEST 資料庫中 Compile 以下程式碼,再依程式碼第 18 ~ 20 行的說明執行回憶程序。
Create Proc usp_BPN_Retrieving @prm_input_item_1 int,
@prm_input_item_2 int,
@rtn_result int output
/*---------------------------------------------------------------+
| Author: Wei-jie Yang |
| Date: 2012/06/19 |
| All Rights Reserved |
| |
| [Description] |
| Backpropagation training program for XOR problem |
| |
| [Parameters] |
| - @prm_input_item_1: Input Value No.1 |
| - @prm_input_item_2: Input Value No.2 |
| - @rtn_result: Result |
| |
| [Usage] |
| declare @result int |
| exec usp_BPN_Retrieving 1, 1, @result output |
| select @result |
+---------------------------------------------------------------*/
as
declare @group_id varchar(10),
@h int,
@hidden_item_amount int,
@hidden_value float,
@i int,
@input_item_amount int,
@o int,
@output_item_amount int,
@output_value float,
@record_counter int,
@temp_hidden_value float,
@temp_output_value float
declare @input_layer table (
i_no int,
i_name varchar(20),
i_value float
)
declare @hidden_layer table (
h_no int,
h_name varchar(20),
h_value float
)
declare @weight_input_hidden table ( -- Weights between Input & Hidden Items
ih_group_id int,
ih_no int,
i_no int,
h_no int,
weight_value float
)
declare @temp_weight_input_hidden table (
ih_group_id int,
ih_no int,
i_no int,
h_no int,
weight_value float
)
declare @weight_hidden_output table ( -- Weights between Hidden & Output Items
ho_group_id int,
ho_no int,
h_no int,
o_no int,
weight_value float
)
declare @temp_weight_hidden_output table (
ho_group_id int,
ho_no int,
h_no int,
o_no int,
weight_value float
)
set nocount on
-- Initialization (begin) =============================================================================================
select @input_item_amount = 3
select @hidden_item_amount = 3
select @output_item_amount = 1
if @prm_input_item_1 = @prm_input_item_2
select @group_id = 1
else
select @group_id = 0
-- Get Weights (between Input & Hidden Layers) ----------------------------------------------------
select @record_counter = count(*)
from Weight_Input_Hidden
where IH_Group_ID = @group_id
if @record_counter > 0
begin
insert into @weight_input_hidden (ih_group_id, ih_no, i_no, h_no, weight_value)
select IH_Group_ID, IH_No, I_No, H_No, Weight_Value
from TEST.dbo.Weight_Input_Hidden
where IH_Group_ID = @group_id
end
else
begin
select @i = 0
while @i <= @input_item_amount - 1
begin
select @h = 1
while @h <= @hidden_item_amount - 1
begin
insert into @weight_input_hidden (ih_group_id, ih_no, i_no, h_no, weight_value)
values(@group_id, @i * 100 + @h, @i, @h, round(rand(), 2))
select @h = @h + 1
end
select @i = @i + 1
end
end
-- Get Weights (between Hidden & Output Layers) ---------------------------------------------------
select @record_counter = count(*)
from Weight_Hidden_Output
where HO_Group_ID = @group_id
if @record_counter > 0
begin
insert into @weight_hidden_output (ho_group_id, ho_no, h_no, o_no, weight_value)
select HO_Group_ID, HO_No, H_No, O_No, Weight_Value
from TEST.dbo.Weight_Hidden_Output
where HO_Group_ID = @group_id
end
else
begin
select @o = 1
while @o <= @output_item_amount
begin
select @h = 0
while @h <= @hidden_item_amount - 1
begin
insert into @weight_hidden_output (ho_group_id, ho_no, h_no, o_no, weight_value)
values(@group_id, @h * 100 + @o, @h, @o, round(rand(), 2))
select @h = @h + 1
end
select @o = @o + 1
end
end
-- Initialization (end) ===============================================================================================
-- Generate Input Items (begin) =======================================================================================
insert into @input_layer (i_no, i_name, i_value) values(0, 'X0', -1)
insert into @input_layer (i_no, i_name, i_value) values(1, 'X1', @prm_input_item_1)
insert into @input_layer (i_no, i_name, i_value) values(2, 'X2', @prm_input_item_2)
-- Generate Input Items (end) =========================================================================================
-- Main Procedure (begin) =============================================================================================
select @output_value = 99
-- Generate Hidden Items (begin) ---------------------------------------------------------------
delete from @hidden_layer
where 1 = 1
insert into @hidden_layer (h_no, h_name, h_value)
values(0, 'X0', -1)
select @h = 1
while @h <= @hidden_item_amount - 1
begin
select @temp_hidden_value = sum(i.i_value * w.weight_value)
from @weight_input_hidden w,
@input_layer i
where w.i_no = i.i_no
select @hidden_value = 1 / (1 + exp((-1) * @temp_hidden_value))
delete from @hidden_layer
where h_no = @h
insert into @hidden_layer (h_no, h_name, h_value)
values (@h, 'Y' + cast(@h as varchar(10)), @hidden_value)
select @h = @h + 1
end
-- Generate Hidden Items (end) -----------------------------------------------------------------
-- Generate Output Item (begin) ----------------------------------------------------------------
select @temp_output_value = sum(h_value * w.weight_value)
from @weight_hidden_output w,
@hidden_layer h
where w.h_no = h.h_no
select @output_value = 1 / (1 + exp((-1) * @temp_output_value))
-- Generate Output Item (end) ------------------------------------------------------------------
if @output_value < 0.5
select @output_value = 0
else
select @output_value = 1
select @rtn_result = @output_value
set nocount off
return