?? bp.h
字號:
b=(*lpSrc==255)?0:1;
tz[m]+=b;
}
}
//提取第9個特征-總象素值
for(i=0;i<lHeight;i++)
for(j=k*width;j<(k+1)*width;j++)
{ lpSrc=(unsigned char*)lpDIBBits + lLineBytes * i + j;
b=(*lpSrc==255)?0:1;
tz[8]+=b;
}
//提取第10、11個特征-水平掃描切割
i=int(lHeight*1/3);
for(j=k*width;j<(k+1)*width;j++)
{ lpSrc=(unsigned char*)lpDIBBits + lLineBytes * i + j;
b=(*lpSrc==255)?0:1;
tz[9]+=b;
}
//
i=int(lHeight*2/3);
for(j=k*width;j<(k+1)*width;j++)
{ lpSrc=(unsigned char*)lpDIBBits + lLineBytes * i + j;
b=(*lpSrc==255)?0:1;
tz[10]+=b;
}
//提取第12、13個特征-垂直掃描切割
j=int(k*width+width*1/3);
for(i=0;i<lHeight;i++)
{ lpSrc=(unsigned char*)lpDIBBits + lLineBytes * i + j;
b=(*lpSrc==255)?0:1;
tz[11]+=b;
}
j=int(k*width+width*2/3);
for(i=0;i<lHeight;i++)
{ lpSrc=(unsigned char*)lpDIBBits + lLineBytes * i + j;
b=(*lpSrc==255)?0:1;
tz[12]+=b;
}
//存儲特征
for(i=0;i<dim;i++)
tezheng[k][i]=tz[i];
}
::GlobalUnlock ((HGLOBAL)hDIB);
//返回特征向量矩陣的指針
return tezheng;
}
/**********************************
* 函數名稱 code()
*
* 參量:
* BYTE* lpDIBBits -指向輸入圖像的象素其實位置的指針
* int num -圖片中樣本的個數
* LONG lLineByte -輸入圖片每行的字節數
* LONG lSwidth -預處理時歸一化的寬度
* LONG lSheight -預處理時歸一化的長度
*
* 函數功能 :
* 對于輸入樣本提取特征向量,在這里把歸一化樣本的
* 每一個象素都作為特征提取出來
**************************************/
double** code (BYTE* lpDIBBits,int num, LONG lLineByte,LONG lSwidth,LONG lSheight)
{
//循環變量
int i,j,k;
BYTE* lpSrc;
// 建立保存特征向量的二維數組
double **data;
// 為這個數組申請二維存儲空間
data = alloc_2d_dbl(num,lSwidth*lSheight);
// 將歸一化的樣本的每個象素作為一個特征點提取出來
//逐個數據掃描
for(k=0;k<num;k++)
{
//對每個數據逐行掃描
for(i=0;i<lSheight;i++)
{
//對每個數據逐列掃描
for(j=k*lSwidth;j<(k+1)*lSwidth;j++)
{
// 指向圖像第i行第j列個象素的指針
lpSrc = lpDIBBits + i*lLineByte + j;
//如果這個象素是黑色的
if(*(lpSrc)==0)
//將特征向量的相應位置填1
data[k][i*lSwidth+j-k*lSwidth]=1;
//如果這個象素是其他的
if(*(lpSrc)!=0)
//將特征向量的相應位置填0
data[k][i*lSwidth+j-k*lSwidth]=0;
}
}
}
return(data);
}
/****************************************************
* 函數名稱 BpTrain()
*
* 參數:
* double **data_in -指向輸入的特征向量數組的指針
* double **data_out -指向理想輸出數組的指針
int n_in -輸入層結點的個數
* int n_hidden -BP網絡隱層結點的數目
* double min_ex -訓練時允許的最大均方誤差
* double momentum -BP網絡的相關系數
* double eta -BP網絡的訓練步長
* int num -輸入樣本的個數
*
* 函數功能:
* 根據輸入的特征向量和期望的理想輸出對BP網絡盡行訓練
* 訓練結束后將權值保存并將訓練的結果顯示出來
********************************************************/
void BpTrain(double ** data_in, double** data_out,int n_in,int n_hidden,double min_ex,double momentum,double eta ,int num)
{
//循環變量
int i,k,l;
//輸出層結點數目
int n_out=4;
//指向輸入層數據的指針
double* input_unites;
//指向隱層數據的指針
double* hidden_unites;
//指向輸出層數據的指針
double* output_unites;
//指向隱層誤差數據的指針
double* hidden_deltas;
//指向輸出層誤差數劇的指針
double* output_deltas;
//指向理想目標輸出的指針
double* target;
//指向輸入層于隱層之間權值的指針
double** input_weights;
//指向隱層與輸出層之間的權值的指針
double** hidden_weights;
//指向上一此輸入層于隱層之間權值的指針
double** input_prev_weights ;
//指向上一此隱層與輸出層之間的權值的指針
double** hidden_prev_weights;
//每次循環后的均方誤差誤差值
double ex;
//為各個數據結構申請內存空間
input_unites= alloc_1d_dbl(n_in + 1);
hidden_unites=alloc_1d_dbl(n_hidden + 1);
output_unites=alloc_1d_dbl(n_out + 1);
hidden_deltas = alloc_1d_dbl(n_hidden + 1);
output_deltas = alloc_1d_dbl(n_out + 1);
target = alloc_1d_dbl(n_out + 1);
input_weights=alloc_2d_dbl(n_in + 1, n_hidden + 1);
input_prev_weights = alloc_2d_dbl(n_in + 1, n_hidden + 1);
hidden_prev_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1);
hidden_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1);
//為產生隨機序列撒種
time_t t;
bpnn_initialize((unsigned)time(&t));
//對各種權值進行初始化初始化
bpnn_randomize_weights( input_weights,n_in,n_hidden);
bpnn_randomize_weights( hidden_weights,n_hidden,n_out);
bpnn_zero_weights(input_prev_weights, n_in,n_hidden );
bpnn_zero_weights(hidden_prev_weights,n_hidden,n_out );
//開始進行BP網絡訓練
//這里設定最大的迭代次數為15000次
for(l=0;l<15000;l++)
{
//對均方誤差置零
ex=0;
//對樣本進行逐個的掃描
for(k=0;k<num;k++)
{
//將提取的樣本的特征向量輸送到輸入層上
for(i=1;i<=n_in;i++)
input_unites[i] = data_in[k][i-1];
//將預定的理想輸出輸送到BP網絡的理想輸出單元
for(i=1;i<=n_out;i++)
target[i]=data_out[k][i-1];
//前向傳輸激活
//將數據由輸入層傳到隱層
bpnn_layerforward(input_unites,hidden_unites,
input_weights, n_in,n_hidden);
//將隱層的輸出傳到輸出層
bpnn_layerforward(hidden_unites, output_unites,
hidden_weights,n_hidden,n_out);
//誤差計算
//將輸出層的輸出與理想輸出比較計算輸出層每個結點上的誤差
bpnn_output_error(output_deltas,target,output_unites,n_out);
//根據輸出層結點上的誤差計算隱層每個節點上的誤差
bpnn_hidden_error(hidden_deltas,n_hidden, output_deltas, n_out,hidden_weights, hidden_unites);
//權值調整
//根據輸出層每個節點上的誤差來調整隱層與輸出層之間的權值
bpnn_adjust_weights(output_deltas,n_out, hidden_unites,n_hidden,
hidden_weights, hidden_prev_weights, eta, momentum);
//根據隱層每個節點上的誤差來調整隱層與輸入層之間的權值
bpnn_adjust_weights(hidden_deltas, n_hidden, input_unites, n_in,
input_weights, input_prev_weights, eta, momentum);
//誤差統計
for(i=1;i<=n_out;i++)
ex+=(output_unites[i]-data_out[k][i-1])*(output_unites[i]-data_out[k][i-1]);
}
//計算均方誤差
ex=ex/double(num*n_out);
//如果均方誤差已經足夠的小,跳出循環,訓練完畢
if(ex<min_ex)break;
}
//相關保存
//保存輸入層與隱層之間的權值
w_weight(input_weights,n_in,n_hidden,"win.dat");
//保存隱層與輸出層之間的權值
w_weight(hidden_weights,n_hidden,n_out,"whi.dat");
//保存各層結點的個數
w_num(n_in,n_hidden,n_out,"num");
//顯示訓練結果
CString str;
if(ex<=min_ex)
{
str.Format ("迭代%d次,\n平均誤差%.4f",l,ex);
::MessageBox(NULL,str,"訓練結果",NULL);
}
if(ex>min_ex)
{
str.Format("迭代%d次,平均誤差%.4f\n我已經盡了最大努力了還是達不到您的要求\n請調整參數重新訓練吧!",l,ex);
::MessageBox(NULL,str,"訓練結果",NULL);
}
//釋放內存空間
free(input_unites);
free(hidden_unites);
free(output_unites);
free(hidden_deltas);
free(output_deltas);
free(target);
free(input_weights);
free(hidden_weights);
free(input_prev_weights);
free(hidden_prev_weights);
}
/*******************************************
* 函數名稱
* CodeRecognize()
* 參量
* double **data_in -指向待識別樣本特征向量的指針
* int num -待識別的樣本的個數
* int n_in -Bp網絡輸入層結點的個數
* int n_hidden -Bp網絡隱層結點的個數
* int n_out -Bp網絡輸出層結點的個數
* 函數功能:
* 讀入輸入樣本的特征相量并根據訓練所得的權值
* 進行識別,將識別的結果寫入result.txt
****************************************/
void CodeRecognize(double **data_in, int num ,int n_in,int n_hidden,int n_out)
{
//循環變量
int i,k;
// 指向識別結果的指針
int *recognize;
//為存放識別的結果申請存儲空間
recognize=(int*)malloc(num*sizeof(int));
//指向輸入層數據的指針
double* input_unites;
//指向隱層數據的指針
double* hidden_unites;
//指向輸出層數據的指針
double* output_unites;
//指向輸入層于隱層之間權值的指針
double** input_weights;
//指向隱層與輸出層之間的權值的指針
double** hidden_weights;
//為各個數據結構申請內存空間
input_unites= alloc_1d_dbl(n_in + 1);
hidden_unites=alloc_1d_dbl(n_hidden + 1);
output_unites=alloc_1d_dbl(n_out + 1);
input_weights=alloc_2d_dbl(n_in + 1, n_hidden + 1);
hidden_weights = alloc_2d_dbl(n_hidden + 1, n_out + 1);
//讀取權值
if( r_weight(input_weights,n_in,n_hidden,"win.dat")==false)
return;
if(r_weight(hidden_weights,n_hidden,n_out,"whi.dat")==false)
return;
//逐個樣本掃描
for(k=0;k<num;k++)
{
//將提取的樣本的特征向量輸送到輸入層上
for(i=1;i<=n_in;i++)
input_unites[i]=data_in[k][i-1];
//前向輸入激活
bpnn_layerforward(input_unites,hidden_unites,
input_weights, n_in,n_hidden);
bpnn_layerforward(hidden_unites, output_unites,
hidden_weights,n_hidden,n_out);
//根據輸出結果進行識別
int result=0 ;
//考察每一位的輸出
for(i=1;i<=n_out;i++)
{
//如果大于0.5判為1
if(output_unites[i]>0.5)
result+=(int)pow(2,double(4-i));
}
//如果判定的結果小于等于9,認為合理
if(result<=9)
recognize[k]=result;
//如果判定的結果大于9,認為不合理將結果定位為一個特殊值20
if(result>9)
recognize[k]=20;
}
//將識別結果寫到文本中
FILE *fp;
fp=fopen("result.txt","w+");
for(i=0;i<num;i++)
{
if(recognize[i]==20)
fprintf(fp,"無法識別,");
else
fprintf(fp,"%d,",recognize[i]);
}
fclose(fp);
//將識別的結果顯示出來
CString str,str1;
for(i=0;i<num;i++)
{
if(recognize[i]!=20)
str.Format("%d ",recognize[i]);
if(recognize[i]==20)
str.Format("無法識別 ");
str1+=str;
}
//通知用戶訓練完成
::MessageBox(NULL,str1,"識別結果",NULL);
//釋放存儲空間
free(input_unites);
free(hidden_unites);
free(output_unites);
free(input_weights);
free(hidden_weights);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -