cf> 스칼라 : 차원이 없는 경우
vector : 1차원
Matrix(행렬) : 2차원
Tensor : 3차원
2D Tensor : |t| = (batch size, dim) -> t가 batch size(세로) dimension(가로)의 크기를 가진다.
3D Tensor : |t| = (batch size, width,height) -> t가 batch size(세로)너비(가로)*높이(깊이)의 크기를 가진다.
인덱스를 활용하여 슬라이싱, 수정이 쉬움
ex) 1D vector 선언하기 : np.array([0.,1.,2.,3.,4.,5.,6.])
2D array 선언하기 : np.array([[0.,1.,2.,3.],[4.,5.,6.],[7.,8.,9.],[10.,11.,12.]])
t.dim() : rank 반환
t.shape() : shape 반환
Numpy와 유사함
ex) t = torch.FloatTensor[0.,1.,2.,3.,4.,5.,6.]) : 파이썬 리스트 -> torch의 float형 tensor
t.dim() : rank 반환
t.shape() = t.size() : shape 반환
+) 2차원도 numpy와 동일
: PyTorch에서 제공하는 기능
불가피하게 크기가 다른 행렬끼리 사칙연산을 해야 할 때, “자동으로” 행렬의 크기가 맞춰준다.
어떻게? 크기가 작은 행렬이 크기가 큰 행렬의 size와 같아지도록 원소를 반복
: 평균값 리턴
ex) t = torch.FloatTensor([1., 2.])
t.mean() #1.5
t = torch.FloatTensor([[1., 2.], [3., 4.]])
t.mean() #1,2,3,4 전체 평균
t.mean(dim=0) #2 by 2 -> 1 by 2 => [2.(1,3의 평균), 3.(2,4의 평균)]
t.mean(dim=1) #2 by 2 -> 2 by 1 => [1.5(1,2의 평균), 3.5(3,4의 평균)]
: 합 리턴(개수만큼 나누지 않은 mean과 동일함)
ex) t = torch.FloatTensor([[1., 2.], [3., 4.]])
t.sum() #10.
t.sum(dim=0) #2 by 2 -> 1 by 2 => [4., 6.]
t.sum(dim=1) #2 by 2 -> 2 by 1 => [3., 7.]
Max : tensor나 행렬에 대해 가장 큰 값 리턴
Argmax : max의 인덱스값 리턴
ex) t = torch.FloatTensor([[1., 2.], [3., 4.]])
t.max() #4.
t.max(dim=0) #2 by 2 -> 1 by 2 => [3.(1과 3 비교), 4.(2와 4 비교)]
t.max(dim=1) #2 by 2 -> 2 by 1 => [2.(1과 2 비교), 4.(3과 4 비교)]
ex) t = np.array([[[0, 1, 2], [3, 4 5,]] | [6, 7, 8], [9, 10, 11]]))
ft = torch.FloatTensor(t)
ft.shape #torch.Size([2, 2, 3]) #가로, 세로, 깊이
ft.view([-1, 3]) #앞에는 모르겠고(-1) 뒤에 2개의 차원은 3으로 지정
#tensor([ [0, 1, 2], | [3, 4, 5] | [6, 7, 8], | [9, 10, 11] ]) #Size는 [4(세로), 3(가로)] = [2, 2, 3] -> [2*2, 3]
ft.view([-1, 1, 3]) #원래 크기 (2, 2, 3) -> (2*2, 1, 3) => (4, 1, 3)
#tensor([ [ [ [0, 1, 2] ] | [ [3 , 4, 5] ] ] | [ [6, 7, 8] ] | [ [9, 10, 11] ] ] )
: veiw함수와 유사하지만 dimension의 원소의 개수가 1인 경우 자동으로 그 dimension을 없애줌
ex) ft = torch.FloatTensor([ [0], [1], [2] ])
#tensor([ [0] | [1] | [2] ]) ; size는 [3, 1]
ft.squeeze() #두번째 dimension이 1이므로
#tensor([0, 1, 2]) ; size는 [3]
+) squeeze(dim = 원하는 dimension값) ; 해당 dimension값==1일 경우 작동
ex) ft.squeeze(dim = 0) #0번째 dim값이 3이므로 변화 없음
ft.squeeze(dim = 1) # ft.squeeze()와 같은 결과 리턴
ex) ft = torch.Tensor([0, 1, 2]) #size : [3]
ft.unsqueeze(0) #ft 0번 dimension에 1을 넣어라 -> size : 1 by 3
view에서도 같은 결과를 리턴할 수 있음
ex) ft.view(1, -1) #뒤는 상관없이 앞에 1을 넣음
#tensor([ [0, 1, 2] ]) #shape : [1, 3]
ft.unsqueeze(1)
#tensor([ [0] | [1] | [2] ]) -> size : 3 by 1
ft.unsqueeze(-1) #dim = -1 ; 마지막 dimension을 나타내므로 dim=1과 같음
#tensor([ [0] | [1] | [2] ]) -> size : 3 by 1
: Tensor의 타입을 바꿔주는 기능
ex) lt = torch.LongTensor([1, 2, 3, 4])
lt.float()
#tensor([1., 2., 3., 4.])
bt = torch.ByteTensor([True, False, False, True])
#tensor([1, 0, 0, 1])
bt.long()
#tensor([1, 0, 0, 1])
bt.float()
#tensor([1., 0., 0., 1.])
: 이어붙이는 기능
ex) x = torch.FloatTensor([ [1, 2], [3, 4] ])
y = torch.FloatTensor([ [5, 6], [7, 8] ])
torch.cat([x, y], dim = 0) #가로로 이어붙이기
#tensor([ [1, 2] |3, 4] | [5, 6] | [7, 8] )) -> size : 4 by 2
torch.cat([x, y], dim = 1) #세로로 이어붙이기
#tensor([ [1, 2, 5, 6] | [3, 4, 7, 8] ]) -> size : 2 by 4
: Concatenation을 편리하게 사용할 수 있는 함수
ex) x = torch.FloatTensor([1, 4])
y = torch.FloatTensor([2, 5])
z = torch.FloatTensor([3, 6])
torch.stack([x , y, z])
#tensor([ [1, 4] | [2, 5] | [3, 6] ]) -> size : 3 by 2
torch.stack([x , y, z], dim = 1) #위의 결과에 따라 (dim = 1) = 3
#tensor([ [1, 2, 3] | [4, 5, 6] ]) -> size : 2 by 3
+) Cat을 사용한 구현
torch.cat([x.unsqueeze(0), y.unsqueeze(0), z.unsqueeze(0)], dim = 0)
#unsqueeze한 x,y,z 모두 1 by 2
#tensor([ [1, 4] | [2, 5] | [3, 6] ])
: 기존의 tensor와 같은 shape의 1 또는 0으로만 구성된 tensor 생성
ex) x = torch.FloatTensor([ [0, 1, 2], [2, 1, 0] ])
torch.ones_like(x)
#tensor([ [1, 1, 1] | [1, 1, 1] ])
torch.zeros_like(x)
#tensor([ [0, 0, 0] | [0, 0, 0] ])
: 메모리를 새로 선언하지 않고 결과값을 기존의 tensor에 할당하는 기능
ex) x = torch.FloatTensor([ 1, 2] , [3, 4] ))
x.mul(2.)
#tensor([ [2., 4.] | [6., 8.] ])
x
# tensor([ [1., 2.] | [3., 4.] ]) -> x의 값이 바뀌지 않음
x.mul_(2.) #In-place Operation
#tensor([ [2., 4.] | [6., 8.] ])
x
#tensor([ [2., 4.] | [6., 8.] ]) -> x의 값이 바뀜
주어진 데이터로 최선의 예측을 하도록 학습시키는 방법
Linear regression : 학습데이터와 가장 잘 맞는 하나의 직선 찾기
Y = Wx + b (W: Weight, b: Bias)
W와 b는 각각 0으로 초기화 => 처음에 어떤 입력을 받아도 0을 예측
우리의 목적 : W와 b 학습시키기
=> Requires_grad = True ; PyTorch에게 W와 b 학습시킬 것을 명시
: loss를 이용해 모델 개선하기
torch.optim 라이브러리 사용 -> tensor와 적당한 learning rate를 지정해준다.
ex) 공부시간과 성적의 상관관계
x_train = torch.FloatTensor([ [1], [2], [3] ])
y_train = torch.FloatTensor([ [2], [4], [6] ])
W = torch.zeros(1, requires_grad=True)
b = torch.zeros(1, requires_grad=True)
optimizer = optim.SGD([W, b], lr = 0.01)
nb_epoches= 1000
for nb_epoch in range(1, nb_epochs+1):
hypothesis = x_train * W + b
cost = torch.mean((hypothesis – y_train) ** 2)
항상 붙어다니는 3줄
optimizer.zero_grad() #gradient 초기화
cost.backward() #gradient 계산
optimizer.step() #계산된 gradient를 방향대로 W와 b 계산
=> For문이 반복적으로 학습되면서 W와 b가 각각 하나의 숫자로 수렴하게 됨
Cost를 줄이는 Gradient Descent
Review> Hypothesis(Linear Regression) : H(x) = Wx + b
;인공신경망의 구조, 주어진 input x에 대해 어떤 output y를 예측할지 알려줌
( W : 하나의 matrix, x : input vector, b : Bais vector)
Simpler Hypothesis Function : H(x) = Wx ; W라는 상수 하나만 학습
어떻게 모델의 좋고 나쁨을 평가할 수 있을까?
=> Cost function
: 모델 예측값이 실제 데이터와 얼마나 다른지 나타내는 값
잘 학습된 모델일수록 cost값이 낮다
우리가 원하는 것 : cost function 최소화
=> 기울기(Gradient)가 음수일 때, W가 커져야 함
=> 기울기가 양수일 때, W가 작아져야 함
: gradient를 이용해 cost를 줄인다
Cost를 줄이려면 W를 Grad W값에 일정 상수 알파(learing rate = lr)를 곱한 값을 뺌
시작할 때 optimizer 정의 -> optimizer.zero_grad()로 gradient를 0으로 초기화 ->
cost.backward()로 gradient 계산 -> optimizer.step()으로 gradient 줄이기