Pytorch를 다루는데 꼭 필요한 tensor에 대한 개념과 선형 모델로 간단한 데이터 모델을 예측하는 모델을 만들어보자
X, Y # Tensors X.dim() # 차원을 출력 X.shape, X.size() # 텐서의 모양을 출력
import torch
X =torch.rand(3,4, 5)
print('X.dim()', X.dim())
print('X.shape', X.shape)
print('X.size()', X.size())
X.dim() 3
X.shape torch.Size([3, 4, 5])
X.size() torch.Size([3, 4, 5])
X.matmul(Y) # 행렬 곱 (내적) X.mul(Y) # X*Y 와 동일. 각 원소 별로 곱하는 연산.
X = torch.rand(3,2,5)
Y = torch.rand(3,5,3)
D = X.matmul(Y) # 행렬 곱 (내적)
print(D)
print(D.shape)
# X.mul(Y) # X*Y 와 동일. 각 원소 별로 곱하는 연산.
tensor([[[1.7955, 1.2414, 1.4892],
[1.4453, 1.0660, 1.0680]],
[[1.5991, 1.2970, 1.6333],
[1.0118, 1.4612, 0.9563]],
[[0.4231, 0.7838, 1.0513],
[0.8023, 1.0286, 1.2409]]])
torch.Size([3, 2, 3])
X의 shape이 [100,1,20] 이고, Y가 [100,40,20] 일때, 크기가 다르기 때문에 원소별 연산 (예; +, * 등) 적용이 불가한 것처럼 보이지만, numpy와 pytorch는 broadcasting을 지원하여, X의 두번째 차원 1인 경우, Y의 두번째 차원인 40에 맞춰 X의 값들을 반복 복제하는 식으로 자동으로 크기를 조절하여 연산이 가능하도록 만들어줍니다. 매번 복제하는 코드를 명시적으로 구현할 필요 없이, 매우 편리하게 응용될 수 있지만, 의도치 않게 broadcasting이 되면 디버깅을 할때 오류를 잡는 것이 어려워 질 수 있으므로 꼭 주의하여 사용 것이 좋습니다.
텐서의 shape를 바꿔야할 경우 사용합니다. 매우 자주 쓰이는 함수이므로 꼭 알아두세요!
X.shape
X.view(3,10).shape
torch.Size([3, 10])
많은 함수에서 매개변수로 요구되는 개념입니다. 다차원 텐서에 해당 함수 연산을 어떤 축으로 적용 할지를 결정하는데 사용합니다.\ 예; np.concaternate((A1,B1),axis = 0) 이런식으로 함수의 매개변수 중 하나로 자주 등장합니다. \ \ 참고자료> http://taewan.kim/post/numpy_sum_axis/ \
특정 차원이 1인 경우 축소시키거나 차원을 확장시킬 때 사용합니다. 자주 등장하므로 알아두면 좋습니다.
torch.squeeze(X) # X: [100,1,20] => [100,20]
컴퓨터는 여러가지 자료형(int,float,uint8 등)이 있지만 type이 같지 않으면 수치적인 문제가 발생할 수 있기 때문에 항상 유의하는 것이 좋습니다. 따라서 자료형이 무엇인지 그리고 어떻게 바꾸는지 알고 있어야 합니다.
두 개 이상의 텐서들을 지정된 축으로 쌓아서 더 큰 텐서를 만드는 함수. 하나의 텐서로 합치기 위한 입력 텐서들은 concatenate하는 축을 제외하고는 모두 같은 크기를 가져야 합니다.
선형 모델 f(x)=Wx+b에 대해서, 주어진 데이터를 제일 잘 표현하는 learnable parameter인 Weight W와 Bias b를 찾는 방법의 예제 입니다. 이 실습에서는 parameter 탐색을 하는 다양한 방법 중 가장 Naive한 방법으로 찾는 예제를 보여줍니다.
먼저 필요한 라이브러리들을 import합니다.
from __future__ import print_function, division
import os
import torch
import pandas as pd
from skimage import io, transform
import numpy as np
import warnings
warnings.filterwarnings("ignore")
다음의 그래프는 지난 시험의 결과를 토대로 서로 다른 학생의 공부시간과 성적의 관계를 모아놓은 표입니다.
![스크린샷 2022-08-24 오후 5.00.16](무제.assets/스크린샷 2022-08-24 오후 5.00.16.png)
이번에는 GDrive와 Colab의 csv 파일을 읽어오는 법과 외부 인터넷 페이지 상의 csv 파일을 읽어오는 법에 배워보도록 하겠습니다.
하단의 링크에는 health_data.csv 파일이 들어있습니다. 이 파일을 다운받은 후 google drive의 가장 기본 디렉토리인 "내 드라이브"로 옮겨주세요.
https://drive.google.com/file/d/1C1_Sh2Rw5St58NLvDer62cJd-bvUvUcs/view?usp=sharing
Colab과 Gdrive 모두 google에서 제공하는 서비스이므로 2개를 연동시킬 수 있습니다.
하단의 링크를 참조하시면 친절한 설명이 되어있습니다.
https://starrykss.tistory.com/1029
from google.colab import drive
drive.mount('/content/gdrive') Mounted at /content/gdrive
Mounted at /content/gdrive
gdrive와 colab을 연동시켰다면 gdrive에서 csv 파일을 가져와 사용해봅시다.
import pathlib
path = pathlib.Path('/content/gdrive/My Drive/health_data.csv')
data_file = pd.read_csv(path)
data_file.head()
![스크린샷 2022-08-24 오후 5.13.35](무제.assets/스크린샷 2022-08-24 오후 5.13.35.png)
이 데이터는 정제가 되지 않아 데이터가 불완전 한 상태입니다. NaN은 숫자로 표현 불가한 값으로 최적의 Weight W와 Bias b 를 찾는데 방해가 됩니다. 이런 데이터들을 모두 제거하는 전처리 작업을 해봅시다.
pd.isnull(data_file)
![스크린샷 2022-08-24 오후 5.20.28](무제.assets/스크린샷 2022-08-24 오후 5.20.28.png)
data_file.isnull()
(힌트1) pandas의 dropna()이용
(힌트2) axis에 대한 개념을 모르겠다면 tensor manipulation 부분으로 가서 다시 공부해보세요!
data_file = pd.read_csv(path).dropna(axis=0)
data_file.head()
![스크린샷 2022-08-24 오후 5.26.15](무제.assets/스크린샷 2022-08-24 오후 5.26.15.png)
data_file = data_file.dropna(index=0).reset_index(drop=True)
data_file.head()
height =
weight =
![스크린샷 2022-08-24 오후 6.23.34](무제.assets/스크린샷 2022-08-24 오후 6.23.34.png)
이런식으로 하면 되지 않을까 생각했는데 실패 ㅠㅠ
height = torch.tensor(data_file.height)
weight = torch.tensor(data_file.weight)
(힌트) .view() 함수이용, shape = (50, 1), dimension = 2
x_train = height.view([height. shape[0] ,1]).float()
y_train = weight.view([weight. shape[0] ,1]).float()
(힌트) 랜덤 생성 함수 torch.rand()함수 사용, concatenate의 경우 torch.cat()함수를 사용합니다. axis도 데이터의 형태에 맞게 사용하시면 됩니다.
x_train = torch.cat((torch.rand(50.1)*45+145,x_train). axis = 0)
y_train = torch.cat((torch.rand(50.1)*45+145,y_train). axis = 0)
![스크린샷 2022-08-25 오전 1.29.36](무제.assets/스크린샷 2022-08-25 오전 1.29.36.png)
%matplotlib inline
import matplotlib.pyplot as plt
x = x_train
y = y_train
plt.scatter(x,y)
plt.show()
hypothesis=Wx+b
현재 구한 직선 (Hypothesis)이 데이터에 잘 fitting 되었는지 확인하는 방법으로는 Error ∣hypothesis−y∣의 합으로 구하며 이를 loss라고 명명합니다. 일반적으로는 L2 loss라 하여 간단히 (hypothesis−y)2를 사용하나, 본 예제에서는 데이터에 거짓 데이터(Outlier)들이 많이 포함되어 있어, 거짓 데이터에 강인하다고 알려진, L1 loss ∣hypothesis−y∣를 사용합니다. 이전에 구했던 loss의 값보다 더 작은 loss가 나올 경우 min_loss에 현재의 loss를, min_W과 min_b에는 현재 W와 b를 저장합니다.
50000번을 반복하여 생성된 직선을 matplotlib으로 시각화하여 얼마나 현재 training dataset에 얼마나 잘 fitting 되었는지 확인하여보세요.
(힌트) 랜덤으로 숫자를 생성하는 함수로는 torch.rand() 함수를 사용하고, 적당히 크기와 오프셋을 조정해주세요. ([출력범위] = 크기*[입력범위] + 오프셋)
(힌트) 파이썬의 기초가 약하여 if문, for문 같은 문법을 간단하게 공부하고 싶으시다면 wikidoc(https://wikidocs.net/book/1 : jump to python)을 참고하시면 도움이 될것입니다.
(+) |hypothesis - y|의 값들을 모두 더하는 가장 쉬운 방법은 for문을 사용하는 것이지만, 가장 짧게 작성할 수 있는 방법은 벡터화하여 연산하는 방법입니다. https://ooyoung.tistory.com/141 벡터화와 관련된 간단한 설명이 되어있는 링크이며 벡터화를 시키지 않아도 문제를 푸는데는 지장이 없습니다.
#답안 작성
#문제를 푸는데 필요한 변수들이며 필요할 경우 추가 혹은 삭제하셔도 무방합니다.
iter = 50000 #loss값을 구하는 횟수로 총 50000번
weight_max = 100 #'[입력범위]'로 random값의 weight 범위 제한 목적 ( -50 < weight < 50 )
bias_max = 150 #오프셋으로 random값의 bias 범위 제한 목적 (-150 < bias < 0)
min_loss = 1000000 #업데이트 된 가장 작은 값의 loss 저장
min_W = 0
min_b = 0
#dataset
x = x_train
y = y_train
def loss_fn(hypo, GT):
return sum(abs(hypo - GT))
# [Do it yourself] 위의 변수들을 활용하여 문제를 풀어주세요.
for i in range(iter):
W =
b =
hypothesis =
cur_loss = loss_fn(hypothesis,y)
...
if cur_loss < min_loss:
...
최종적으로 data에 직선을 잘 fitting 시켰는지 시각화 해봅시다
# 직선 시각화
%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
x = x_train
y = y_train
plt.scatter(x, y)
t = np.arange(140.,190.,0.001)
plt.plot(t, min_W*t+min_b)
plt.xlabel('height (cm)')
plt.ylabel('weight (kg)')
plt.show()
대략 아래와 같은 결과를 얻으셨다면 Day1의 실습은 마무리가 된 것입니다.