Quiz-4 (2026.03.18) // 범위: ~02wk
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]
④ 에러 발생
②
이번에는 b를 2x1처럼 해석한 뒤 곱하고, 다시 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)이다.