Physics Informed Neural Network를 보다가 한가지 의문이 들었다.
Physics Informed Neural Network란 공학과 편미분 방정식과 초기조건, 경계조건이 주어졌을 때 인공신경망을 활용하여 이 편미분 방정식을 풀려는 접근법이다.
파이토치를 공부해본 사람들은 알겠지만
loss.backward()로 loss가 미분이 되서 오차역전파가 되는 것을 간접적으로나마 알 수 있을 것이다.
한가지 의문이 들었다.
어떤식이 주어졌다고 가정하자!
단순 x^2 +1이다.
이걸 x에 대해 미분하면 2x가 나온다.
어떻게 하면 좋을까?
이때 사용하는 것이
torch.autograd.grad()
이다!!
한번 사용해보자!
입력은 [1, 2, 3, 4]로 구성되어있는 어떤 텐서라고 생각하자.
x = torch.tensor([1, 2, 3, 4], requires_grad = True, dtype = torch.float64)
torch.Tensor()가 아닌 torch.tensor()로 정의해야 requires_grad를 편하게 정의할 수 있다.
x = torch.Tensor([1, 2, 3])
x.requires_grad_(True)
대문자로 하면 이렇게 정의해야 한다!
암튼 y도 정의해보자.
y = x**2 + 1
y를 출력하면 뭐가 나올지 감이 올것이다.(그렇다고 암산하지는 말고)
1^2+1= 2, 2^2+1 = 5, 3^2+1 = 10, 4^2+1 = 17 해서
tensor([ 2., 5., 10., 17.], dtype=torch.float64...)이 나온다.
자 이제 미분을 하고 x를 넣어보자!
d_x = torch.autograd.grad(y.sum(), x, create_graph=True)[0]
이렇게하면 된다!
y를 x에 대하여 미분한 다음 x를 집어 넣겠다는 뜻이다!
중요한 점은 y.sum()을 해야 된다!
저렇게 안하면 오류가 난다!
출처) https://rooney-song.tistory.com/5
d_x를 출력하면
tensor([2., 4., 6., 8.], dtype=torch.float64...)이 나온다!
x^2가 2x로 미분이 된다음 1, 2, 3, 4가 들어간것을 알 수 있다.
참고로 y.mean()을 하면 들어가는 인자가 4개라서 위의 값에서 각각 4로 나눠진 값이 나온다.
tensor([0.5, 1., 1.5, 4.], dtype=torch.float64...)가 나온다!
재밌는건 y.max()와 y.min()도 가능하다.
y.max()를 하면 tensor([0., 0., 0., 8.], dtype=torch.float64...)
y.min()를 하면 tensor([0.5, 0., 0., 0.], dtype=torch.float64...)이 나온다.
참도로 d_x를 한번더 미분할 수 있다!
d_xx = torch.autograd.grad(d_x.sum(), a, create_graph=True)[0]
이걸 출력하면 2x를 미분한 2만 나온다.(이때는 뭘넣어도 2만 나온다...)
tensor([2., 2., 2., 2.], dtype=torch.float64, ...)
+이런식으로도 미분값을 볼 수 있다.
a = torch.ones((2, 2), requires_grad = True) #미분이 가능한 경우
b = a+1
print(b)
b.sum().backward()
print(a.grad)
'''
b_x = torch.autograd.grad(b.sum(), a, create_graph=True)[0]
print(b_x)
'''
backward를 사용하면 미분이 가능해진다!
그다음 .grad를 통해 미분 값을 볼 수 있다.
a = torch.ones((2, 2), requires_grad = True) #미분이 가능한 경우
t = torch.ones((2, 2), requires_grad = True) #미분이 가능한 경우
b = a**2+t
print(b)
b.sum().backward()
print(a.grad)
print(t.grad)
다변수에 대해서도 할 수 있다!
a^2 + t라는 식이 있을 때
먼저 2라는 값이 나오는 것을 알 수 있다.
그 다음 backward로 미분을 수행한다.
마지막에 .grad를 출력하면 a에 대해서 미분, t에 대해서 미분한 값을 따로따로 볼 수 있다!
a에대한 미분 값은 2a라서 모두 2가 되며, t에대한 미분 값은 1이기 때문에 모두 1이 되는 것을 볼 수 있었다!
loss.backward로 오차 역전파를 만들어서
파라미터에 따른 오차의 gradient를 구한 다음, optimizer.step으로
각각의 파라미터에 대해
parameter = parameter - learning_rate * parameter.grad를 해주는 걸로 보인다.