Quiz-8 (2026.04.01) // 범위: ~04wk

Author

최규빈

Published

April 1, 2026

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.grad

gradient 값을 초기화 하지 않음.

(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 = None
What = 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 = None
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.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 = None
What = 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)