本文的目的是在一個(gè)神經(jīng)網(wǎng)絡(luò)已經(jīng)通過python或者MATLAB訓(xùn)練好的神經(jīng)網(wǎng)絡(luò)模型,將訓(xùn)練好的模型的權(quán)重和偏置文件以TXT文件格式導(dǎo)出,然后通過python程序?qū)xt文件轉(zhuǎn)化為coe文件,(coe文件是為了將其寫入rom,網(wǎng)絡(luò)中的權(quán)重和偏置通過讀取ROM即可,后續(xù)需要修改輸入其他特征值,只需要修改input的rom里面的coe文件即可)。
設(shè)計(jì)思想
其中sigmoid函數(shù)是本次實(shí)驗(yàn)最大的難點(diǎn),因?yàn)閟igmoid函數(shù)的值是在0-1之間的小數(shù),其值越大,說明該模型的輸出是該結(jié)果的幾率越大。但是verilog硬件描述語言,其計(jì)算結(jié)果只有0或1兩種情況,所以要想直接通過verilog語言計(jì)算出sigmoid函數(shù)的值是比較復(fù)雜的,本次使用的方法為查找表法,通過外部其他語言計(jì)算出sigmoid函數(shù)的值,然后將其放入查找表,后續(xù)當(dāng)需要使用sigmoid函數(shù)時(shí),直接輸出結(jié)果。但是這個(gè)需要不斷地往里面加值,每更新一次輸入,那么就往sigmoid模塊里面的查找表添加上該輸入的sigmoid值。
由于FPGA的計(jì)算是基于數(shù)字邏輯和二進(jìn)制運(yùn)算,小數(shù)計(jì)算只能通過 固定點(diǎn)數(shù)(即帶有定點(diǎn)小數(shù)位的整數(shù)表示)來模擬某些浮點(diǎn)數(shù)計(jì)算。這需要使用額外的邏輯來實(shí)現(xiàn)浮點(diǎn)數(shù)的運(yùn)算、舍入和特殊值處理。
但是本文選擇一個(gè)簡便的方法,選擇將輸入,權(quán)重 分別保留兩位小數(shù)(可自己選擇位數(shù),保留越多精度越高,反之精度越低),然后分別將其乘以100,將數(shù)據(jù)全都變成帶符號整數(shù),然后將其進(jìn)行乘加運(yùn)算。將偏置保留4位小數(shù)并乘以10000,得到的結(jié)果除以10000然后進(jìn)行sigmoid計(jì)算,后續(xù)無論添加多少層,都可以以此方法來進(jìn)行計(jì)算。以下為搭建神經(jīng)網(wǎng)絡(luò)的步驟:
step1: 處理數(shù)據(jù),將保存好的權(quán)重文件轉(zhuǎn)化為coe文件,然后添加一個(gè)ROM,并將coe文件加載進(jìn)ROM里面;
module input_rom_ctr(
input sys_clk,//50MHz時(shí)鐘
input rst_n,//復(fù)位,低電平有效
input [5:0] data_deep,
output reg [31:0] rom_data_r, //ROM讀出數(shù)據(jù)
output reg viald,
output reg [6:0] rom_addr_rr //ROM輸入地址
);
reg [6:0] rom_addr;
//產(chǎn)生ROM地址讀取數(shù)據(jù)
always @ (posedge sys_clk or negedge rst_n)
begin
if(!rst_n)begin
rom_addr <= 7'd0;
viald <= 1'b1;
end
else if(rom_addr_rr >= (data_deep -1'd1))begin
viald <= 1'b0;
end
else if(rom_addr >= (data_deep - 1'd1))begin
rom_addr <= 7'd0;
end
else begin
rom_addr <= rom_addr+1'b1;
viald <= viald;
end
end
reg [6:0]rom_addr_r;
always @(posedge sys_clk or negedge rst_n) begin
if(!rst_n)begin
rom_addr_r <= 7'd0;
rom_addr_rr <= 7'd0;
end
else begin
rom_addr_r <= rom_addr;
rom_addr_rr <= rom_addr_r;
end
end
wire [31:0] rom_data;
always @(posedge sys_clk or negedge rst_n)begin
if(!rst_n)begin
rom_data_r <= 32'd0;
end
else begin
rom_data_r <= #2 rom_data;
end
end
//實(shí)例化ROM
input_rom rom_ip_inst
(
.clka (sys_clk ), //inoput clka
.addra (rom_addr), //input [4:0] addra
.douta (rom_data) //output [7:0] douta
);
endmodule
step2:將ROM里的數(shù)據(jù)讀取出來,如果數(shù)據(jù)較少就直接使用二維數(shù)組保存數(shù)據(jù),較多的話可以添加一個(gè)RAM,然后通過調(diào)用RAM里面的變量搭建第一層神經(jīng)網(wǎng)絡(luò)(暫不添加sigmoid)。
input_rom_ctr input_rom( //取輸入層的數(shù)據(jù)存入ram
.sys_clk (clk),//50MHz時(shí)鐘
.rst_n (rst_n),//復(fù)位,低電平有效
.data_deep(5),
.rom_data_r (rom_data1), //ROM讀出數(shù)據(jù)
.viald (en_wr1),
.rom_addr_rr (input_index)
);
always @(posedge clk)begin
if(en_wr1) begin
input_layer[input_index] <= rom_data1; ? //從rom里面讀出數(shù)據(jù),并將其寫入ram/寄存器里面,后面的神經(jīng)網(wǎng)絡(luò)直接調(diào)用寄存器操作
end
else begin
input_data <= input_layer[input_index];//從ram里面讀出來的數(shù)據(jù),加載地址就得到相應(yīng)的數(shù)據(jù)。
end
end
Step3:通過仿真得到第一層神經(jīng)網(wǎng)絡(luò)每個(gè)神經(jīng)元的乘加結(jié)果,并加上偏置后,通過外部計(jì)算得到sigmoid值后將其添加到sigmoid模塊的lut查找模塊中,如此反復(fù),最后就可以得到一個(gè)神經(jīng)網(wǎng)絡(luò)框架。(sigmoid函數(shù)的結(jié)果也要乘以100,作為下一層的輸入),最后得到的輸入層的每個(gè)神經(jīng)元的結(jié)果就代表其識別結(jié)果的概率。
module sigmoid (
input wire signed [31:0] input_value, // 輸入32位有符號整數(shù)
output reg signed [31:0] sigmoid_output // 輸出32位有符號整數(shù)
);
always @(*) begin //可以看做是一個(gè)查找表,將上一層的輸入進(jìn)入sigmoid函數(shù)來進(jìn)行查找值,然后將得到的值乘以100用于保留兩位小數(shù),精度要求高的就多乘一點(diǎn)
case (input_value)
-2673 : sigmoid_output = 43; //上一層輸入3490,是原本輸入乘以100,保留兩位小數(shù)乘以權(quán)重乘以100,即改結(jié)果是原本結(jié)果的10000倍,所以進(jìn)sigmoid函數(shù)的應(yīng)該是0.349
17232 : sigmoid_output = 85; //建議以后有更多值后繼續(xù)添加,查找表越豐滿,后續(xù)能使用的輸入就越多。
36380 : sigmoid_output = 97;
124358 : sigmoid_output = 100;
-47650 : sigmoid_output = 1;
-5781 : sigmoid_output = 36;
3657 : sigmoid_output = 59;
-23082 : sigmoid_output = 9;
///上面是第一層隱層的結(jié)果,下面是輸出層的結(jié)果。
4816 : sigmoid_output = 62;
-3390 : sigmoid_output = 42;
20652 : sigmoid_output = 89;
-4386 : sigmoid_output = 39;
-2004 : sigmoid_output = 45;
-623 : sigmoid_output = 48;
default: sigmoid_output = 0;
endcase
end
endmodule
仿真結(jié)果
最后的output_layer就是輸出的最后結(jié)果。
來源:https://blog.csdn.net/qq_48434158/article/details/132426289
-
FPGA
+關(guān)注
關(guān)注
1644文章
22007瀏覽量
616375 -
matlab
+關(guān)注
關(guān)注
189文章
2999瀏覽量
233619 -
神經(jīng)網(wǎng)絡(luò)
+關(guān)注
關(guān)注
42文章
4812瀏覽量
103195 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4376瀏覽量
64530 -
python
+關(guān)注
關(guān)注
56文章
4825瀏覽量
86444
原文標(biāo)題:基于FPGA的神經(jīng)網(wǎng)絡(luò)的預(yù)測過程的實(shí)現(xiàn)
文章出處:【微信號:gh_9d70b445f494,微信公眾號:FPGA設(shè)計(jì)論壇】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
脈沖耦合神經(jīng)網(wǎng)絡(luò)在FPGA上的實(shí)現(xiàn)誰會?
【PYNQ-Z2試用體驗(yàn)】基于PYNQ的神經(jīng)網(wǎng)絡(luò)自動(dòng)駕駛小車 - 項(xiàng)目規(guī)劃
卷積神經(jīng)網(wǎng)絡(luò)如何使用
如何設(shè)計(jì)BP神經(jīng)網(wǎng)絡(luò)圖像壓縮算法?
解析深度學(xué)習(xí):卷積神經(jīng)網(wǎng)絡(luò)原理與視覺實(shí)踐
如何移植一個(gè)CNN神經(jīng)網(wǎng)絡(luò)到FPGA中?
基于FPGA的神經(jīng)網(wǎng)絡(luò)的性能評估及局限性
如何用ARM和FPGA搭建神經(jīng)網(wǎng)絡(luò)處理器通信方案?
基于光學(xué)芯片的神經(jīng)網(wǎng)絡(luò)訓(xùn)練解析,不看肯定后悔
如何構(gòu)建神經(jīng)網(wǎng)絡(luò)?
圖像預(yù)處理和改進(jìn)神經(jīng)網(wǎng)絡(luò)推理的簡要介紹
基于FPGA的RBF神經(jīng)網(wǎng)絡(luò)硬件實(shí)現(xiàn)
基于FPGA的神經(jīng)網(wǎng)絡(luò)硬件實(shí)現(xiàn)方法

評論