pytorch:
注意点:
必须知道的python赋值:万物皆对象,本质是引用(指针)
python中变量(名)与数据分离存储,对变量名的调用,例如:a=1
然后print(a)
,print(a)
实际是先引用数据存储的位置,然后再打印。因此可以简单理解为a和数字1都是对象,1赋值给a则是将地址赋给a。具体可看本站该篇博客 python
说明:无论是浅拷贝还是深拷贝都会生成对象,区别只是对象指向的数据区域是同一块还是重新开辟一块。
计算图:(待写):
计算图的代码实现涉及深拷贝与浅拷贝。(待写)
深拷贝与浅拷贝以及原地操作(inplace):
浅拷贝:即只是指向同一个地址,而不开辟新空间。看是否是浅拷贝,最直观的就是看数据是否一起变化。
1.=
赋值相当于是引用(指针)。
import torch
a = torch.tensor([1,2,3])
a_pre_id = id(a)
b = a
b_pre_id = id(b)
print("a:",a,"a的id:",a_pre_id," b:",b,"b的id:",b_pre_id)
print("a和b的地址是否相同:",a_pre_id ==b_pre_id)
a +=1
a_after_id = id(a)
b_after_id = id(b)
print("~~~~~~~~~~~对a进行操作后~~~~~~~~~~~~~")
print("a:",a,"a的id:",a_after_id," b:",b,"b的id:",b_after_id)
print("a和b的地址是否相同:",a_after_id ==b_after_id)
#结果中将会看到a和b一起变化
a: tensor([1, 2, 3]) a的id: 2341125996856 b: tensor([1, 2, 3]) b的id: 2341125996856
a和b的地址是否相同: True
~~~~~~~~~~~对a进行操作后~~~~~~~~~~~~~
a: tensor([2, 3, 4]) a的id: 2341125996856 b: tensor([2, 3, 4]) b的id: 2341125996856
a和b的地址是否相同: True
2..numpy()
import torch
a = torch.tensor([1,2,3]) #生成tensor对象
a_pre_id = id(a) #a的id
b = a.numpy() #tensor的numpy地址
b_pre_id = id(b) #b的id
print("a:",a,"a的id:",a_pre_id,"\nb:",b,"\t b的id:",b_pre_id)
print("a和b的地址是否相同:",id(a)==id(b))
print("~~~~~~~~~~~对b进行操作后~~~~~~~~~~~~~")
b += 100
a_after_id = id(a)
b_after_id = id(b)
print("a:",a,"a的id:",a_after_id,"\nb:",b,"\t b的id:",b_after_id)
print("a和b的地址是否相同:",a_after_id == b_after_id)
print("b自加后地址无变化变化:",b_after_id == b_pre_id)
print("b_pre_id: ",b_pre_id)
print("b_after_id:",b_after_id)
a: tensor([1, 2, 3]) a的id: 2341139225080
b: [1 2 3] b的id: 2341151747648
a和b的地址是否相同: False
~~~~~~~~~~~对a进行操作后~~~~~~~~~~~~~
a: tensor([101, 102, 103]) a的id: 2341139225080
b: [101 102 103] b的id: 2341151747648
a和b的地址是否相同: False
b自加后地址无变化变化: True
b_pre_id: 2341151747648
b_after_id: 2341151747648
小结:虽然a和b指向不同的地址,但是由于是浅拷贝,.numpy()
所生成的对象,仍然指向a对应tensor
的地址。
3.view()
import torch
a = torch.tensor([1,2,3]) #生成tensor对象
a_pre_id = id(a) #a的id
b = a.view(3,1) #tensor的view地址
b_pre_id = id(b) #b的id
print("a:",a,"a的id:",a_pre_id,"\nb:",b,"\t b的id:",b_pre_id)
print("a和b的地址是否相同:",id(a)==id(b))
print("~~~~~~~~~~~对b进行操作后~~~~~~~~~~~~~")
b += 100
a_after_id = id(a)
b_after_id = id(b)
print("a:",a,"a的id:",a_after_id,"\nb:",b,"\t b的id:",b_after_id)
print("a和b的地址是否相同:",a_after_id == b_after_id)
print("b自加后地址无变化变化:",b_after_id == b_pre_id)
print("b_pre_id: ",b_pre_id)
print("b_after_id:",b_after_id)
a: tensor([1, 2, 3]) a的id: 2341151744072
b: tensor([[1],
[2],
[3]]) b的id: 2341139860280
a和b的地址是否相同: False
~~~~~~~~~~~对a进行操作后~~~~~~~~~~~~~
a: tensor([101, 102, 103]) a的id: 2341151744072
b: tensor([[101],
[102],
[103]]) b的id: 2341139860280
a和b的地址是否相同: False
b自加后地址无变化变化: True
b_pre_id: 2341139860280
b_after_id: 2341139860280
小结:同.numpy
类似,view
生成的对象所指向的位置也是tensor
对象的地址,但是id不同,因为view也
产生一个对象。以下不复赘述和演示,同理。
4.reshape
5.索引 Y=X[:]
6.torch.from_numpy()
7.torch.detach()
*****8.model:forward()
通过写forward方法可以知道,里边会用到赋值=
,而这些一般都是浅拷贝。但是torch.nn
的“层(layer)”则是深拷贝,但是接受通过参数inplace
的指定是否原地操作来执行浅拷贝,例如:torch.nn.ReLu(inplace)
。
inplace作用:
1.减少内存占用
9.copy.copy():
要先导入包:import copy
10.model.state_dict()
11..……
深拷贝:即全部数据复制一遍,开辟一个新空间
1.torch.clone()
import torch
x = torch.tensor([1,2,3])
y = torch.clone(x)
before_x = id(x)
before_y = id(y)
y+=100
print(x,y)
print("before_x id:",before_x)
print("before_y id:",before_y)
print("after_y id: ",id(y))
tensor([1, 2, 3]) tensor([101, 102, 103])
before_x id: 2341169802200
before_y id: 2341166594552
after_y id: 2341166594552
小结:深度拷贝会把数据也拷贝一份。以下同理,不复赘述和实验