Quiz-4 (2026.03.18) // 범위: ~02wk

Author

최규빈

Published

March 18, 2026

1. 차원과 shape

다음 물음에 답하시오. 각 문항의 정답은 하나이다.

(1) 아래 코드의 결과 텐서 shape로 올바른 것은?

a = torch.tensor([[1,2,3,4],[2,2,0,1],[0,1,-1,0],[3,1,-1,3]])
a[[0],:]

torch.Size([4])
torch.Size([1, 4])
torch.Size([4, 1])
torch.Size([])

a[[0],:]는 첫 번째 행을 2차원 행렬 형태로 유지해서 가져오므로 shape는 [1,4]이다.

(2) 아래 코드의 결과 텐서 shape로 올바른 것은?

a = torch.tensor([[1,2,3,4],[2,2,0,1],[0,1,-1,0],[3,1,-1,3]])
a[0,:]

torch.Size([4])
torch.Size([1, 4])
torch.Size([4, 1])
torch.Size([])

a[0,:]는 첫 번째 행을 1차원 벡터로 가져오므로 shape는 [4]이다.

2. reshape와 전치

(1) 아래 코드를 실행했을 때 결과 shape는?

a = torch.tensor([1,2,3,4,5,6])
a.reshape(3,2)

torch.Size([6])
torch.Size([2, 3])
torch.Size([3, 2])
torch.Size([1, 6])

(2) 아래와 같이 정의된 텐서 a를 전치한 결과를 만드는 코드로 올바른 것을 모두 고르시오.

a = torch.tensor([[1,2,3],[2,3,4]])

a.reshape(3,2)
a.T
torch.einsum('ij -> ji', a)
a.permute(1,0)

②, ③, ④

reshape는 원소의 나열 순서를 유지한 채 모양만 바꾸고, 전치는 행과 열의 축을 바꾸는 연산이다.

(3) 아래 중 a = torch.tensor([[1,2,3],[4,5,6]])를 shape [6,1]로 바꾸는 코드를 모두 고르시오.

a.reshape(6,1)
a.reshape(6,-1)
a.reshape(-1,1)
a.reshape(6).reshape(-1)

①, ②, ③

3. @의 유연성

(1) 아래 코드의 결과 shape는?

a = torch.tensor([1,2,3,4]).reshape(2,2)
b = torch.tensor([10,20])
b @ a

[2,2]
[1,2]
[2]
④ 에러 발생

강의노트 설명처럼 b를 일시적으로 1x2로 해석해 곱한 뒤 다시 1차원 벡터로 돌려놓은 결과처럼 이해할 수 있다.

(2) 아래 코드의 결과 shape는?

a = torch.tensor([1,2,3,4]).reshape(2,2)
b = torch.tensor([10,20])
a @ b

[2,2]
[2]
[1,2]
④ 에러 발생

이번에는 b2x1처럼 해석한 뒤 곱하고, 다시 1차원 벡터로 돌려놓은 결과처럼 이해할 수 있다.

(3) 아래 코드의 결과 shape는?

a = torch.tensor([1,2,3])
b = torch.tensor([4,5,6])
a @ b

[1,1]
[3]
[]
④ 에러 발생

1차원 벡터끼리의 @는 내적을 계산하며, 결과 shape는 []이다.

(4) 아래 코드의 결과 shape는?

a = torch.tensor([1,2,3]).reshape(1,3)
b = torch.tensor([4,5,6]).reshape(3,1)
a @ b

[1,1]
[]
[1]
④ 에러 발생

[1,3] @ [3,1]이므로 내적을 행렬곱 형태로 계산한 [1,1] 결과가 나온다.

(5) 아래 코드의 결과 shape는?

a = torch.tensor([1,2,3]).reshape(3,1)
b = torch.tensor([4,5,6]).reshape(1,3)
a @ b

[1,1]
[3]
[3,3]
④ 에러 발생

[3,1] @ [1,3]이므로 바깥곱 형태의 [3,3] 결과가 나온다.

(6) 아래 코드의 실행 결과로 올바른 것은?

a = torch.tensor([1,2,3]).reshape(1,3)
b = torch.tensor([4,5,6]).reshape(1,3)
a @ b

① 결과 shape는 [1,1]이다.
② 결과 shape는 [3,3]이다.
③ 결과는 tensor(32)이다.
④ 에러 발생

[1,3] @ [1,3]은 앞 행렬의 열 개수와 뒤 행렬의 행 개수가 다르므로 곱할 수 없다.

(7) 아래 코드의 결과 shape는?

a = torch.tensor([[1,2],[3,4]])
b = torch.tensor([[10,20],[30,40]])
a @ b

[2,2]
[2]
[1,2]
④ 에러 발생

(8) 아래 코드의 결과 shape는?

a = torch.tensor([[1,2],[3,4]])
b = torch.tensor([10,20])
b @ a

[2]
[2,2]
[1,2]
④ 에러 발생

1차원 벡터와 2차원 행렬의 곱이므로 결과는 다시 1차원 벡터가 된다.

(9) 아래 코드의 결과 shape는?

a = torch.tensor([[1,2],[3,4]])
b = torch.tensor([10,20])
a @ b

[2,2]
[2]
[2,1]
④ 에러 발생

2차원 행렬과 1차원 벡터의 곱이므로 결과는 1차원 벡터가 된다.

(10) 아래 코드의 결과 shape는?

a = torch.tensor([1,2,3]).reshape(1,3)
b = torch.tensor([4,5,6])
a @ b

[3,1]
[3]
[1]
④ 에러 발생

a[1,3]이고 b는 길이 3인 1차원 벡터이다. 이 경우 b[3,1]처럼 해석하여 곱할 수 있으므로 결과 shape는 [1]이다.

4. 다양한 텐서 생성

다음 코드에 대응하는 수식 표현을 모두 고르시오. (단, \(i=1,2,\dots,10\))

(1)

y = 2 + torch.randn(10)

\(y_i \overset{i.i.d.}{\sim} N(2,1)\)
\(y_i = 2 + \epsilon_i,\ \epsilon_i \overset{i.i.d.}{\sim} N(0,1)\)
\(y_i \overset{i.i.d.}{\sim} N(0,1)\)
\(y_i = 2\epsilon_i,\ \epsilon_i \overset{i.i.d.}{\sim} N(0,1)\)

①, ②

두 표현은 서로 같은 내용을 다르게 쓴 것이다. torch.randn(10)N(0,1) 잡음이고, 2를 더하면 분포는 N(2,1)이 된다.

(2)

y = torch.randn(10) * 2

\(y_i \overset{i.i.d.}{\sim} N(0,2^2)\)
\(y_i = 2\epsilon_i,\ \epsilon_i \overset{i.i.d.}{\sim} N(0,1)\)
\(y_i \overset{i.i.d.}{\sim} N(2,1)\)
\(y_i = 2 + \epsilon_i,\ \epsilon_i \overset{i.i.d.}{\sim} N(0,1)\)

①, ②

표준정규에 2를 곱하면 표준편차가 2가 되므로 N(0,4)와 같은 뜻이다.

(3)

y = torch.randn(10) * 2 + 1

\(y_i \overset{i.i.d.}{\sim} N(1,2^2)\)
\(y_i = 1 + 2\epsilon_i,\ \epsilon_i \overset{i.i.d.}{\sim} N(0,1)\)
\(y_i = 1 + \epsilon_i,\ \epsilon_i \overset{i.i.d.}{\sim} N(0,2^2)\)
\(y_i = 2\epsilon_i,\ \epsilon_i \overset{i.i.d.}{\sim} N(1,1)\)

①, ②, ③

①, ②, ③ 세 표현은 서로 같은 내용을 다르게 쓴 것이다. torch.randn(10)N(0,1) 잡음이고, 2를 곱한 뒤 1을 더했으므로 \(y_i \overset{i.i.d.}{\sim} N(1,4)\) 이다.

(4)

p = torch.zeros(10) + 0.5
y = torch.bernoulli(p)

\(y_i \overset{i.i.d.}{\sim} \text{Bernoulli}(0.5)\)
\(y_i \overset{i.i.d.}{\sim} \text{Bernoulli}(1)\)
\(y_i \overset{i.i.d.}{\sim} \text{Bernoulli}(0.1)\)

성공확률이 모두 0.5이므로 각 관측값은 \(\text{Bernoulli}(0.5)\)에서 생성된다.

(5)

p = torch.tensor([0.1] * 5 + [0.9] * 5)
y = torch.bernoulli(p)

\(y_i \overset{i.i.d.}{\sim} \text{Bernoulli}(0.5)\)
\(y_i \sim \text{Bernoulli}(p_i),\ p_i=\begin{cases}0.1,& i=1,\dots,5 \\ 0.9,& i=6,\dots,10\end{cases}\)
\(y_i \overset{i.i.d.}{\sim} \text{Bernoulli}(0.1)\)

앞의 5개와 뒤의 5개의 성공확률이 다르므로 \(\overset{i.i.d.}{\sim}\)로 쓸 수 없다.

(6)

x = torch.linspace(-0.9, 0.9, 10)
p = 1 / (1 + torch.exp(-2*x + 5))
y = torch.bernoulli(p)

\({\bf x}=[-0.9,-0.7,\dots,0.9],\ p_i=\frac{1}{1+\exp(-2x_i+5)},\ y_i \sim \text{Bernoulli}(p_i)\)
\({\bf x}=[-0.9,-0.7,\dots,0.9],\ p_i=\frac{1}{1+\exp(2x_i+5)},\ y_i \sim \text{Bernoulli}(p_i)\)
\({\bf x}=[-0.9,-0.7,\dots,0.9],\ p_i=\frac{1}{1+\exp(-x_i)},\ y_i \sim \text{Bernoulli}(p_i)\)

코드에서 정의한 확률은 \(p_i=\frac{1}{1+\exp(-2x_i+5)}\) 이다. 따라서 이에 대응하는 베르누이 표현은 ①이다.

5. axis, concat, stack

(1) 아래 코드의 결과 shape는?

a = torch.arange(24).reshape(2,3,4)
b = -a
torch.concat([a,b], axis=1)

(4,3,4)
(2,6,4)
(2,3,8)
(2,3,4,2)

axis=1로 concat하면 두 번째 축의 길이가 더해진다.

(2) 아래 코드의 결과 shape는?

a = torch.tensor([1,2,3])
b = torch.tensor([4,5,6])
torch.stack([a,b], axis=1)

(6,)
(2,3)
(3,2)
(1,3,2)

stack은 새로운 축을 추가하면서 결합한다. axis=1이므로 가운데 위치에 새 축이 생긴다.

(3) 아래 코드의 결과로 올바른 것은?

a = torch.tensor([[1,2,3],[3,4,5]])
a.sum(axis=0)

tensor([4, 6, 8])
tensor([6, 12])
tensor(18)
tensor([[4, 6, 8]])

axis=0은 첫 번째 축을 제거하므로 열별 합이 계산된다.

(4) 아래 코드의 결과로 올바른 것은?

a = torch.tensor([[0,1],[2,3],[4,5],[6,7],[8,9]])
a.sum(axis=(0,1))

tensor([10, 35])
tensor([1, 5, 9, 13, 17])
tensor([0, 2, 4, 6, 8])
tensor(45)

axis=(0,1)은 첫 번째 축과 두 번째 축을 모두 제거하므로 모든 원소의 합을 계산한다. 따라서 결과는 tensor(45)이다.