考百度指数 某个关键词在某个行业网站上的,一家企业如何建设自己的网站 下载,甘肃网站推广,超市建网站上一个博客中讲解了用python实现一个简单的两层神经网络#xff0c;我们是把所有的网络层都直接写在了类中。但是作为一个神经网络框架#xff0c;网络的结构应该是可以由使用者自定义的#xff0c;这样一来也就不用为每个网络结构都重写所有代码#xff0c;我们把每一层模…上一个博客中讲解了用python实现一个简单的两层神经网络我们是把所有的网络层都直接写在了类中。但是作为一个神经网络框架网络的结构应该是可以由使用者自定义的这样一来也就不用为每个网络结构都重写所有代码我们把每一层模块化在神经网络的类中定义结构时使用这些模块化的层堆叠形成一个完整的神经网络。每一种层分别实现forward和password两个函数用来正向计算和反向传播。这里我们实现的网络层和功能有全连层、激活层、计算loss、自动训练1、全连层全连层的正向计算很简单f(W,x)xWb。反向传播分别求x,W,b的梯度dxf(W,x)·W.T,dWx·f(W,x),dbf(W,x)。1 defaffine_forward(x, w, b):2 #######################################3 #x: input shape (N, d_1, ..., d_k)4 #w: Weights shape (D, M)5 #b: bias shape (M)6 #7 #Returns :8 #out: output,shape (N, M)9 #cache: (x, w, b)10 ########################################11 x1x.reshape(x.shape[0],-1)12 outnp.dot(x1,w)b13 cache(x,w)14 returnout,cache1516 defaffine_backward(dout, cache):17 ##################################################18 #dout: Upstream derivative, of shape (N, M)19 #cache: Tuple of:20 #x: Input shape (N, d_1, ... d_k)21 #w: Weights shape (D, M)22 #23 #Returns a tuple of:24 #dx: shape (N, d1, ..., d_k)25 #dw: shape (D, M)26 #db: shape (M,)27 ##################################################28 x,wcache29 Nx.shape[0]30 x1x.reshape(N,-1)31 dxnp.dot(dout,w.T).reshape(*x.shape)32 dwnp.dot(x1.T,dout)33 dbnp.sum(dout,axis0)34 return dx,dw,dbView Code2、激活层激活层只实现常用的relu激活函数。f(x)max(0,x)。反向传播也很简单被激活的继承上一级的梯度没有激活的梯度为0。这里不涉及到参数的梯度计算只涉及到梯度的传播。1 defrelu_forward(x):2 out np.maximum(0,x)3 cache x4 returnout, cache567 defrelu_backward(dout, cache):8 x cache9 dx dout * (x0)10 return dxView Code实际使用过程中一般全连接层后面都会接激活层为了方便起见可以合并两层。这里的合并跟之后的整个神经网络的堆叠思想一致。1 defaffine_relu_forward(x, w, b):2 3 全连接层和激活层的合并45 Inputs:6 - x: 全连接层的输入7 - w, b: 全连接层的权重参数89 Returns a tuple of:10 - out: 被激活的全连接层的输出11 - cache: 用于反向传播12 13 a,fc_cacheaffine_forward(x,w,b)14 out,relu_cacherelu_forward(a)15 returnout, (fc_cache,relu_cache)161718 defaffine_relu_backward(dout, cache):19 fc_cache, relu_cache cache20 darelu_backward(dout,relu_cache)21 dx,dw,dbaffine_backward(da,fc_cache)22 return dx, dw, dbView Code3、loss层严格上讲这不算神经网络的一个层只是为了训练而必须进行的一个计算但是这里我们就把它也当作一个层好了。loss函数在上一个博客中已经详细介绍过了。https://www.cnblogs.com/super-JJboom/p/9748468.html1 defsvm_loss(x, y):23 N,Cx.shape4 correct_class_scoresx[range(N),y].reshape(-1,1)5 marginsnp.maximum(0,x-correct_class_scores1)6 lossnp.sum(margins)/N7 dx np.zeros_like(x)8 dx[margins0]19 num_pos np.sum(margins 0, axis1)10 dx[range(N),y]-num_pos11 dx/N1213 returnloss, dx141516 defsoftmax_loss(x, y):1718 N,Cx.shape19 shift_xx-np.max(x,axis1,keepdimsTrue).reshape(-1,1)20 Znp.sum(np.exp(shift_x),axis1,keepdimsTrue)21 log_pro-shift_xnp.log(Z)22 lossnp.sum(log_pro[range(N),y])/N23 probsnp.exp(-log_pro)24 probs[range(N),y]-125 dxprobs26 dx/NView Code到此为止之前我们实现两层神经网络需要的层已经都实现了。先重构一下之前的实现吧。1 #2层神经网络2 classTwoLayerNet(object):3 #The architecure : affine - relu - affine - softmax.4 def __init__(self, input_dim3*32*32,hidden_dim100,num_classes10,weight_scale1e-3,reg0.0):5 ################################6 #input_dim 输入维度7 #hidden_dims 隐藏层神经元个数8 #num_classes 输出个数9 #weight_scale 初始化权重10 #reg 正则项系数11 ################################12 self.params{}13 self.regreg14 self.params[W1]weight_scale*np.random.randn(input_dim,hidden_dim)15 self.params[b1]np.zeros(hidden_dim)16 self.params[W2]weight_scale*np.random.randn(hidden_dim,num_classes)17 self.params[b2]np.zeros(num_classes)1819 def loss(self,X,yNone):20 #返回loss和grad2122 #前向计算23 ar1_out,ar1_cacheaffine_relu_forward(X,self.params[W1],self.params[b1])24 a2_out,a2_cacheaffine_forward(ar1_out,self.params[W2],self.params[b2])25 scoresa2_out2627 if y isNone:28 returnscores2930 loss,grads0,{}31 loss,dscoressoftmax_loss(scores,y)32 lossloss0.5*self.reg*(np.sum(self.params[W1]**2)np.sum(self.params[W2]**2))33 dx2,dw2,db2affine_backward(dscores,a2_cache)34 grads[W2]dw2self.reg*self.params[W2]35 grads[b2]db23637 dx1,dw1,db1affine_relu_backward(dx2,ar1_cache)38 grads[W1]dw1self.reg*self.params[W1]39 grads[b1]db14041 return loss,gradsView Code看起来比之前的实现并没有简单多少。。。这是因为2层神经网络的结构过于简单仅从代码量上来看并没有减少但是对于后面要实现的更复杂的神经网络来说就发挥了巨大的作用。哦对比之前的实现发现少了自动化训练的实现。因为训练有很多参数可以选择和调节之前没有实现如果全部放入神经网络的类中的话会显得过于臃肿所以把训练过程的实现单独拿出来作为一个类。4、自动化训练相比与之前的自动训练过程这里增加了更多的可选项。可以选择优化方法如SGD带动量的SGDadam。每一轮数据迭代完之后显示数据。1 importnumpy as np2 from cs231n importoptim34 classSolver(object):5 def __init__(self,model,data,**kwargs):6 7 初始化对象8 inputs:9 - model:网络结构对象10 - data:字典包含带标签的训练集和验证集11 - kwargs:可选参数详细见下面提取时候的注释12 1314 self.modelmodel15 self.X_traindata[X_train]16 self.y_traindata[y_train]17 self.X_valdata[X_val]18 self.y_valdata[y_val]1920 #解读kwargs21 self.update_rulekwargs.pop(update_rule,sgd) #优化方法的选择默认为随机梯度下降22 self.optim_configkwargs.pop(optim_config,{}) #优化的参数学习率是必须有的选项。其他可以有动量因子之类的参数23 self.lr_decaykwargs.pop(lr_decay,1.0) #学习率衰减因子默认不衰减24 self.batch_sizekwargs.pop(batch_size,128) #批大小默认12825 self.num_epochskwargs.pop(num_epochs,10) #训练全部数据的轮次默认为10轮26 self.print_everykwargs.pop(print_every,10) #多少轮显示一次进度27 self.verbosekwargs.pop(verbose,True) #是否显示进度为false的情况下上一个参数无效2829 #含有不支持的参数30 if len(kwargs)0:31 extra,.join(%s % k for k inkwargs.keys())32 raise ValueError(Unrecongnized arguments %s %extra)3334 #检查优化方法是否支持35 if nothasattr(optim,self.update_rule):36 raise ValueError(invalid update_rule %s %self.update_rule)3738 self.update_rulegetattr(optim,self.update_rule)3940 self._reset()4142 def_reset(self):43 #初始化参数44 self.epoch045 self.best_val_acc046 self.best_params{}47 self.loss_history[]48 self.train_acc_history[]49 self.val_acc_history[]5051 #给给个参数矩阵复制一个优化参数因为之后每个权重的参数不相同需要自己保存52 self.optim_configs{}53 for p inself.model.params:54 d{k:v for k,v inself.optim_config.items()}55 self.optim_configs[p]d5657 def_step(self):58 #单步更新5960 #随机取出batchsize个数据61 num_trainself.X_train.shape[0]62 batch_masknp.random.choice(num_train,self.batch_size)63 X_batchself.X_train[batch_mask]64 y_batchself.y_train[batch_mask]6566 #计算loss67 loss,gradsself.model.loss(X_batch,y_batch)68 self.loss_history.append(loss)6970 #更新参数71 for p,w inself.model.params.items():72 dwgrads[p]73 configself.optim_configs[p]74 next_w,next_configself.update_rule(w,dw,config)75 self.model.params[p]next_w76 self.optim_configs[p]next_config7778 #计算正确率79 def check_accuracy(self,X,y,num_samplesNone,batch_size128):80 NX.shape[0]8182 #如果num_sample不为空 则只从全部数据中选则num_sample个数据计算83 if num_samples is not None and Nnum_samples:84 masknp.random.choice(N,num_samples)85 Nnum_samples86 XX[mask]87 yy[mask]8889 num_batchesN//batch_size90 if N%batch_size!0:91 num_batches192 y_pred[]93 for i inrange(num_batches):94 starti*batch_size95 end(i1)*batch_size96 scoresself.model.loss(X[start:end])97 y_pred.append(np.argmax(scores,axis1))98 y_prednp.concatenate(y_pred,axis0)99 accnp.mean(y_predy)100101 returnacc102103 deftrain(self):104 num_trainself.X_train.shape[0]105 iterations_per_epochmax(num_train//self.batch_size,1)106 num_iterationsself.num_epochs*iterations_per_epoch107108 for t inrange(num_iterations):109 self._step()110111 if self.verbose and t%self.print_every0:112 print(Iteration %d /%d loss: %f %(t1,num_iterations,self.loss_history[-1]) )113114 #每个epoch执行相应操作115 epoch_end(t1)%iterations_per_epoch0116 ifepoch_end:117 self.epoch1118 for k inself.optim_configs:119 self.optim_configs[k][learning_rate]*self.lr_decay120121 first_it(t0)122 last_it(tnum_iterations-1)123 if first_it or last_it orepoch_end:124 train_accself.check_accuracy(self.X_train,self.y_train,num_samples1280)125 val_accself.check_accuracy(self.X_val ,self.y_val)126 self.train_acc_history.append(train_acc)127 self.val_acc_history.append(val_acc)128129 #可视化进度130 ifself.verbose:131 print ((Epoch %d / %d) train acc: %f; val_acc: %f %(132 self.epoch, self.num_epochs, train_acc, val_acc))133134 #检查、保存模型135 if val_accself.best_val_acc:136 self.best_val_accval_acc137 self.best_params{}138 for k,v inself.model.params.items():139 self.best_params[k]v.copy()140141 self.model.paramsself.best_paramsView Code实现到这里已经可以重新训练之前的两层神经网络了训练代码全部整合带最后的测试代码里面了。5、实现全连层神经网络框架实现跟两层神经网络区别不大只是网络层的堆叠使用了循环。这里还没有实现的批归一化和dropout操作后面会讲到。1 classFullyConnectedNet(object):2 #archtecture: {affine - [batch norm] - relu - [dropout]} x (L - 1) - affine - softmax3 def __init__(self,hidden_dims,input_dim3*32*32,num_classes10,dropout0,4 use_batchnormFalse,reg0.0,weight_scale1e-3,dtypenp.float32,seedNone):56 7 inputs:8 - hidden_dims:list,存储了有多少个中间层每一层有多少个神经元9 - input_dim: 输入数据的维度大小10 - num_classes:类别的个数也就是最后一层的神经元个数11 - dropout:失活率12 - use_batchnorm:是否在每一层之间使用批归一化操作13 - reg:正则权重14 - weight_scale:权重矩阵的初始数量级15 - seed:失活率随机16 1718 self.use_batchnormuse_batchnorm19 self.use_dropout(dropout0)20 self.regreg21 self.num_layers1len(hidden_dims)22 self.dtypedtype23 self.params{}2425 #初始化每层的参数w,b [gamma,beta,dropout](如果有的话)26 layer_inputinput_dim27 for i,hd inenumerate(hidden_dims):28 self.params[W%d%(i1)]weight_scale*np.random.randn(layer_input,hd)29 self.params[b%d%(i1)]weight_scale*np.zeros(hd)30 ifself.use_batchnorm:31 self.params[gamma%d%(i1)]np.ones(hd)32 self.params[beta%d%(i1)]np.zeros(hd)33 layer_inputhd34 self.params[W%d%(self.num_layers)]weight_scale*np.random.randn(layer_input,num_classes)35 self.params[b%d%(self.num_layers)]weight_scale*np.zeros(num_classes)36 for k,v inself.params.items():37 self.params[k]v.astype(dtype)3839 self.dropout_param{}40 ifself.use_dropout:41 self.dropout_param{mode:train,p:dropout}42 if seed is notNone:43 self.dropout_param[seed]seed4445 self.bn_params[]46 ifself.use_batchnorm:47 self.bn_params[{mode:train} for i in range(self.num_layers-1)]4849 def loss(self,X,yNone):5051 #跟之前一样yNone时表示测试过程直接返回最后一层的输出即可。否则表示训练过程还要计算loss和gradient。5253 XX.astype(self.dtype)54 modetest if y is None else train5556 if self.dropout_param is notNone:57 self.dropout_param[mode] mode58 ifself.use_batchnorm:59 for bn_param inself.bn_params:60 bn_param[mode] mode616263 #forward pass64 layer_inputX65 ar_cache{}66 dp_cache{}6768 for lay in range(self.num_layers-1):69 ifself.use_batchnorm:70 layer_input, ar_cache[lay] affine_bn_relu_forward(layer_input,71 self.params[W%d%(lay1)], self.params[b%d%(lay1)],72 self.params[gamma%d%(lay1)], self.params[beta%d%(lay1)], self.bn_params[lay])73 else:74 layer_input,ar_cache[lay]affine_relu_forward(layer_input,self.params[W%d%(lay1)],self.params[b%d%(lay1)])7576 ifself.use_dropout:77 layer_input, dp_cache[lay] dropout_forward(layer_input, self.dropout_param)7879 ar_out,ar_cache[self.num_layers]affine_forward(layer_input,self.params[W%d%(self.num_layers)],self.params[b%d%(self.num_layers)])80 scoresar_out8182 #预测时直接返回scores即可83 if modetest:84 returnscores8586 #训练时还要计算loss和gradient87 grads{}88 loss,dscoressoftmax_loss(scores,y)89 dhoutdscores90 loss0.5*self.reg*np.sum(self.params[W%d%(self.num_layers)]**2)91 dx,dw,dbaffine_backward(dhout,ar_cache[self.num_layers])92 grads[W%d%(self.num_layers)]dwself.reg*self.params[W%d%(self.num_layers)]93 grads[b%d%(self.num_layers)]db94 dhoutdx95 for lay in range(self.num_layers-1):96 layself.num_layers-1-lay-197 loss0.5*self.reg*np.sum(self.params[W%d%(lay1)]**2)98 ifself.use_dropout:99 doutdropout_backward(dhout,dp_cache[lay])100 ifself.use_batchnorm:101 dx,dw,db,dgamma,dbetaaffine_bn_relu_backward(dhout,ar_cache[lay])102 grads[gamma%d%(lay1)] dgamma103 grads[beta%d%(lay1)] dbeta104 else:105 dx,dw,dbaffine_relu_backward(dhout,ar_cache[lay])106 grads[W%d%(lay1)]dwself.reg*self.params[W%d%(lay1)]107 grads[b%d%(lay1)]db108 dhoutdx109110 return loss,gradsView Code