0.前言

中间有很多修改代码的是过程笔记,都是不可用的,仅仅用于记录思路,如果想看最终代码直接翻到最下面。


运行李沫2021深度学习线性回归代码如下

def synthetic_data(w, b, num_examples):  
    """生成 y = Xw + b + 噪声。"""
    X = torch.normal(0, 1, (num_examples, len(w)))
    y = torch.matmul(X, w) + b
    y += torch.normal(0, 0.01, y.shape)
    return X, y.reshape((-1, 1))

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)

报以下错误:

TypeError                                 Traceback (most recent call last)
<ipython-input-14-13b36a1f7ef4> in <module>
      8 true_w = torch.tensor([2, -3.4])
      9 true_b = 4.2
---> 10 features, labels = synthetic_data(true_w, true_b, 1000)

<ipython-input-14-13b36a1f7ef4> in synthetic_data(w, b, num_examples)
      1 def synthetic_data(w, b, num_examples):
      2     """生成 y = Xw + b + 噪声。"""
----> 3     X = torch.normal(0, 1, (num_examples, len(w)))
      4     y = torch.matmul(X, w) + b
      5     y += torch.normal(0, 0.01, y.shape)

TypeError: normal() received an invalid combination of arguments - got (int, int, tuple), but expected one of:
 * (Tensor mean, Tensor std, torch.Generator generator, Tensor out)
 * wei
 * (float mean, Tensor std, torch.Generator generator, Tensor out)

为了弄懂错误,就去查阅文档看看,发现网上大部分介绍都是

torch.normal(mean, std, out=None) → Tensor

 Tensor mean, Tensor std

torch.normal(mean, std=1.0, out=None) → Tensor

 Tensor mean, float std

torch.normal(mean=0.0, std, out=None) → Tensor

 float mean, Tensor std

错误里还有torch.Generator generator没有介绍,故专门查阅下包含torch.Generator generator的文档。

注:翻阅pytorch1.0中文文档没有介绍torch.normal(mean, std, *, generator=None, out=None),最终查阅了最新pytorch英文文档得出以下记录。发现多出了两种torch.normal()函数的格式。

1.torch.normal()函数的另外两种格式介绍

 torch.normal(mean, std, *, generator=None, out=None) → Tensor

 torch.normal(mean, std, *, generator=None, out=None) → Tensor

返回从单独的正态分布中提取的随机数张量,这些正态分布的平均值和标准差是给定的。

mean 是一个张量,具有每个输出元素正态分布的均值

std 是一个张量,每个输出元素的正态分布的标准差

mean 和 std 的形状不需要匹配,但是每个张量中的元素总数需要相同。

当形状不匹配时,平均值的形状被用作返回输出张量的形状

当std是CUDA张量时,这个函数使它的设备与CPU同步。

参数

mean (Tensor) –每个元素平均值的张量

std (Tensor) –每个元素标准偏差的张量

关键字参数

generator (torch.Generator, optional) –用于采样的伪随机数生成器

out (Tensor, optional) –输出张量

torch.normal(mean, std, size, *, out=None) → Tensor

torch.normal(mean, std, size, *, out=None) → Tensor

与上述函数类似,但所有绘制的元素都共享平均值和标准差。由此产生的张量大小由大小给定。

参数

mean (float)-所有分布的平均值

std(float)–所有分布的标准偏差

size (int...)–定义输出张量形状的整数序列。

关键字参数

out(张量,可选)–输出张量。

2.对代码的修改(记录的错误代码及笔记)

由错误看出代码格式为(int, int, tuple)以及课程中老师所说,大胆推测使用的格式为

torch.normal(mean, std, size, *, out=None)

修改代码如下:

def synthetic_data(w, b, num_examples):  
    """生成 y = Xw + b + 噪声。"""
    X = torch.normal(0., 1., (num_examples, len(w)))
#X = torch.normal(mean = 0.,std= 1., size =(num_examples, len(w)))
#尝试上述也不行
    y = torch.matmul(X, w) + b
    y += torch.normal(0., 0.01, y.shape)
    return X, y.reshape((-1, 1))

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)

运还是报错老问题

注:以上代码在pytorch1.0.0版本还是报错

3.结论以及代码其它修改过程记录(也是错误的代码

经过反复的尝试,最终确认。因为使用的版本为pytorch1.0.0而不是新版本,无法使用老师给的程序。(pytorch1.0.0版本normal函数无size的使用方式)

最终决定按照pytorch1.0.0版本魔改代码如下:

此处采用格式为(Tensor mean, float std, torch.Generator generator, Tensor out)

修改代码如下:

def synthetic_data(w, b, num_examples):  
    """生成 y = Xw + b + 噪声。"""
    X = torch.normal(torch.tensor([0]), 1.)
    y = torch.matmul(X, w) + b
    y += torch.normal(torch.tensor([0]), 0.01)
    return X, y.reshape((-1, 1))

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)

出现新的错误:

RuntimeError: _th_normal is not implemented for type torch.LongTensor

原因类型默认为float64,类型太长,故改成32位

故修改代码如下:

def synthetic_data(w, b, num_examples):  
    """生成 y = Xw + b + 噪声。"""
    a1 = torch.tensor([0],dtype=torch.float32)#直接放函数里会报错,故使用a1先生成好

    X = torch.normal(a1, 1.)
    y = torch.matmul(X, w) + b
    y += torch.normal(a1, 0.01)
    return X, y.reshape((-1, 1))

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)

出现新的错误:

RuntimeError                              Traceback (most recent call last)
<ipython-input-48-e254f9fc8d52> in <module>
     10 true_w = torch.tensor([2, -3.4],dtype=torch.float32)
     11 true_b = 4.2
---> 12 features, labels = synthetic_data(true_w, true_b, 1000)

<ipython-input-48-e254f9fc8d52> in synthetic_data(w, b, num_examples)
      4 
      5     X = torch.normal(a1, 1.)
----> 6     y = torch.matmul(X, w) + b
      7     y += torch.normal(a1, 0.01)
      8     return X, y.reshape((-1, 1))
RuntimeError: inconsistent tensor size, expected tensor [1] and src [2] to have the same number of elements, but got 1 and 2 elements respectively


原因是计算时维数不一样。

修改代码如下:

def synthetic_data(w, b, num_examples):  
    """生成 y = Xw + b + 噪声。"""
    a1 = torch.tensor([0,0],dtype=torch.float32)#直接放函数里会报错,故使用a1先生成好
    
    X = torch.normal(a1, 1.)
    y = torch.matmul(X, w) + b
    y += torch.normal(a1,1.)
    return X, y.reshape((-1, 1))

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)

出现错误如下:

RuntimeError                              Traceback (most recent call last)
<ipython-input-36-915e79a2fa26> in <module>
     10 true_w = torch.tensor([2, -3.4])
     11 true_b = 4.2
---> 12 features, labels = synthetic_data(true_w, true_b, 1000)

<ipython-input-36-915e79a2fa26> in synthetic_data(w, b, num_examples)
      5     X = torch.normal(a1, 1.)
      6     y = torch.matmul(X, w) + b
----> 7     y += torch.normal(a1,1.)
      8     return X, y.reshape((-1, 1))
      9 

RuntimeError: output with shape [] doesn't match the broadcast shape [2]

 由于广播机制等原因,张量的 y+=a y=a+y 的运算是有区别的,故修改代码如下:
 

def synthetic_data(w, b, num_examples):  
    """生成 y = Xw + b + 噪声。"""
    a1 = torch.tensor([0,0],dtype=torch.float32)#直接放函数里会报错,故使用a1先生成好
    
    X = torch.normal(a1, 1.)
    y = torch.matmul(X, w) + b
    y = torch.normal(a1,1.) + y
    return X, y.reshape((-1, 1))

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)

此处代码运行以及不会报错,但是接下来运行下面代码:

print('features:', features[0], '\nlabel:', labels[0])

输出如下:

features: tensor(-0.9737) 
label: tensor([7.3704])

 与课程中输出不一样,:如下

features: tensor([-0.0748, -0.3831]) 
label: tensor([5.3410])

 后来反思之后发现陷入误区,不能根据错误而该程序,应该从课程中要设计个什么函数而写代码,以上代码仅仅是思考的过程笔记,都不是正确的,正确代码从第4节开始。

 ==============================分界线=================================

==============补充函数torch.matmul()介绍=================

torch.matmul(tensor1, tensor2, out=None) → Tensor

两张量的矩阵积。

行为取决于张量的维数,如下所示:

如果两个张量都是一维的,则返回点积(标量)。

如果两个参数都是二维的,则返回矩阵积。

如果第一个参数是一维的,第二个参数是二维的,那么为了矩阵相乘,在其维数前面加上1。在矩阵相乘之后,前面的维度被移除。

如果第一个参数是二维的,第二个参数是一维的,则返回矩阵向量积。

如果两个参数都至少是一维的,并且至少有一个参数是N维的(其中N>2),则返回一个成批矩阵乘法。如果第一个参数是一维的,则为了成批矩阵相乘的目的,在其维数前面加一个1,然后将其删除。如果第二个参数是一维的,则为了成批矩阵的倍数,在其维数后附加一个1,并在其后删除。非矩阵(即批处理)维度是广播的(因此必须是可广播的)。例如,如果tensor1是torch张量,tensor2是torch张量,out将是torch张量。

注意

此函数的一维点积版本不支持out参数。

参数:

tensor1(张量)–要相乘的第一个张量

tensor2(张量)–要相乘的第二个张量

out(张量,可选)–输出张量

====================================================================

==============================分界线=================================

====================================================================

4.最终程序如下(正确修改后的代码):

于是从最根本的地方出发,想办法找个类似函数替换。课程根据带有噪声的线性模型构造一个人造数据集。 设训练数据集样本数为1000,输入个数(特征数)为2。就有了如下代码:

import numpy as np

def synthetic_data(w, b, num_examples):  
    """生成 y = Xw + b + 噪声。"""
    #X = torch.normal(0, 1, (num_examples, len(w)))
    #原本老师定义size 为(num_examples=1000,len(w)=2)
    X = torch.tensor(np.random.normal(0, 1, size=(num_examples, len(w))), dtype=torch.float32)

    #或者使用下面代码与上面代码差不多效果
    #X = torch.randn(num_examples, len(w), dtype=torch.float32)
    #以下代码创建一个形状为 (3, 4) 的张量。其中的每个元素都从均值为0、标准差为1的标准高斯(正态)分布中随机采样。
    #参考自https://zh-v2.d2l.ai/chapter_preliminaries/ndarray.html#id2
    #的torch.randn(3, 4)函数

# numpy.random.normal(loc=0,scale=1e-2,size=shape)
#参数loc(float):正态分布的均值,对应着这个分布的中心。loc=0说明这一个以Y轴为对称轴的正态分布
#参数scale(float):正态分布的标准差,对应分布的宽度,scale越大,正态分布的曲线越矮胖,scale越小,曲线越高瘦
#参数size(int 或者整数元组):输出的值赋在shape里,默认为None

#补充 (w,b)的初始化  若维数为d
#可以证明,如果X服从正态分布,均值为0,方差为1,且各个维度线性无关,而(w,b)是
#(-1/(d的根号),1/(d的根号))的均匀分布,则 (W^T)X+b 是均值为0,方差为1/3的正态分布 
#原因:若(W^T)X+b很大或很小会导致梯度趋近于0,造成梯度消失现象

    y = torch.matmul(X, w) + b
    #若input维度1D,other维度2D,则先将1D的维度扩充到2D(1D的维数前面+1),
    #然后得到结果后再将此维度去掉,得到的与input的维度相同。
    #即使作扩充(广播)处理,input的维度也要和other维度做对应关系
    
    #y += torch.normal(0, 0.01, y.shape)
    #其中噪声项 ϵ  服从均值为0、标准差为0.01的正态分布。
    y += torch.tensor(np.random.normal(0, 0.01, size=y.size()), dtype=torch.float32)
    
    return X, y.reshape((-1, 1))

true_w = torch.tensor([2, -3.4])
true_b = 4.2
features, labels = synthetic_data(true_w, true_b, 1000)
print('features:', features[0], '\nlabel:', labels[0])

 输出

features: tensor([-0.7966, -0.0960]) 
label: tensor([2.9413])
d2l.set_figsize()
d2l.plt.scatter(features[:, (1)].detach().numpy(),
                labels.detach().numpy(), 1);

输出图片

================================补充================================

在后面课程使用

d2l.synthetic_data(true_w, true_b, 1000)

会报错如下:

TypeError                                 Traceback (most recent call last)
<ipython-input-2-296d220dc8b5> in <module>
      7 true_w = torch.tensor([2, -3.4])
      8 true_b = torch.tensor(4.2)
----> 9 features, labels = d2l.synthetic_data(true_w, true_b, 1000)
     10 #D:\Anaconda3\lib\site-packages\d2l\torch.py in synthetic_data(w, b, num_examples)
     11 #对代码进行了修改

D:\1learnsoft\2PyTorch\Anaconda3\lib\site-packages\d2l\torch.py in synthetic_data(w, b, num_examples)
    130     """Generate y = Xw + b + noise"""
    131     
--> 132     X = d2l.normal(0, 1, (num_examples, len(w)))
    133 
    134     y = d2l.matmul(X, w) + b

TypeError: normal() received an invalid combination of arguments - got (int, int, tuple), but expected one of:
 * (Tensor mean, Tensor std, torch.Generator generator, Tensor out)
 * (Tensor mean, float std, torch.Generator generator, Tensor out)
 * (float mean, Tensor std, torch.Generator generator, Tensor out)

按报错地址找到文件夹中的torch.py的synthetic_data(w, b, num_examples)函数
按照上面使用np.random.normal修改即可,如下:

def synthetic_data(w, b, num_examples):
    
    """Generate y = Xw + b + noise.由于pytorch版本使用的1.0故进行以下修改"""
    X = torch.tensor(np.random.normal(0, 1, size=(num_examples, len(w))), dtype=torch.float32)
	#X = d2l.normal(0, 1, (num_examples, len(w)))
	
    y = d2l.matmul(X, w) + b
	
    y += torch.tensor(np.random.normal(0, 0.01, size=y.size()), dtype=torch.float32)
	#y += d2l.normal(0, 0.01, y.shape)
	
    return X, d2l.reshape(y, (-1, 1))

补充错误:

TabError: inconsistent use of tabs and spaces in indentation

注:此错误表示你修改代码时缩进不一样,复制其余地方的缩进粘贴即可

================================结束================================

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐