"""
attribute = 속성. class의 맴버함수 but ()이 필요 없음
<tensor class>
1. .requires_grad : 이 attribute를 True 로 설정하면, 그 tensor에서 이뤄진 모든 연산들을 추적(track)하기 시작
2. .backward() : 호출하여 모든 변화도(gradient)를 자동으로 계산
3. .grad 속성: 이 Tensor의 변화도가 누적됨.
4. .detach() : Tensor가 기록을 추적하는 것을 중단하게 하려면
5. with torch.no_grad(): gradient는 필요없고, 메모리는 절약하고 싶고, 학습가능한 매개변수로 찾고 싶을때.
<Function class>
부호화(encode)하여 순환하지 않는 그래프(acyclic graph)를 생성
1. .grad_fn : Tensor 를 생성한 Function 을 참조
"""
pass
x = torch.ones(2, 2, requires_grad=True)
y = x + 4
print(y)
print(y.grad_fn)
tensor([[5., 5.],
[5., 5.]], grad_fn=<AddBackward0>)
<AddBackward0 object at 0x000001B1F842D2C8>
k = torch.tensor([[1,2],[3,4]], requires_grad=True, dtype = torch.double)
print(k*k)
tensor([[ 1., 4.],
[ 9., 16.]], dtype=torch.float64, grad_fn=<MulBackward0>)
print(y.requires_grad)
print(k.requires_grad_(False))
True
tensor([[1., 2.],
[3., 4.]], dtype=torch.float64)
x1 = torch.ones(2, 2, requires_grad=True)
x2 = x1 + 3
x3 = 3*(x2 ** 2)
out = torch.mean(x3)
out.backward()
print(x1.grad)
''' 위에꺼 주석하고 이것도 해보기.
x3.backward(torch.tensor([[1,1],[1,1]],dtype=torch.double)) # d_out/d_x1 = 3*2/4 ... = 3/2(x+3)|x = 1 = [[6,6],[6,6]]
print(x1.grad) # 생각해보면 d_Loss/d_x1를 이용해 x1을 갱신해야하므로, x1과 똑같은 size의 tensor가 print된다
'''
pass
tensor([[6., 6.],
[6., 6.]])
with torch.no_grad():
print((x1 ** 2).requires_grad)
False
print(x3.requires_grad)
y3 = x3.detach()
print(y3.requires_grad)
print(x3.eq(y3).all())
True
False
tensor(True)