딥 러 닝 프레임 워 크 PyTorch - 제3 장 Tensor 와 Autograd

23512 단어 PyTorch딥 러 닝
Tensor 
"""
Tensor    ,             ,     PyTorch    ,   Theano、TensorFlow、 Torch MxNet        。
              ,        ,             ,          。
       (  )、    (  )、    (  )       (    )。
Tensor Numpy ndarrays  , PyTorch tensor  GPU  。
"""

from __future__ import print_function
import torch as t

#torch   
print(t.__version__)

"""
3.1.1    
        , tensor        :

1.torch.function, torch.save 。
2.    tensor.function, tensor.view 。
     , tensor               ,          , torch.sum (torch.sum(a, b)) tensor.sum (a.sum(b))    。

         , tensor         :

         ,  a.add(b),             tensor。
        ,  a.add_(b),          a ,a    。
    _     inplace  ,             ,           
"""

"  Tensor"

a=t.Tensor(2,3)#  tensor   
print(a)#            ,print    overflow

b=t.Tensor([[1,2,3],[4,5,6]])# list     tensor
print(b)

print(b.tolist())# tensor  list

b_size=b.size()#tensor.size()  torch.Size  
print(b_size)

print(b.numel())#b       ,2*3,   b.nelement()

c=t.Tensor(b_size)#     b     tensor
d=t.Tensor((2,3))#      W 2 3 tensor
print(c,d)

#  tensor.size(),     tensor.shape    tensor   ,tensor.shape   tensor.size()
print(c.shape)

"""
      ,t.Tensor(*sizes)  tensor ,          ,
                ,   tensor     ,           tensor          。
"""

"       tensor   "
print(t.ones(2,3))
print(t.zeros(2,3))
print(t.arange(1,6,2).shape)
print(t.linspace(1,10,3))
print(t.randn(2,3,device=t.device('cpu')))
print(t.randperm(5))#   5     
print(t.eye(2,4,dtype=t.int))#    1,        


scalar=t.tensor(3.14159)
print('scalar: %s, shape of sclar: %s' %(scalar, scalar.shape))

vector=t.tensor([1,2])
print('vector: %s, shape of vector: %s' %(vector, vector.shape))

tensor = t.Tensor(1,2) #    t.tensor([1, 2])   
print(tensor.shape)

matrix = t.tensor([[0.1, 1.2], [2.2, 3.1], [4.9, 5.2]])
print(matrix,matrix.shape)

empty_tensor = t.tensor([])
print(empty_tensor.shape)


"""
  Tensor  
  tensor.view      tensor   ,               。
view         ,    tensor  tensor    ,         ,          。
                     ,   squeeze unsqueeze          。
"""

a=t.arange(0,6)
print(a.view(2,3))

b=a.view(-1,3)#     -1   ,         
print(b.size())

b.unsqueeze(1)#  ,       '1'(   0  )
print(b[:,None].shape)

b.unsqueeze(-2)#-2         
print(b[None,:].shape)

c=b.view(1,1,1,2,3)
print(c.squeeze(0))#   0  '1'

print(c.squeeze())#      ‘1’   

a[1]=100
print(b)# a  ,b  view   ,      

"""
resize         size   ,  view  ,     tensor   。
           ,           ,           ,            ,     
"""
print(b.resize_(1,3))
print(b.resize_(3,3))#        ,          

"""
    
"""

a=t.randn(3,4)
print(a)
print(a[0])# 0 (   0  )
print(a[:,0])# 0 
print(a[0][2])#  0  2   ,   a[0, 2]
print(a[:2])#   
print(a[:2,0:2])#    , 0,1 
print(a[0:1, :2]) #  0 ,   
print(a[0, :2]) #        :    

# None   np.newaxis,  a      
#    a.view(1, a.shape[0], a.shape[1])
print(a[None].shape)

print(a[:,None,:].shape)
print(a[:,None,None,:,None].shape)

"""
    
"""
x=t.arange(0,27).view(3,3,3)
print(x)
print(x[[1,2],[1,2],[2,0]])# x[1,1,2] x[2,2,0]
print(x[[2,1,0],[0],[1]])# x[2,0,1],x[1,0,1],x[0,0,1]
print(x[[0, 2], ...]) # x[0]   x[2]


"""

     
       tensor      (point-wise,  element-wise)    ,
              
"""
a = t.arange(0,6).view(2,3)
print("a:",a)
#print("t.cos(a):",t.cos(a))
print("a % 3:",a % 3)  # t.fmod(a, 3)
print("a ** 2:",a ** 2)  # t.pow(a, 2)
print("t.clamp(a, min=2, max=4)",t.clamp(a,min=2,max=4))
#  a        3        (  3    3)
print(a)
print(t.clamp(a, min=3))

#b=a.sin_()#     a = a.sin();b=a ,         
#print(b)


"""
    
                ,               。
   sum,       tensor  ,     tensor          
             dim,                  。  dim(   Numpy  axis)       ,             :

        (m, n, k)

    dim=0,       (1, n, k)  (n, k)
    dim=1,       (m, 1, k)  (m, k)
    dim=2,       (m, n, 1)  (m, n)
size    "1",     keepdim,keepdim=True     1。  ,        ,                 , cumsum。
"""
b = t.ones(2,3)
print("b.sum():",b.sum(dim=0,keepdim=True))
print("b.sum():",b.sum(dim=0,keepdim=False))# keepdim=False,     "1",    

a = t.arange(0, 6).view(2, 3)
print(a)
print(a.cumsum(dim=1)) #      

"""
  
              ,          ,            
t.max(tensor):  tensor       
t.max(tensor,dim):        ,  tensor   
t.max(tensor1, tensor2):     tensor       

"""
a = t.linspace(0, 15, 6).view(2, 3)
b = t.linspace(15, 0, 6).view(2, 3)
print(a>b)
print(a[a>b])
print(t.max(a))
print(t.max(b,dim=1))
#        15 6     0   1      
#        0 0            0   
print(t.max(a,b))
print(t.clamp(a,min=10))#   a 10     


"""
    
trace:       (    )
diag:     
triu/tril:      /   
mm/bmm:    ,batch     
t:  
dot/cross:  /  
inverse:    
svd:     
"""
b=a.t()
print(b.is_contiguous())#               ,     .contiguous        
print(b.contiguous())



"""
Tensor Numpy
Tensor Numpy            ,                。
      ,Numpy Tensor    。
  Numpy    ,       ,
     Tensor       ,    Numpy  ,      tensor,       
"""
import numpy as np

a=np.ones([2,3],dtype=np.float32)
print(a)

b=t.from_numpy(a)
print(b)

b=t.Tensor(a)#      numpy    Tensor
print(b)

a[0][1]=100
print(b)

c=b.numpy()#a,b,c        
print(c)# numpy      Tensor         ,      ,      

a=np.ones([2,3])
print(a.dtype)#      a   (dtype  float32)

b=t.Tensor(a)#      ,     
print(b.dtype)

c=t.from_numpy(a)#  c   (DoubleTensor)
print(c)

a[0,1]=100
print(b,c)#b a     ,c a    

#          ,t.tensor        ,      
tensor=t.tensor(a)
tensor[0,0]=2
print(a)


"""
    (broadcast)               ,                     /  。 Numpy         :

1.           shape       ,shape            1  
2.                 ,       1,      
3.              1 ,                 
PyTorch             ,                             ,     ,     :

1.unsqueeze  view,  tensor[None],:          1,    1
2.expand  expand_as,    ,    3;         ,           。
"""

a=t.ones(3,2)
b=t.zeros(2,3,1)
#       
#    a 2 ,b 3 ,       a   1 ,
#  :a.unsqueeze(0),a     (1,3,2),b    (2,3,1),
#    :a b             ,     1 ,
#           ,        (2,3,2)
print(a+b)


#      
print(a.view(1,3,2).expand(2,3,2)+b.expand(2,3,2))

e=a.unsqueeze(0).expand(1000000,3,2)
print(e)


"""
    
tensor      (Tensor)    (Storage),
        tensor   (size)、  (stride)、    (type)   ,
              。
          ,             ,
          tensor      ,        。
"""

a=t.arange(0,6)
print(a.storage())

b=a.view(2,3)
print(b.storage())

#      id             
# storage       ,     storage
print(id(b.storage()) == id(a.storage()))

a[1]=100
print(b)#a  ,b     ,      storage

c=a[2:]
print(c.storage())

#data_ptr  tensor        
print(c.data_ptr(),a.data_ptr())

"""
    Tensor   
"""

"GPU/CPU"
#tensor       gpu/cpu   。
#   tensor.cuda(device_id)  tensor.cpu()。
#            tensor.to(device)"
a=t.randn(3,4)
print(a.device)


"""
    :

             ,      。
               ,                       ,
      y = wx+b+e,e        0     。
             w b        ,    w b   。
"""

import torch as t
from matplotlib import pyplot as plt
from IPython import display

device = t.device('cpu')

#        ,                  
t.manual_seed(1000)

def get_fake_data(batch_size=8):
    '''       :y=x*2+3,       '''
    x = t.rand(batch_size, 1, device=device) * 5
    y = x * 2 + 3 +  t.randn(batch_size, 1, device=device)
    return x, y
#       x-y  
x, y = get_fake_data(batch_size=16)
plt.scatter(x.squeeze().cpu().numpy(), y.squeeze().cpu().numpy())

#        
w = t.rand(1, 1).to(device)
b = t.zeros(1, 1).to(device)

lr = 0.001  #    

for ii in range(2000):  # 2000   
    x, y = get_fake_data()  #     

    #     forward,  loss
    y_pred = x.mm(w) + b.expand_as(y)
    loss = 0.5 * (y_pred - y) ** 2  #      loss
    loss = loss.sum()

    # backward:      
    dloss = 1
    dy_pred = dloss * (y_pred - y)

    dw = x.t().mm(dy_pred)
    db = dy_pred.sum()

    #     
    w.sub_(lr * dw)
    b.sub_(lr * db)

    if ii % 1000 == 0:  #  1000   ,    
        #   
        display.clear_output(wait=True)
        x = t.arange(0, 20).view(-1, 1).float()
        y = x.mm(w) + b.expand_as(x)
        plt.plot(x.numpy(), y.numpy())  #   

        x2, y2 = get_fake_data(batch_size=20)
        plt.scatter(x2.numpy(), y2.numpy())

        plt.xlim(0, 20)
        plt.ylim(0, 41)
        plt.show()
        plt.pause(0.5)

print(w.squeeze(), b.squeeze())

Autograd 
from __future__ import print_function
import torch as t
#  tensor     requires_grad
a=t.randn(3,4,requires_grad=True)
print(a)

b=t.zeros(3,4).requires_grad_()
print(b)

c=a.add(b)
print(c)

d=c.sum()
d.backward()#     

print(d)
print(d.requires_grad)

print(a.grad)

#         c    , c   a, a    ,
#   c requires_grad       True
print(a.requires_grad, b.requires_grad, c.requires_grad)

print(a.is_leaf,b.is_leaf,c.is_leaf)


"""
  y=x^2*e^x   
autograd                 
"""
def f(x):
    '  y'
    y=x**2*t.exp(x)
    return y

def gradf(x):
    '     '
    dx=2*x*t.exp(x)+x**2*t.exp(x)
    return dx

x=t.randn(3,4,requires_grad=True)
y=f(x)
print(y)

y.backward(t.ones(y.size()))#gradient   y  
print(x.grad)
# autograd                   
print(gradf(x))


"""
   
"""
x=t.ones(1)
b=t.rand(1,requires_grad=True)
w=t.rand(1,requires_grad=True)
y=w*x#   y=w.mul(x)
z=y+b#   z=y.add(b)

print(x.requires_grad,b.requires_grad,w.requires_grad)

#      y.requires_grad True,   y        w
#   y.requires_grad True
print(y.requires_grad)

# grad_fn      variable       ,
# z add     ,           AddBackward
print(z.grad_fn)

# next_functions  grad_fn   ,   tuple,tuple     Function
#     y,    (mul)   ,           y.grad_fn MulBackward
#     b,      ,     ,grad_fn None,   
print(z.grad_fn.next_functions)

# variable grad_fn       function   
print(z.grad_fn.next_functions[0][0] == y.grad_fn)

#     w,    ,    ,      
#     x,    ,     ,   None
print(y.grad_fn.next_functions)

#      grad_fn None
print(w.grad_fn,x.grad_fn)

"""
  w      ,    x   ,              buffer,             。
              retain_graph     buffer。
"""
#  retain_graph   buffer
print(z.backward(retain_graph=True))
print(w.grad)

#      ,    ,    w AccumulateGrad     
z.backward()
print(w.grad)

"""
PyTorch       ,                     ,       Python    ( for、if )         。
               ,                       ,        
"""

def abs(x):
    if x.data[0]>0:
        return x
    else:
        return -x
x=t.ones(1,requires_grad=True)
y=abs(x)
y.backward()
print(x.grad)

x=-1*t.ones(1)
x=x.requires_grad_()
y=abs(x)
y.backward()
print(x.grad)


def f2(x):
    result=1
    for li in x:
        if li.item()>0:
            result=li*result
    return result

x=t.arange(-2.0,4.0,requires_grad=True)
y=f2(x)#y=x[3]*x[4]*x[5]
y.backward()
print(x.grad)

"""
   requires_grad     False,       requires_grad    True,
          requires_grad  True。
           autograd tensor  。
              ,       /    ,            。
            ( inference,      ),                  ,        ,             。
"""

x=t.ones(1,requires_grad=True)
w=t.rand(1,requires_grad=True)
y=x*w
#y   w, w.requires_grad = True
print(x.requires_grad,w.requires_grad,y.requires_grad)

with t.no_grad():
    x=t.ones(1)
    w=t.rand(1,requires_grad=True)
    y=x*w
# y   w x,  w.requires_grad = True,  y requires_grad   False
print(x.requires_grad, w.requires_grad, y.requires_grad)

t.set_grad_enabled(False)
X=t.ones(1)
w=t.rand(1,requires_grad=True)
y=x*w
# y   w x,  w.requires_grad = True,  y requires_grad   False
print(x.requires_grad, w.requires_grad, y.requires_grad)

"""
        tensor   ,       autogard  ,
       tensor.data      tensor.detach()
"""
a = t.ones(3,4,requires_grad=True)
b = t.ones(3,4,requires_grad=True)
c = a * b

print(a.data)#     tensor
print(a.data.requires_grad) #              

#     tensor=a.data,     tensor   ,backward     
tensor = a.detach()
print(tensor.requires_grad)

또한, variable 에 대한 조작 만 autograd 를 사용 할 수 있 으 며, variable 의 data 를 직접 조작 하면 역방향 전 파 를 사용 할 수 없습니다.매개 변수 초기 화 를 제외 하고, 일반적으로 우 리 는 variable. data 의 값 을 수정 하지 않 습 니 다.
PyTorch 에서 계산 그림 의 특징 은 다음 과 같다.
autograd 는 사용자 가 variable 에 대한 조작 에 따라 계산 도 를 구축 합 니 다.변수 에 대한 조작 은 Function 으로 추상 화 됩 니 다.함수 (Function) 가 아 닌 출력 에 대해 사용자 가 만 든 노드 를 잎 노드, 잎 노드 의 grad 라 고 합 니 다.fn 은 None 입 니 다.잎 노드 에 가이드 가 필요 한 variable 은 Accumulated Grad 표 지 를 가지 고 있 는데 그 경사도 가 누적 되 기 때문이다.variable 기본 값 은 가이드 가 필요 없 는, 즉 requires 입 니 다.grad 속성 은 기본적으로 False 입 니 다. 한 노드 requiresgrad 가 True 로 설정 되 어 있 으 면 모든 의존 노드 requiresgrad 는 모두 True 입 니 다.variable 의 volatile 속성 은 기본적으로 False 입 니 다. 만약 에 어떤 variable 의 volatile 속성 이 True 로 설정 된다 면 모든 의존 노드 의 volatile 속성 은 True 입 니 다.volatile 속성 은 True 의 노드 가 가이드 하지 않 습 니 다. volatile 의 우선 순위 비 requiresgrad 높다.여러 차례 역방향 으로 전 파 될 때, 경사도 는 누적 된다.역방향 으로 전 파 된 중간 캐 시 는 비 워 집 니 다. 여러 번 역방향 전 파 를 하기 위해 retain 을 지정 해 야 합 니 다.graph = True 는 이 캐 시 를 저장 합 니 다.비 잎 노드 의 경사도 계산 이 끝나 면 비 워 집 니 다. autograd. grad 또는 hook 기술 로 비 잎 노드 의 값 을 얻 을 수 있 습 니 다.variable 의 grad 는 data 모양 과 일치 하 므 로 variable. data 를 직접 수정 하 는 것 을 피해 야 합 니 다. data 에 대한 직접 조작 은 autograd 를 이용 하여 역방향 전파 함수 backward 의 매개 변수 grad 를 할 수 없 기 때 문 입 니 다.variables 는 체인 가이드 의 중간 결과 로 볼 수 있 습 니 다. 스칼라 라면 생략 할 수 있 습 니 다. 기본 값 은 1 PyTorch 로 동적 그림 디자인 을 사용 하여 중간 층 의 출력, 동적 인 디자인 계산 도 구 조 를 편리 하 게 볼 수 있 습 니 다.
확장 autograd
현재 절대 다수의 함 수 는 모두 autograd 를 사용 하여 역방향 구 도 를 실현 할 수 있 지만, 만약 자신 이 복잡 한 함 수 를 써 야 한다 면 자동 역방향 구 도 를 지원 하지 않 으 면 어떻게 합 니까?Function 을 써 서 전방 향 전파 와 역방향 전파 코드 를 실현 하고 Function 계산 그림 의 사각형 에 대응 하 며 파 라 메 터 를 받 아 계산 하고 결 과 를 되 돌려 줍 니 다.다음은 예 를 들 어 보 겠 습 니 다.
class Mul(Function):
                                                            
    @staticmethod
    def forward(ctx, w, x, b, x_requires_grad = True):
        ctx.x_requires_grad = x_requires_grad
        ctx.save_for_backward(w,x)
        output = w * x + b
        return output
        
    @staticmethod
    def backward(ctx, grad_output):
        w,x = ctx.saved_variables
        grad_w = grad_output * x
        if ctx.x_requires_grad:
            grad_x = grad_output * w
        else:
            grad_x = None
        grad_b = grad_output * 1
        return grad_w, grad_x, grad_b, None

분석 은 다음 과 같다.
사용자 정의 Function 은 autograd. Function 을 계승 해 야 합 니 다. 구조 함수 가 없습니다.init__,forward 와 backward 함 수 는 모두 정적 방법 forward 함수 의 입력 과 출력 은 모두 Tensor 이 고 backward 함수 의 입력 과 출력 은 모두 Variable backward 함수 의 출력 과 forward 함수 의 입력 이 일일이 대응 하 며 backward 함수 의 입력 과 forward 함수 의 출력 은 각각 backward 함수 에 대응 하 는 grad 입 니 다.output 매개 변 수 는 t. autograd. backward 의 grad 입 니 다.variables 만약 에 어떤 입력 이 가이드 가 필요 하지 않 으 면 None 로 돌아 갑 니 다. 예 를 들 어 forward 의 입력 매개 변수 xrequires_grad 는 이 를 유도 할 수 없 음 이 분명 합 니 다. None 로 돌아 가면 역방향 으로 전 파 될 수 있 습 니 다. 전방 향 전파 의 일부 중간 결 과 를 이용 하여 저장 해 야 합 니 다. 그렇지 않 으 면 전방 향 전파 가 끝 난 후에 이 대상 들 은 Function 의 사용 을 이용 하여 Function. application (variable) 을 사용 합 니 다.
from torch.autograd import Function
class MultiplyAdd(Function):
                                                            
    @staticmethod
    def forward(ctx, w, x, b):                              
        print('type in forward',type(x))
        ctx.save_for_backward(w,x)
        output = w * x + b
        return output
        
    @staticmethod
    def backward(ctx, grad_output):                         
        w,x = ctx.saved_variables
        print('type in backward',type(x))
        grad_w = grad_output * x
        grad_x = grad_output * w
        grad_b = grad_output * 1
        return grad_w, grad_x, grad_b
x = V(t.ones(1))
w = V(t.rand(1), requires_grad = True)
b = V(t.rand(1), requires_grad = True)
print('      ')
z=MultiplyAdd.apply(w, x, b)
print('      ')
z.backward() #   

# x     ,             ,      
x.grad, w.grad, b.grad

 
      
type in forward 
      
type in backward 
(None, tensor([1.]), tensor([1.]))
x = V(t.ones(1))
w = V(t.rand(1), requires_grad = True)
b = V(t.rand(1), requires_grad = True)
print('      ')
z=MultiplyAdd.apply(w,x,b)
print('      ')

#   MultiplyAdd.backward
#   grad_w, grad_x, grad_b
z.grad_fn.apply(V(t.ones(1)))
      
type in forward 
      
type in backward 
(tensor([1.]), tensor([0.0806], grad_fn=), tensor([1.]))

forward 함수 의 입력 은 tensor 이 고 backward 함수 의 입력 은 variable 이 며 고급 구 도 를 실현 하기 위해 서 입 니 다.backward 함수 의 입 출력 은 variable 이지 만 실제 사용 할 때 autograd. Function 은 입력 variable 를 tensor 로 추출 하고 결 과 를 계산 하 는 tensor 를 variable 로 봉 하여 되 돌려 줍 니 다.backward 함수 에서 도 variable 를 조작 해 야 하 는 이 유 는 경사도 의 경사도 (backward of backward) 를 계산 할 수 있 기 위해 서 입 니 다.다음 예 를 들 어 torch. autograd 에 대한 자세 한 사용 은 문 서 를 참조 하 십시오.
x = V(t.Tensor([5]), requires_grad=True)
y = x ** 2
grad_x = t.autograd.grad(y, x, create_graph=True)
grad_x # dy/dx = 2 * x
(tensor([10.], grad_fn=),)
grad_grad_x = t.autograd.grad(grad_x[0],x)
grad_grad_x #      d(2x)/dx = 2
(tensor([2.]),)

이러한 디자인 은 autograd 로 하여 금 고급 가이드 기능 을 가지 게 할 수 있 지만 Tensor 의 사용 도 제한 합 니 다. autograd 에서 역방향 으로 전 파 된 함 수 는 현재 있 는 Variable 작업 만 이용 할 수 있 기 때 문 입 니 다.이 디자인 은 0.2 버 전에 새로 추 가 된 것 으로 유연성 을 높이 고 기 존 버 전의 코드 를 호 환 하기 위해 PyTorch 는 또 다른 autograd 를 확장 하 는 방법 도 제공 했다.PyTorch 는 장식 기 를 제공 합 니 다 @ oncedifferentiable, backward 함수 에서 입력 한 variable 을 tensor 로 자동 으로 추출 하여 결 과 를 계산 하 는 tensor 를 자동 으로 variable 로 밀봉 할 수 있 습 니 다.이 기능 이 있 으 면 우 리 는 numpy / scipy 의 함 수 를 편리 하 게 사용 할 수 있 습 니 다. 조작 은 variable 가 지원 하 는 조작 에 국한 되 지 않 습 니 다.그러나 이런 방법 은 이름 에서 암시 한 바 와 같이 한 번 만 유도 할 수 있 고 역방향 전파 도 를 끊 어 더 이상 고급 구 도 를 지원 하지 않 는 다.
위 에서 묘사 한 것 은 모두 신식 Function 이 고 레 거 시 Function 도 있 습 니 다. 를 가 질 수 있 습 니 다.init__방법, forward 와 backwad 함수 도 @ staticmethod 라 고 설명 할 필요 가 없 지만 버 전이 바 뀌 면서 이러한 Function 은 점점 적어 질 것 입 니 다. 더 이상 소개 하지 않 습 니 다.
또한 자신의 Function 을 실현 한 후에 gradcheck 함 수 를 사용 하여 실현 이 정확 한 지 확인 할 수 있 습 니 다.gradcheck 은 수치 접근 을 통 해 경사도 를 계산 할 수 있 으 며, 일정한 오차 가 있 을 수 있 으 며, eps 의 크기 를 제어 하여 용인 하 는 오 차 를 제어 할 수 있 습 니 다.
이 부분 에 대한 내용 은 github 에서 개발 자 들 의 토론 을 참고 할 수 있 습 니 다 [2].
다음은 Function 을 어떻게 이용 하여 sigmoid Function 을 실현 하 는 지 예 를 들 어 설명 한다. 
class Sigmoid(Function):
                                                             
    @staticmethod
    def forward(ctx, x): 
        output = 1 / (1 + t.exp(-x))
        ctx.save_for_backward(output)
        return output
        
    @staticmethod
    def backward(ctx, grad_output): 
        output,  = ctx.saved_variables
        grad_x = output * (1 - output) * grad_output
        return grad_x
#                     
test_input = V(t.randn(3,4), requires_grad=True)
t.autograd.gradcheck(Sigmoid.apply, (test_input,), eps=1e-3)
True
def f_sigmoid(x):
    y = Sigmoid.apply(x)
    y.backward(t.ones(x.size()))
    
def f_naive(x):
    y =  1/(1 + t.exp(-x))
    y.backward(t.ones(x.size()))
    
def f_th(x):
    y = t.sigmoid(x)
    y.backward(t.ones(x.size()))
    
x=V(t.randn(100, 100), requires_grad=True)
%timeit -n 100 f_sigmoid(x)
%timeit -n 100 f_naive(x)
%timeit -n 100 f_th(x)
E:\Anaconda\lib\site-packages\ipykernel_launcher.py:11: DeprecationWarning: 'saved_variables' is deprecated; use 'saved_tensors'
  # This is added back by InteractiveShellApp.init_path()


The slowest run took 4.77 times longer than the fastest. This could mean that an intermediate result is being cached.
501 µs ± 412 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
357 µs ± 123 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
The slowest run took 4.84 times longer than the fastest. This could mean that an intermediate result is being cached.
353 µs ± 286 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

분명히 f_sigmoid 단순 이용 autograd 의 가감 과 곱셈 조작 으로 이 루어 진 함수 보다 훨씬 빠르다. 왜냐하면 fsigmoid 의 backward 는 역방향 전파 과정 을 최적화 시 켰 다.또한 시스템 구현 buildin 인터페이스 (t. sigmoid) 가 더 빠 른 것 으로 나 타 났 다. 
 
"""
                         。           ,     :

  autograd.grad  
  hook
autograd.grad hook          ,          api  ,           。
    hook  ,               grad  。
"""

x = t.ones(3, requires_grad=True)
w = t.rand(3, requires_grad=True)
y = x * w
# y   w, w.requires_grad = True
z = y.sum()
print(x.requires_grad, w.requires_grad, y.requires_grad)

z.backward()
print(x.grad, w.grad, y.grad)

#      :  grad         
x = t.ones(3, requires_grad=True)
w = t.rand(3, requires_grad=True)
y = x * w
z = y.sum()
# z y   ,    backward()
print(t.autograd.grad(z, y))

#      :  hook
# hook     ,     ,       
def variable_hook(grad):
    print('y   :',grad)

x = t.ones(3, requires_grad=True)
w = t.rand(3, requires_grad=True)
y = x * w
#   hook
hook_handle = y.register_hook(variable_hook)
z = y.sum()
z.backward()

#         hook,          hook
hook_handle.remove()
"""
 Variable      
"""
import torch as t
from matplotlib import pyplot as plt
from IPython import display
import numpy as np

#        ,                   
t.manual_seed(1000)

def get_fake_data(batch_size=8):
    '''       :y = x*2 + 3,       '''
    x = t.rand(batch_size,1) * 5
    y = x * 2 + 3 + t.randn(batch_size, 1)
    return x, y

#      x-y       
x, y = get_fake_data()
plt.scatter(x.squeeze().numpy(), y.squeeze().numpy())

#        
w = t.rand(1, 1, requires_grad=True)
b = t.zeros(1, 1, requires_grad=True)
losses = np.zeros(500)

lr = 0.005  #    

for ii in range(500):
    x, y = get_fake_data(batch_size=32)

    # forward:  loss
    y_pred = x.mm(w) + b.expand_as(y)
    loss = 0.5 * (y_pred - y) ** 2
    loss = loss.sum()
    losses[ii] = loss.item()

    # backward:      
    loss.backward()

    #     
    w.data.sub_(lr * w.grad.data)
    b.data.sub_(lr * b.grad.data)

    #     
    w.grad.data.zero_()
    b.grad.data.zero_()

    if ii % 50 == 0:
        #   
        display.clear_output(wait=True)
        x = t.arange(0, 6).view(-1, 1).float()
        y = x.mm(w.data) + b.data.expand_as(x)
        plt.plot(x.numpy(), y.numpy())  # predicted

        x2, y2 = get_fake_data(batch_size=20)
        plt.scatter(x2.numpy(), y2.numpy())  # true data

        plt.xlim(0, 5)
        plt.ylim(0, 13)
        plt.show()
        plt.pause(0.5)

print(w.item(), b.item())

plt.plot(losses)
plt.ylim(5,50)

https://github.com/chenyuntc/pytorch-book/blob/master/chapter3-Tensor%E5%92%8Cautograd/Autograd.ipynb
https://blog.csdn.net/V_lq6h/article/details/88320308

좋은 웹페이지 즐겨찾기