《情書》(Love letter),韓國SBS電視臺綜藝節目,被譽為“韓國的流行制造機”、綜藝節目中的“大長今”,由搞笑才能一流的韓國著名主持人姜虎東擔綱主持。該節目于2004年~2006年間, 每周六17:40在韓國SBS電視臺播出,200, 以下是為大家整理的關于情書手寫體1篇 , 供大家參考選擇。
情書手寫體1篇
【篇一】情書手寫體
分數: ___________
任課教師簽字:___________
課程作業
學年學期:2017——2018學年第二學期
課程名稱:模式識別
作業名稱:作業七
學生姓名:
學號:
提交時間:
一、問題重述
編寫手寫體識別大作業程序,要求做到以下幾點內容:
(1)針對“002手寫數字數據集(1934+946)”數據包,進行手寫體辨識。要求使用之前作業中用到的各類平均值為類中心的最小距離法、KNN近鄰法(K取1,3,5)等等。
(2)嘗試使用神經網絡方法進行辨識過程。
(3)嘗試70000個樣本的數據集進行辨識,其中60000個用于訓練,10000個用于測試。
二、方法原理
1、特征選擇準則——類別可分性準則
類別可分性準則值可以衡量樣本的可分程度,取值越大表明樣本可分程度越小,可以在一定程度上減小最終的分類錯誤率。
類別可分性準則函數值J的計算公式如下所示
其中C為類別數,m為總樣本均值,mi為某一類均值,X表示樣本數據。
值得注意的是,并非J取值越大,最終的分類錯誤率就一定越小。最終的分類結果還與數據的分布特性以及分類器的選擇有關。因此在J值取值只需滿足條件即可,并非一定要取到最大值。
2、特征提取方法——PCA降維
當樣本數據維數較高時,程序當中涉及到矩陣的運算會有很大負荷,算法的執行效率會大幅降低。因此在訓練之前,需要將樣本數據進行降維處理。
主成分分析法(簡稱PCA)可以減少樣本數據的相關性,突出差異性,是分類、辨識當中常用的降維方法。
PCA可以將高維的數據降到任意低的維度上。但是為了保證樣本數據不失真,一般要求PCA算法降維中,特征值占比不小于所有特征值之和75%。
PCA算法的流程如下圖所示。
圖1 PCA降維算法流程圖
3、分類器
分類器是整個分類環節當中的最后一項,也是分類過程的關鍵所在。分類器分為訓練和測試兩個環節,相應的算法有很多。常用的有基于類均值的最小距離法、KNN近鄰法等基本線性分類算法,以及向量機、神經網絡等更為復雜的算法。
分類結束之后,計算訓練錯誤率和測試錯誤率,以此為標準檢驗分類器算法的優劣以及整個分類過程的好壞。
(1)基于類均值的最小距離法
基于類均值的最小距離法首先計算每類訓練樣本的均值點,再分別計算每個均值點到測試樣本的距離,測試樣本歸屬于距其最近的均值點所在的數據類型。
基于類均值的最小距離法算法流程如下:
圖2基于類均值的最小距離法流程圖
(2)KNN近鄰法
KNN近鄰法源自近鄰法。KNN近鄰法不再單單尋找距測試樣本最近的一個點,而是尋找距其最近的K個點,然后按這K個點類型確定測試樣本的類型。判斷原則往往是少數服從多數。
K的取值一般取技術。特別的當K取1,這種方法就是常見的最近鄰法。
KNN近鄰法算法流程如下:
圖3KNN近鄰法流程圖
(3)BP神經網絡
BP網絡是一類多層的前饋神經網絡。它的名字源于網絡訓練的過程中,調整網絡的權值的算法是誤差的反向傳播的學習算法,即為BP學習算法。BP算法的結構簡單,可調的參數多,訓練的算法也多,而且操作性好。BP網是前向網絡的核心部分算法,是神經網絡中最精華、最完美的部分。
本次作業利用BP神經網絡算法對樣本進行訓練測試,并將結果與其他方法進行對比。
三、處理流程
本次數據處理的數據集為32*32的二值圖,保存格式為文本格式。訓練樣本數為1934,每個數字大約有200個;測試樣本數為926個,每個數字個數從80到120不等。
整個手寫體辨識過程可以分為以下四個階段:
word/media/image5.gif
圖4 手寫體辨識過程
1、數據采集
本次作業所用到的數據為二值化后的文本文檔,所以數據采集過程只需要將文檔中的數據讀取到工作空間即可。
本階段將訓練樣本和測試樣本分別存到兩個元胞數組的變量當中,每個元胞含有10個元胞元素,依次對應0~9;每個元胞元素中存放n*1024的矩陣,其中n代表該類數據的樣本數,1024代表二值化后的點陣數。
2、特征生成
本階段將原始數據進行處理,提取出16個特征元素。特征生成過程如下。
將32*32的二值化矩陣平均分成16塊,求出每塊矩陣當中非零元素的個數,作為相應的特征元素。如,將下圖所示的一組數據(類型為0)提取特征值后為[3 43 25 0 14 30 19 6 5 30 8 22 0 37 40 11]。
word/media/image6.gif
圖5 一組類型為0的原始數據
word/media/image7.gif
圖6 將二值均值分塊過程
3、特征選擇與提取
為了減小計算量需要對樣本進行降維處理。降維方式選擇PCA算法,在保證類別可分性準則值滿足要求的條件下,特征值占比不小于75%即可。設n表示PCA處理后的維度。
表1 1934與70000兩個數據集PCA降維后不同維度下特征值占比和可分性準則
word/media/image8.gif
圖71934樣本集PCA降維后的特征值占比和可分性函數值
word/media/image9.gif
圖870000樣本集PCA降維后的特征值占比和可分性函數值
為了減少計算量,選擇特征值占比大于75%維度最小的情況。因此針對1934數據集,利用PCA將其降成5維;針對70000數據集,也利用PCA降成5維。
4、分類器
將PCA降維后的數據(5維)和不進行PCA降維的數據(16維),分別利用基于類均值的最小距離法訓練、KNN近鄰法(K取1、3、5)、BP神經網絡算法,對樣本進行訓練、測試,得到的錯誤率如下:
表2 分類錯誤率
對分類結果以及之前的工作總結,如下:
(1) 當數據集規模變大時,各種算法的錯誤率會增加;
(2) PCA降維后雖然會減小運算量,但是會增大分類錯誤率;
(3) 幾種方法中,基于類均值的最小距離分類算法的效果相對最差,BP神經網絡的分類效果相對最好。
(4) 對于基于類均值的最小距離法、KNN近鄰法來說,訓練錯誤率一般是略高于測試錯誤率的。
(5) 本作業次設計的分類器對于1934樣本集分類效果比較令人滿意,但是對于70000樣本集分類效果很差,針對大樣本數據,算法需要改進
四、代碼附錄:
1、 數據采集程序:
%手寫體識別:1934訓練樣本+946個測試樣本
%每個txt文件對應32*32的矩陣,轉換為一條行向量。
clear all
close all;
clc;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%保存訓練數據
PathTrain=[cd,"\trainingDigits\"];
TrainList=dir([PathTrain,"*.txt"]);
TrainData_Original=cell(10,1);%保存原始訓練數據
for i=1:length(TrainList)
fid=fopen([PathTrain,TrainList(i).name],"r");
temp_1=textscan(fid,"%s");
fclose(fid);
temp_2=cell2mat(temp_1{1});
temp_3=str2num(reshape(temp_2,[],1))";%存成行向量
label=str2num(TrainList(i).name(1));%該行數據的數據類型
TrainData_Original{label+1}=[TrainData_Original{label+1};temp_3];
end
save("TrainData","TrainData_Original");
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%保存測試數據
PathTest=[cd,"\testDigits\"];
TestList=dir([PathTest,"*.txt"]);
TestData_Original=cell(10,1);%保存原始測試數據
for i=1:length(TestList)
fid=fopen([PathTest,TestList(i).name],"r");
temp_1=textscan(fid,"%s");
fclose(fid);
temp_2=cell2mat(temp_1{1});
temp_3=str2num(reshape(temp_2,[],1))";%存成行向量
label=str2num(TestList(i).name(1));%該行數據的數據類型
TestData_Original{label+1}=[TestData_Original{label+1};temp_3];
end
save("TestData","TestData_Original");
2、 特征生成程序:
clc;
clear all;
close all;
load TrainData;
load TestData;
Feature_x=4;%水平分為四份
Feature_y=4;%垂直分為四份
TestData_Feature=cell(10,1); %存放加工后的測試數據
TrainData_Feature=cell(10,1); %存放加工后的訓練數據
for i=1:length(TestData_Original)
temp_1=TestData_Original{i};
for j=1:size(temp_1,1)
temp_2=reshape(temp_1(j,:),32,32);%1*1024的將行向量重塑為32*32的矩陣
Feature=zeros(1,Feature_x*Feature_y);%存放每個元素的特征值
xy_i=0;
for x_i=0:Feature_x-1
for y_i=0:Feature_y-1
xy_i=xy_i+1; temp_3=temp_2(32*x_i/Feature_x+1:32*(x_i+1)/Feature_x,32*y_i/Feature_y+1:32*(y_i+1)/Feature_y);
Feature(xy_i)=nnz(temp_3);%提取生成特征值
end
end
TestData_Feature{i}=[TestData_Feature{i}; Feature];
end
end
save("TestData_Feature","TestData_Feature");
for i=1:length(TrainData_Original)
temp_1=TrainData_Original{i};
for j=1:size(temp_1,1)
temp_2=reshape(temp_1(j,:),32,32); %1*1024的將行向量重塑為32*32的矩陣
Feature=zeros(1,Feature_x*Feature_y); %存放每個元素的特征值
xy_i=0;
for x_i=0:Feature_x-1
for y_i=0:Feature_y-1
xy_i=xy_i+1; temp_3=temp_2(32*x_i/Feature_x+1:32*(x_i+1)/Feature_x,32*y_i/Feature_y+1:32*(y_i+1)/Feature_y);
Feature(xy_i)=nnz(temp_3);%提取生成特征值
end
end
TrainData_Feature{i}=[TrainData_Feature{i}; Feature];
end
end
save("TrainData_Feature","TrainData_Feature");
3、特征選擇與提取
%3、特征選取與提取
load("TrainData_Feature");
load("TestData_Feature");
PCA_train=cell(16,1);
Degree=zeros(16,1);
for i=1:16
[PCA_train{i},Degree(i)]=PCA_reduction(TrainData_Feature,i)%返回PCA變換矩陣
end
n_PCA=5; %選擇降到5維,特征值占比大于75%
TrainData_PCA=cell(length(TrainData_Feature),1);
for i=1:length(TrainData_Feature)
TrainData_PCA{i}=TrainData_Feature{i}*PCA_train{n_PCA};%訓練樣本降維
end
TestData_PCA=cell(length(TestData_Feature),1);
for i=1:length(TestData_Feature)
TestData_PCA{i}=TestData_Feature{i}*PCA_train{n_PCA};%測試樣本降維
end
J=Category_separability(TrainData_PCA)
Degree_5=Degree(n_PCA)
save("TrainData_PCA","TrainData_PCA","J","Degree_5");
save("TestData_PCA","TestData_PCA");
%計算類別可分性準則函數J值
function J=Category_separability(Data)
ALL_C=length(Data);%類別數
every_dimension=size(Data{1},2);%數據的維度
every_number=zeros(ALL_C,1);%每一類的數量
every_mean=zeros(ALL_C,every_dimension);%每一類的平均值
SW=0;SB=0;all_mean=every_mean(1,:);%計算總平均值
for i=1:ALL_C
every_number(i)=size(Data{i},1);
every_mean(i,:)=mean(Data{i});
all_mean=every_number(i)*every_mean(i,:)+all_mean;
temp_1=pdist2(Data{i},every_mean(i,:));
Si=sum(temp_1.^2);
SW=SW+Si;
end
all_mean=all_mean/sum(every_number(:));
for i=1:ALL_C%計算總平均值
SB=SB+every_number(i)*(all_mean-every_mean(i,:))*(all_mean-every_mean(i,:))";
end
J=SB/SW;
3、 分類器:
%(1)基于類均值的最小距離法
%A是訓練樣本,B是測試樣本,輸出output是錯誤率
function output=Min_distance(A,B)
TrainData=A;
StudyData=B;
%訓練樣本
ALL_C_Train=length(TrainData);%類別數
%學習樣本
ALL_C_Study=length(StudyData);%類別數
every_number_Study=zeros(ALL_C_Study,1);%每一類的數量
Study=[];
for i=1:ALL_C_Study
every_number_Study(i)=size(StudyData{i},1);
Study=[Study;StudyData{i}];%求出所有的數據
end
%求訓練樣本均值
Mean=[];
for i=1:ALL_C_Train
Mean=[Mean;mean(TrainData{i})];
end
%基于類均值的最小距離法
StudyType_all=zeros(size(Study,1),1);%判別結果
StudyType_Standard_all=StudyType_all;
for i=1:size(Study,1)
[~,m]=min(pdist2(Study(i,:),Mean));%求最小距離
StudyType_all(i)=m-1;
end
number=0;
for i=1:ALL_C_Study
StudyType_Standard_all(number+1:number+every_number_Study(i))=ones(every_number_Study(i),1)*(i-1);
number=every_number_Study(i)+number;
end
output=Error_rate(StudyType_all,StudyType_Standard_all);
%(2)kNN近鄰法,k取1、3、5...
function output=NearestNeighbor_kNN(A,B,k)
TrainData=A;StudyData=B;Train=[];Study=[];%A是訓練樣本, B是測試樣本
ALL_C_Train=length(TrainData);%類別數-------------------------訓練樣本
every_number_Train=zeros(ALL_C_Train,1);%每一類的數量
for i=1:ALL_C_Train
every_number_Train(i)=size(TrainData{i},1);
Train=[Train;TrainData{i}];%求出所有的數據
end
ALL_C_Study=length(StudyData);%類別--------------------------數學習樣本
every_number_Study=zeros(ALL_C_Study,1);%每一類的數量
for i=1:ALL_C_Study
every_number_Study(i)=size(StudyData{i},1);
Study=[Study;StudyData{i}];%求出所有的數據
end
StudyType_all=zeros(size(Study,1),1);%判別結果
mink_point=zeros(size(Study,1),k);%距測試樣本最近的k個點所在矩陣的行號
label=zeros(1,k);%距測試樣本最近的k個點的類型
for i=1:size(Study,1)%每一個樣本----------------------------kNN近鄰法
S_distance=pdist2(Study(i,:),Train);
[~,m]=sort(S_distance,"ascend");mink_point(i,:)=m(1:k);
for j=1:k %每個最近點所在的標簽
number=0;
for ii=1:ALL_C_Train
ifmink_point(i,j)>=number+1&&mink_point(i,j)50 %出現次數最多的值的頻率,%
StudyType_all(i)=countW(value,1);
end
end
StudyType_Standard_all=StudyType_all;number=0;%標準值
for i=1:ALL_C_Study
StudyType_Standard_all(number+1:number+every_number_Study(i))=ones(every_number_Study(i),1)*(i-1);
number=every_number_Study(i)+number;
end
output=Error_rate(StudyType_all,StudyType_Standard_all); %測試樣本的錯誤率
(3)BP神經網絡算法
%BP神經網絡
%function error=BP_Networks(A,B)
load TestData_PCA;
load TrainData_PCA;
A=TrainData_PCA;
B=TestData_PCA;%測試錯誤率
TrainData=A;
StudyData=B;
%訓練樣本
ALL_C_Train=length(TrainData);%類別數
every_number_Train=zeros(ALL_C_Train,1);%每一類的數量
Train=[];
TrainType_Standard=[];
for i=1:ALL_C_Train
every_number_Train(i)=size(TrainData{i},1);
TrainType_Standard=[TrainType_Standard;ones(every_number_Train(i),1)*(i)];%訓練樣本類型
Train=[Train;TrainData{i}];%求出所有的數據
end
%學習樣本
StudyType_Standard_all=[];
Study=[];
ALL_C_Study=length(StudyData);%類別數
every_number_Study=zeros(ALL_C_Study,1);%每一類的數量
Study=[];
for i=1:ALL_C_Study
every_number_Study(i)=size(StudyData{i},1);
StudyType_Standard_all=[StudyType_Standard_all;ones(every_number_Study(i),1)*(i)];
Study=[Study;StudyData{i}];%求出所有的數據
end
%特征值歸一化
[input,minI,maxI] = premnmx( Train") ;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%創建神經網絡
net = newff( minmax(input) , [30 10] , { "tansig" "logsig" } , "traingdx" ) ;
%{minmax(input):獲取4個輸入信號(存儲在f1 f2 f3 f4中)的最大值和最小值;
[10,3]:表示使用2層網絡,第一層網絡節點數為10,第二層網絡節點數為3;
{ "logsig" "purelin" }:
表示每一層相應神經元的激活函數;tansig
即:第一層神經元的激活函數為logsig(線性函數),第二層為purelin(對數S形轉移函數)
"traingdx":表示學習規則采用的學習方法為traingdx(梯度下降自適應學習率訓練函數)%}
%設置訓練參數
net.trainparam.show = 10 ;% 顯示中間結果的周期
net.trainparam.epochs = 1000 ;%最大迭代次數(學習次數)
net.trainparam.goal = 0 ;%神經網絡訓練的目標誤差
net.trainParam.lr = 0.01 ;%學習速率(Learning rate)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%開始訓練
%其中input為訓練集的輸入信號,對應output為訓練集的輸出結果
%構造輸出矩陣
s = length( TrainType_Standard) ;
output = zeros( s ,ALL_C_Train ) ;
for i = 1 : s
output( i , TrainType_Standard( i ) ) = 1 ;
end
net = train(net,input,output");
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%開始測試
% 測試數據歸一化
testInput = tramnmx ( Study" , minI, maxI ) ;
% 仿真 其中net為訓練后得到的網絡,返回Y
Y=sim(net,testInput);
% 統計識別正確率
[s1,s2] = size(Y) ;
hitNum = 0 ;
for i = 1 : s2
[m,Index] = max(Y(:,i)) ;
if( Index==StudyType_Standard_all(i))
hitNum = hitNum + 1 ;
end
end
error=1- hitNum / s2 ;%錯誤率
sprintf("識別率是 %3.3f%%",100 * hitNum / s2 )%正確率




