运用自定义模型类从头末尾训练线性回归,比较PyTorch 1.x和TensorFlow 2.x之间的自动差异和静态模型子类化办法,
这篇冗长的文章重点引见如何在PyTorch 1.x和TensorFlow 2.x中辨别运用带有模块/模型API的静态子类化模型,以及这些框架在训练循环中如何运用AutoDiff取得损失的梯度并从头末尾完成 一个十分干练的突变后代完成。
生成噪声的线性数据为了专注于自动差异/自动突变功用的中心,我们将运用最复杂的模型,即线性回归模型,然后我们将首先运用numpy生成一些线性数据,以添加随机级别的噪声。
def generate_data(m=0.1, b=0.3, n=200):
x = np.random.uniform(-10, 10, n)
noise = np.random.normal(0, 0.15, n)
y = (m * x + b ) + noise return x.astype(np.float32), y.astype(np.float32)
x, y = generate_data()plt.figure(figsize = (12,5))
ax = plt.subplot(111)
ax.scatter(x,y, c = "b", label="samples")
模型然后,我们将在TF和PyTorch中完成从零末尾的线性回归模型,而无需运用任何层或激活器,而只需定义两个张量w和b,辨别代表线性模型的权重和偏向,并复杂地完成线性函数即可:y = wx + b
正如您在下面看到的,我们的模型的TF和PyTorch类定义基本上完全相反,但在一些api称号上只要很小的差异。
独一值得留意的区别是,PyTorch明白地运用Parameter对象定义权重和要由图形"捕获"的偏置张量,而TF似乎在这里更"神奇",而是自动捕获用于图形的参数。
确真实PyTorch参数中是Tensor子类,当与Module api一同运用时,它们具有十分特殊的属性,可以自动将本身添加到Module参数列表中,并会出如今在parameters()迭代器中。
无论如何,两个框架都可以从此类定义和执行办法(call或 forward ),参数和图形定义中提取信息,以便向前执行图形执行,并且正如我们将看到的那样,经过自动可微分取得梯度功用,以便可以执行反向传达。
TensorFlow静态模型
class LinearRegressionKeras(tf.keras.Model):
def __init__(self):
super().__init__() self.w = tf.Variable(tf.random.uniform(shape=[1], -0.1, 0.1))
self.b = tf.Variable(tf.random.uniform(shape=[1], -0.1, 0.1))
def __call__(self,x):
return x * self.w + self.b
PyTorch静态模型
class LinearRegressionPyTorch(torch.nn.Module):
def __init__(self):
super().__init__() self.w = torch.nn.Parameter(torch.Tensor(1, 1).uniform_(-0.1, 0.1))
self.b = torch.nn.Parameter(torch.Tensor(1).uniform_(-0.1, 0.1))
def forward(self, x):
return x @ self.w + self.b
训练循环,反向传达和优化器如今我们曾经完成了复杂的TensorFlow和PyTorch模型,我们可以定义TF和PyTorch api来完成均方误差的损失函数,最后实例化我们的模型类并运转训练循环。
异样,本着眼于自动差异/自动突变功用中心的目的,我们将运用TF和PyTorch特定的自动差异完成方式完成自定义训练循环,以便为我们的复杂线性函数提供突变并手动优化权重和偏向参数以及暂时和朴素的突变后代优化器。
在TensorFlow训练循环中,我们将特别明白地运用GradientTape API来记载模型的正向执行和损失计算,然后从该GradientTape中取得用于优化权重和偏向参数的梯度。
相反,在这种状况下,PyTorch提供了一种更"神奇"的自动突变办法,隐式捕获了对参数张量的任何操作,并为我们提供了相反的梯度以用于优化权重和偏置参数,而无需运用任何特定的api。
一旦我们有了权重和偏向梯度,就可以在PyTorch和TensorFlow上完成我们的自定义梯度派生办法,就像将权重和偏向参数减去这些梯度乘以恒定的学习率一样复杂。
(责任编辑:admin)