使用C#完成常用神经网络,并理解相关每个步骤和计算
这是一个由c#编写的神经网络,可以看到内部任何细节的实现,可以对学习神经网络,以及理解其中的计算方式。此架构不包含自动 Backward 向后传播,为了展示更多的计算细节。
源码包含 cnn,bp,fcn,lstm,convlstm,GRU 等示例内容,包含示例所用的数据内容。
LOSS支持:MESLOSS,cross-entropy
激活函数支持:ReLu,Tanh,Sigmod,Softmax
数据类型支持: float[][] 与 float[][][,],二维与四维
池化支持:平均池化Averpooling,最大池化Maxpooling
其他支持:ConvLayer,Conv2DLayer,MulLayer,ConvTranspose2DLayer
每个支持类都包含了向前传播Forward,与Backward向后传播的域名交易方法
以下几个小例子
CNN的训练实现
public class CNN
{
Conv2DLayer cl;
Conv2DLayer cl2;
Conv2DLayer cl3;
//TanhLayer sl = new TanhLayer();
//TanhLayer sl2 = new TanhLayer();
//TanhLayer sl3 = new TanhLayer();
Maxpooling ap1;
Maxpooling ap2;
SigmodLayer sl = new SigmodLayer();
SigmodLayer sl2 = new SigmodLayer();
//SigmodLayer sl3 = new SigmodLayer();
Softmax sl3 = new Softmax();
//Averpooling ap2;
//Averpooling ap1;
public CNN()
{
cl = new Conv2DLayer(1, 0, 5, 1, 6);
//ap1 = new Averpooling(2);
ap1 = new Maxpooling(2);
cl2 = new Conv2DLayer(1, 0, 5, 6, 12);
// ap2 = new Averpooling(2);
ap2 = new Maxpooling(2);
cl3 = new Conv2DLayer(in_channels: 12, out_channels: 10, _inSize: 4,_full:true );
}
public dynamic Forward(float[][][,] matrices)
{
dynamic data = cl.Forward(matrices);
data = sl.Forward(data);
data = ap1.Forward(data);
data = cl2.Forward(data);
data = sl2.Forward(data);
data = ap2.Forward(data);
data = cl3.Forward(data);
data = sl3.Forward(data);
return data;
}
dynamic cl3grid;
dynamic cl2grid;
dynamic clgrid;
public void backward(dynamic grid)
{
dynamic grid2 = sl3.Backward(grid);
cl3grid = cl3.backweight(grid2);//获取cl3的权重
//--------------------------------
grid2 = cl3.Backward(grid2);
grid2 =ap2.Backward(grid2);
grid2 = sl2.Backward(grid2);
cl2grid = cl2.backweight(grid2);//获取cl2的权重
//-------------------------------------
grid2 = cl2.Backward(grid2);
grid2 = ap1.Backward(grid2);
grid2 = sl.Backward(grid2);
clgrid = cl.backweight(grid2);//获取cl的权重
}
float lr = 1.0f;
public void update()
{
// int channl = cl3grid.grid.Length;
cl3.wdata = Matrix.MatrixSub(cl3.wdata, Matrix.multiply(cl3grid.grid, lr));
cl3.basicData = Matrix.MatrixSub(cl3.basicData, Matrix.multiply(cl3grid.basic, lr));
cl2.weights = Matrix.MatrixSub(cl2.weights, Matrix.multiply(cl2grid.grid, lr));
cl2.basicData = Matrix.MatrixSub(cl2.basicData, Matrix.multiply(cl2grid.basic, lr));
cl.weights = Matrix.MatrixSub(cl.weights, Matrix.multiply(clgrid.grid, lr));
cl.basicData = Matrix.MatrixSub(cl.basicData, Matrix.multiply(clgrid.basic, lr));
}
}
LSTM 实现例子
public class LSTMCELL
{
ConvLayer convLayerih;
ConvLayer convLayerhh;
int input_size; int hidden_size;
public LSTMCELL(int _input_size, int _hidden_size)
{
input_size = _input_size;
hidden_size = _hidden_size;
convLayerih = new ConvLayer(input_size, hidden_size * 4 );
//convLayerih.weights = JsonConvert.DeserializeObject<float[][]>(util.getstr("D:\\lstmihw.json"));
//convLayerih.basicData = JsonConvert.DeserializeObject<float[]>(util.getstr("D:\\lstmihb.json"));
convLayerhh = new ConvLayer( hidden_size, hidden_size * 4);
//convLayerhh.weights = JsonConvert.DeserializeObject<float[][]>(util.getstr("D:\\lstmhhw.json"));
//convLayerhh.basicData = JsonConvert.DeserializeObject<float[]>(util.getstr("D:\\lstmhhb.json"));
}
SigmodLayer input_gate_s = new SigmodLayer();
SigmodLayer forget_gate_s = new SigmodLayer();
SigmodLayer output_gate_s = new SigmodLayer();
TanhLayer cell_memory_tl = new TanhLayer();
TanhLayer cell_tl = new TanhLayer();
MulLayer c_next_mul = new MulLayer();
MulLayer mulin_gate_mul = new MulLayer();
MulLayer h_next_mul = new MulLayer();
public dynamic Forward(float[][] input, float[][] h_prev, float[][] c_prev)
{
//a_vector = np.dot(x, self.weight_ih.T) + np.dot(h_prev, self.weight_hh.T)
//a_vector += self.bias_ih + self.bias_hh
Xinput = input;
xh_prev = h_prev;
xc_prev = c_prev;
var ih = convLayerih.Forward(input);
var hh = convLayerhh.Forward(h_prev);
var a_vector = Matrix.MatrixAdd(ih, hh);
List<float[][]> liast = Matrix.chunk(a_vector,4,1);
var a_i = liast[0];
var a_f = liast[1];
var a_c = liast[2];
var a_o = liast[3];
input_gate = input_gate_s.Forward(a_i);
forget_gate = forget_gate_s.Forward(a_f);
cell_memory = cell_memory_tl.Forward(a_c);
output_gate = output_gate_s.Forward(a_o);
var c_next_temp = c_next_mul.Forward(forget_gate, c_prev);
var mulin_gate = mulin_gate_mul.Forward(input_gate, cell_memory);
var c_next = Matrix.MatrixAdd(c_next_temp, mulin_gate);
var h_next = h_next_mul.Forward(output_gate, cell_tl.Forward(c_next));
// dh_prev = Matrix.zroe(h_next.Length, h_next[0].Length);
return (h_next,c_next);//上次的状态,上次的记忆
}
dynamic Xinput, xh_prev, xc_prev, input_gate, forget_gate, cell_memory, output_gate;
// dynamic dh_prev;
dynamic ihweight, hhweight;
public dynamic backward(dynamic grid)
{
var dh = h_next_mul.BackwardY(grid);
var d_tanh_c = cell_tl.Backward(dh);
//var dc_prev=c_next_mul.backwardY(d_tanh_c);
var d_input_gate = mulin_gate_mul.Backward(d_tanh_c);
var d_forget_gate=c_next_mul.Backward(d_tanh_c);
var d_cell_memory = mulin_gate_mul.BackwardY(d_tanh_c);
var d_output_gate = h_next_mul.Backward(grid);// d_tanh_c
var d_ai = input_gate_s.Backward(d_input_gate);
var d_af = forget_gate_s.Backward(d_forget_gate);
var d_ao = output_gate_s.Backward(d_output_gate);
var d_ac = cell_memory_tl.Backward(d_cell_memory);
var temp=Matrix.cat(d_ai, d_af, 1);
var temp2 = Matrix.cat( d_ac, d_ao, 1);
var da= Matrix.cat(temp, temp2, 1);
// var daT=Matrix.T(da);
ihweight = convLayerih.backweight(da);
hhweight = convLayerhh.backweight(da);
return convLayerih.backward(da);
}
float lr = 0.1f;
public void update()
{
convLayerih.weights = Matrix.MatrixSub(convLayerih.weights, Matrix.multiply(ihweight.grid, lr));
convLayerih.basicData = Matrix.MatrixSub(convLayerih.basicData, Matrix.multiply(ihweight.basic, lr));
convLayerhh.weights = Matrix.MatrixSub(convLayerhh.weights, Matrix.multiply(hhweight.grid, lr));
convLayerhh.basicData = Matrix.MatrixSub(convLayerhh.basicData, Matrix.multiply(hhweight.basic, lr));
}
}
FCN实现例子
public class FCN
{
Conv2DLayer cl;
Conv2DLayer cl2;
Conv2DLayer cl3;
ConvTranspose2DLayer Tcl1;
Maxpooling mpl = new Maxpooling();
Maxpooling mpl2 = new Maxpooling();
SigmodLayer sl = new SigmodLayer();
SigmodLayer sl2 = new SigmodLayer();
SigmodLayer sl3 = new SigmodLayer();
Softmax sl4 = new Softmax();
public FCN(int weightssize)
{
cl = new Conv2DLayer(1, weightssize / 2, weightssize, 1, 6, bias: false);
cl2 = new Conv2DLayer(1, weightssize / 2, weightssize, 6, 12, bias: false);
cl3 = new Conv2DLayer(1, weightssize / 2, weightssize, 12, 24, bias: false);
Tcl1 = new ConvTranspose2DLayer(2, 1, weightssize + 1, 24, 1, bias: false);
}
public dynamic Forward(dynamic data)
{
dynamic data2= cl.Forward(data);
data2=sl.Forward(data2);
data2=mpl.Forward(data2);
data2 = cl2.Forward(data2);
data2 = sl2.Forward(data2);
data2 = mpl2.Forward(data2);
data2 = cl3.Forward(data2);
data2 = sl3.Forward(data2);
data2=Tcl1.Forward(data2);
data2 = sl4.Forward(data2);
return data2;
}
public dynamic backward(dynamic grid)
{
var grid2 = sl4.Backward(grid);
grid2= Tcl1.Backward(grid2);
grid2 = sl3.Backward(grid2);
grid2 = cl3.Backward(grid2);
grid2 = mpl2.Backward(grid2);
grid2 = sl2.Backward(grid2);
grid2 = cl2.Backward(grid2);
grid2 = mpl.Backward(grid2);
grid2 = sl.Backward(grid2);
grid2 = cl.Backward(grid2);
return grid2;