Quiz-8 (2026.04.01) // 범위: ~04wk
1. 파이토치를 이용한 미분
(1) 다음 함수 \(f(x_1, x_2) = (x_1 + 3x_2)^2\) 에 대하여 \(\frac{\partial}{\partial x_1}f(x_1,x_2) \Big|_{x_1=1.5,x_2=2.0}\) 과 \(\frac{\partial}{\partial x_2}f(x_1,x_2) \Big|_{x_1=1.5,x_2=2.0}\) 을 계산하려고 한다. 다음 중 올바른 코드를 모두 고르시오.
(a)
x1 = torch.tensor(1.5, requires_grad=True)
x2 = torch.tensor(2.0, requires_grad=True)
y = (x1 + 3*x2)**2
y.backward()
x1.grad, x2.grad(b)
x = torch.tensor([[1.5],[2.0]], requires_grad=True)
y = (torch.tensor([[1.0, 3.0]]) @ x)**2
y.backward()
x.grad(c)
def f(x1, x2):
return (x1 + 3*x2)**2
x1 = torch.tensor(1.5, requires_grad=True)
x2 = torch.tensor(2.0, requires_grad=True)
y = f(x1, x2)
y.backward()
x1.grad, x2.grad(d)
x1 = torch.tensor(1.5)
x2 = torch.tensor(2.0)
y = (x1 + 3*x2)**2
y.backward()
x1.grad, x2.grad정답: (a), (b), (c) // (d)는 requires_grad=True를 쓰지 않아서 틀렸음.
(2) 다음 코드들 중 \(z = 3(x+2)^2\) 에서 \(\frac{dz}{dx}\Big|_{x=4}\) 를 올바르게 계산하는 코드를 모두 고르시오.
(a)
x = torch.tensor(4.0, requires_grad=True)
y = (x + 2)**2
z = 3 * y
z.backward()
x.grad(b)
x = torch.tensor(4.0, requires_grad=True)
z = 3 * (x + 2)**2
z.backward()
x.grad(c)
x = torch.tensor(4.0, requires_grad=True)
y = x + 2
z = 3 * y**2
y.backward()
x.grad(d)
x = torch.tensor(4.0, requires_grad=True)
y = (x + 2)**2
z = 3 * y
y.backward()
x.grad정답: (a), (b) // (c),(d)가 오답인 이유는 y를 x로 미분하였기 때문.
2. 코드 오류 찾기
(1) 다음 코드는 \(f'(3)\)과 \(f'(5)\)를 계산하려는 코드이다. 코드의 문제점을 설명하라.
def f(x):
return x**2
x = torch.tensor(3.0, requires_grad=True)
y = x**2
y.backward()
print(f"f'(3) = {x.grad}")
x.data = torch.tensor(5.0)
y = x**2
y.backward()
print(f"f'(5) = {x.grad}")gradient 값을 초기화 하지 않음.
(2) 다음 코드는 회귀분석에서 \(\hat{\bf w}\) 을 경사하강법으로 구하는 코드이다. 코드의 문제점을 설명하라.
torch.manual_seed(43052)
x = torch.randn(100).sort()[0]
eps = torch.randn(100)*0.5
w0ast = 2.5
w1ast = 4
y = w0ast + w1ast*x + eps
#---#
Y = y.reshape(-1,1)
X = torch.stack([torch.ones(100), x], axis=1)
What = torch.tensor([[-5.00],[10.00]], requires_grad=True)
#---#
for epoch in range(30):
Yhat = X @ What
loss = torch.mean((Y - Yhat)**2)
loss.backward()
What.data = What.data - 0.1 * What.gradgradient 값을 초기화 하지 않음.
(3) 다음 코드는 회귀분석에서 파라미터를 업데이트하는 코드이다. 코드의 문제점을 설명하라.
torch.manual_seed(43052)
x = torch.randn(100).sort()[0]
eps = torch.randn(100)*0.5
w0ast = 2.5
w1ast = 4
y = w0ast + w1ast*x + eps
#---#
Y = y.reshape(-1,1)
X = torch.stack([torch.ones(100), x], axis=1)
net = torch.nn.Linear(in_features=2, out_features=1, bias=False)
net.weight.data = torch.tensor([[-5.00],[10.00]])
loss_fn = torch.nn.MSELoss()
optimizer = torch.optim.SGD(net.parameters(), lr=0.1)
#---#
for epoch in range(30):
Yhat = net(X)
loss = loss_fn(Yhat, Y)
loss.backward()
optimizer.step()gradient 값을 초기화 하지 않음.
3. 똑같은 코드 찾기 (\(\star\))
아래 문제에서 사용되는 데이터 및 기준 코드는 04wk 강의노트의 (5.회귀분석-C)를 따른다:
# 데이터
torch.manual_seed(43052)
x = torch.randn(100).sort()[0]
eps = torch.randn(100)*0.5
w0ast = 2.5
w1ast = 4
y = w0ast + w1ast*x + eps
Y = y.reshape(-1,1)
X = torch.stack([torch.ones(100), x], axis=1)
X1 = x.reshape(-1,1)
# 풀이2
w0hat = torch.tensor(-5.00, requires_grad=True)
w1hat = torch.tensor(10.00, requires_grad=True)
for epoch in range(30):
yhat = w0hat + w1hat*x
loss = torch.sum((y - yhat)**2)
loss.backward()
w0hat.data = w0hat.data - 0.001 * w0hat.grad
w1hat.data = w1hat.data - 0.001 * w1hat.grad
w0hat.grad = None
w1hat.grad = None아래 각 문항의 코드가 위의 코드와 같은 결과를 출력하도록 물음표(???)를 채우시오.
(1)
What = torch.tensor([[-5.00],[10.00]], requires_grad=True)
#---#
for epoch in range(30):
???
loss = torch.sum((Y - Yhat)**2)
loss.backward()
???
What.grad = NoneWhat = torch.tensor([[-5.00],[10.00]], requires_grad=True)
#---#
for epoch in range(30):
Yhat = X @ What
loss = torch.sum((Y - Yhat)**2)
loss.backward()
What.data = What.data - 0.001 * What.grad
What.grad = None(2) – hint: SSE 에서 MSE로 손실이 바뀔때 학습률을 어떻게 보정해야 같은 결과가 나올까요?
What = torch.tensor([[-5.00],[10.00]], requires_grad=True)
#---#
for epoch in range(30):
Yhat = X @ What
loss = torch.mean((Y - Yhat)**2)
loss.backward()
What.data = What.data - ???? * What.grad
What.grad = NoneWhat = torch.tensor([[-5.00],[10.00]], requires_grad=True)
#---#
for epoch in range(30):
Yhat = X @ What
loss = torch.mean((Y - Yhat)**2)
loss.backward()
What.data = What.data - 0.1 * What.grad
What.grad = None(3)
What = torch.tensor([[-5.00],[10.00]], requires_grad=True)
loss_fn = ????
#---#
for epoch in range(30):
Yhat = X @ What
loss = loss_fn(Yhat,Y)
loss.backward()
What.data = What.data - ???? * What.grad
What.grad = NoneWhat = torch.tensor([[-5.00],[10.00]], requires_grad=True)
loss_fn = torch.nn.MSELoss()
#---#
for epoch in range(30):
Yhat = X @ What
loss = loss_fn(Yhat,Y)
loss.backward()
What.data = What.data - 0.1 * What.grad
What.grad = None(4)
net = torch.nn.Linear(in_features=??, out_features=??, bias=False)
net.weight.data = ???
loss_fn = torch.nn.MSELoss()
#---#
for epoch in range(30):
Yhat = ???
loss = loss_fn(Yhat, Y)
loss.backward()
??????????
??????????net = torch.nn.Linear(in_features=2, out_features=1, bias=False)
net.weight.data = torch.tensor([[-5.00, 10.00]])
loss_fn = torch.nn.MSELoss()
#---#
for epoch in range(30):
Yhat = net(X)
loss = loss_fn(Yhat, Y)
loss.backward()
net.weight.data = net.weight.data - 0.1 * net.weight.grad
net.weight.grad = None(5)
net = torch.nn.Linear(in_features=??, out_features=??, bias=False)
net.weight.data = ???
loss_fn = torch.nn.MSELoss()
????????
#---#
for epoch in range(30):
Yhat = net(X)
loss = loss_fn(Yhat, Y)
loss.backward()
optimizer.step()
???net = torch.nn.Linear(in_features=2, out_features=1, bias=False)
net.weight.data = torch.tensor([[-5.00, 10.00]])
loss_fn = torch.nn.MSELoss()
optimizer = torch.optim.SGD(net.parameters(), lr=0.1)
#---#
for epoch in range(30):
Yhat = net(X)
loss = loss_fn(Yhat, Y)
loss.backward()
optimizer.step()
optimizer.zero_grad()(6)
net = torch.nn.Linear(in_features=???, out_features=???, bias=True)
net.weight.data = ????
net.bias.data = ????
loss_fn = torch.nn.MSELoss()
optimizer = torch.optim.SGD(net.parameters(), lr=0.1)
#---#
for epoch in range(30):
Yhat = ???
loss = loss_fn(Yhat, Y)
loss.backward()
optimizer.step()
optimizer.zero_grad()net = torch.nn.Linear(in_features=1, out_features=1, bias=True)
net.weight.data = torch.tensor([[10.00]])
net.bias.data = torch.tensor([-5.00])
loss_fn = torch.nn.MSELoss()
optimizer = torch.optim.SGD(net.parameters(), lr=0.1)
#---#
for epoch in range(30):
Yhat = net(X1)
loss = loss_fn(Yhat, Y)
loss.backward()
optimizer.step()
optimizer.zero_grad()4. \({\bf W}^\ast\)를 추정하는 두 가지 방법
다음 설명 중 옳은 것을 모두 고르시오.
(1) 적절한 학습률(learning rate)과 충분한 반복(epoch)이 주어지면, 경사하강법으로 구한 추정값은 회귀분석에서 배운 해석해로 수렴한다.
(2) 적절한 학습률(learning rate)과 충분한 반복(epoch)이 주어지면, 경사하강법으로 구한 추정값은 결국 true parameter \(\begin{bmatrix} w_0^\ast \\ w_1^\ast \end{bmatrix}\) 로 수렴한다.
(3) 경사하강법에서 loss를 SSE에서 MSE로 바꿀 때, 학습률을 샘플 수 \(n\)배 만큼 조절하면 정확히 같은 결과를 얻을 수 있다.
(4) 경사하강법을 사용하면 벡터미분을 수행하여 해석해 공식을 유도하지 않아도 파라미터를 추정할 수 있다.
정답: (1), (3), (4)