44.3_Linear类的实现

44.3 Linear类的实现

接下来实现进行线性变换的Linear类(实现的是作为层的Linear类,而不是作为函数的Linear类)。这里首先给出简单的Linear类,然后展示改良版的Linear类。我们来看以下代码。

import numpy as np   
importdezero-functionsasF   
fromdezero.core import Parameter   
class Linear(Layer): def__init__(self,in_size,out_size,nobias  $\equiv$  False,dtype=np.float32): super().__init_() I,O  $=$  in_size,out_size W_data  $=$  np.random.randint(I,O).astypedtype)\*np.sqrt(1/I) self.W  $=$  Parameter(W_data,name  $\coloneqq$  'W') ifnobias: self.b  $=$  None else: self.b  $=$  Parameter(np.zeros(O,dtype  $\equiv$  dtype),name  $\equiv$  'b')   
defforward(self,x): y  $=$  F.Linear(x,self.W,self.b) returny

Linear类是在Layer类的基础上实现的。初始化方法__init__(self, in_size, out_size, nobias)接收输入大小、输出大小和“是否使用偏置”的标志位作为参数。当nobias为True时,省略偏置。

初始化权重和偏置的做法是向实例变量设置Parameter实例,如self.W = Parameter(...) 和 self.b = Parameter(...)。设置后,这两个参数的Parameter实例变量名就会被添加到self._params中。

Linear类的权重新始值需要设置为随机数。上一个步骤将随机的初始值的量级设置为0.01(0.01 * np.random.randint(...))。这里将量级设置为np.sqrt(1/in_size)。这是参考文献[25]中提出的设置初始值的方法。另外,神经网络的计算也支持32位浮点数,因此,我们使用32位浮点数作为参数数据的默认设置值。

之后,在forward方法中实现线性变换,只需调用DeZero的linear函数即可。以上就是Linear类的实现。

前面提到了Linear类有一种更好的实现方法,即延迟创建权重W的时间。具体做法是在forward方法中创建权重,这样就能自动确定Linear类的输入大小(in_size)(无须用户指定)。下面是改进版的Linear类的实现。

dezero/layers.py

import numpy as np   
importdezero-functionsasF   
fromdezero.core import Parameter   
class Linear(Layer): def__init__(self,out_size,nobias  $\equiv$  False,dtype=np.float32,in_size=No super().__init_() self.in_size  $=$  in_size self.out_size  $=$  out_size self.dtype  $=$  dtype self.W  $=$  Parameter(None,name  $\coloneqq$  'W') if self.in_sizeis not None:#如果没有指定in_size,则延后处理 self._init_W() ifnobias: self.b  $=$  None else: self.b  $=$  Parameter(np.zeros(out_size,dtype  $\equiv$  dtype),name  $\equiv$  'b') def_init_W(self): I,O  $=$  self.in_size,self.out_size W_data  $=$  np.random.randint(I,O).astype(self.dtype)*np.sqrt(1/I) self.W.data  $=$  W_data   
defforward(self,x): #在传播数据时初始化权重
if self.w.data is None:  
    self.in_size = x.shape[1]  
    self._init_W()  
y = F.Linear(x, self.w, self.b)  
return y

这就是改进版的Linear类。这里需要注意的地方是我们不用指定__init__方法的in_size。in_size参数的默认值为None,在None的情况下,self.W.data的初始化会被推迟。具体来说,forward(self,x)方法根据输入x的大小创建权重数据。现在我们只要按照layer = Linear(100)的方式指定输出大小即可。以上就是Linear类的实现。