개발/머신러닝-딥러닝

2023.06.15 파이토치로 구현한 선형회귀

상달군 2023. 7. 6. 17:49
728x90

목차
1.단항 선형회귀 실습

  • 경사하강법(Gradient Descent)

2.다중 선형회귀
3.문제


13.파이토치로 구현한 선형회귀.ipynb


1.단항 선형회귀 실습

◼ 한 개의 입력이 들어가서 한 개의 출력이 나오는 구조

 

import torch
import torch.nn as nn # 파이토치로 신경망(딥러닝) 모델을 만들수 있는애
import torch.optim as optim # optimizer: 기울기, 절편을 학습하며 갱신할 수 있게 해주는 알고리즘
import matplotlib.pyplot as plt

🔻랜덤 시드 설정하기 

# 파이썬 코드를 재실행 해도 같은 결과가 나올 수 있도록 랜덤시드를 설정 해줌

torch.manual_seed(10)

🔻예제를 위한 데이터셋 만들기

x_train = torch.FloatTensor([[1],[2],[3]])
y_train = torch.FloatTensor([[2],[4],[6]])

print(x_train)
print(x_train.shape)
print(y_train)
print(y_train.shape)

🔻그래프 그리기 

plt.figure(figsize=(8,5))
plt.scatter(x_train, y_train)

🔻선형변환 클래스 사용  

🗨 nn.Linear는 파이토치에서 사용되는 선형 변환(linear transformation)을 수행하는 클래스

     H(x) = Wx + b에서 Wx + b는 x에 대한 1차 방적식으로 직선을 표현한다

  • W(Weight) : 기울기 
  • b(bias) : 절편
 # 가설의 공식을 만들수 있다.  H = Wx +b

 model = nn.Linear(1, 1)
 print(model)
print(list(model.parameters()))

3

🔻 바로 예측 해보기 

# 비용 함수
# Cost Function = Loss Function

#학습을 하지 않고 바로 예측을 했기 때문에 신빙성은 전혀 없다.
y_pred = model(x_train)
print(y_pred)

비용함수(Cost Function, Loss Function)
기계 학습에서 사용되는 함수로, 모델의 예측 값과 실제 값 사이의 차이를 측정하는 데 사용됨.
모델이 얼마나 정확하게 예측하는지를 평가.

🔻MSE값 구하기

# MSE
((y_pred - y_train)**2).mean()

🔻MSE값 구하기 (nn.MSELoss(): MSE를 구하는 함수)

# MSE
loss = nn.MSELoss()(y_pred, y_train)
loss

🔻pred 값 직접 구해보기 ! 

# 데이터 [[1],[2],[3]]
# W: [[-0.0838]] , b: [-0.0343]
# 공식 : H = Wx + b
# pred: [[-0.1181],[-0.2019],[-0.2858]]


#pred값 실제 계산 해보기
print(-0.0838*1+-0.0343)
print(-0.0838*2+-0.0343)
print(-0.0838*3+-0.0343)


◼ 경사하강법(Gradient Descent)

  • 비용 함수의 값을 최소로 하는 W와 b를 찾는 알고리즘을 옵티마이저 알고리즘라고 한다.
  • 최적화 알고리즘
  • 옵티마이저 알고리즘을 통해 W와 b를 찾아내는 과정을 학습이라고 부른다.
  • 경사 하강법은 가장 기본적인 옵티마이저 알고리즘이라고 보면 된다.

🔻옵티마이저 설정하기( 최적화 알고리즘 선택 및 하이퍼파라미터 설정)

# lr 학습률(Learning rate) : 한번 움직이는 거리 (increment step)
optimizer = optim.SGD(model.parameters(), lr=0.01 )
optimizer

PyTorch에서 제공하는 최적화(optimizer) 알고리즘을 포함하는 torch.optim 모듈
최적화는 딥러닝 모델의 학습 과정에서 모델의 가중치와 편향을 업데이트하여 손실 함수를 최소화하는 과정
loss = nn.MSELoss()(y_pred, y_train)


# 밑에 3개는 항상 붙어다니는 셋트

#gradient를 초기화
optimizer.zero_grad()  # 기존 optimizer가 가지고 있는 값을 초기화 해라 !

#비용 함수를 미분하여 gradient(기울기)계산
loss.backward()        # 미분을 취해서 기울기와 절편을 다시 찾아내는것(역전파)

#W와b를 업데이트
optimizer.step()       #기울기와 절편을 업데이트

# 이전 기울기와절편= W: [[-0.0838]] , b: [-0.0343]
# 다시 계산한 기울기와 절편= W: [[0.1120]], b: [0.0498]

# 학습전 파라미터 확인하기
print(list(model.parameters()))

# 학습(Training) (반복 훈련을 해야한다!)
# 반복 훈련을 하면서 틀린 W,b를 수정하여 오차를 계속 출여나감
# epochs: 반복 훈련 횟수

epochs = 1000

for epoch in range(epochs + 1):
  y_pred = model(x_train)
  loss = nn.MSELoss()(y_pred, y_train)
  optimizer.zero_grad()
  loss.backward()
  optimizer.step()

  if epoch % 100 == 0:
    print(f'Epoch {epoch}/{epochs} Loss: {loss:.6f}')

🔻 가장 좋은 파라미터값 

🗨 학습후 모델 파라미터 확인 input 1개, output 1개 

# 가장 좋을때의 파라미터값
print(list(model.parameters()))

# W: [[1.9709]], b: [0.0661]

# 1.9709 * x + 0.0661

x_test = torch.FloatTensor([[10],[12.1234]]) # 스칼라 2개짜리 답안지 만들기 [10],[12.1234]
y_pred = model(x_test) # 우리가 만든 model에 답안지를 넣고 예측 하기
print(y_pred) #우리가 만든 모델은 1개의 답안을 넣으면 1개의 값이 나온다.

🗨 답안지를 넣고 예측 하기 단항 선형회귀를 사용하였기 때문에 1의 input에 1개의 값이 나오게 된다. 

따라서, 우리는 스칼라 2개짜리 답안을 넣었기 모델에 넣었기 때문에 pred값이 2개가 출력 되게 된다. 


2.다중 선형회귀

# 직접 손으로 데이터 만들기
x_train = torch.FloatTensor([[73,80,75],
                             [93,88,93],
                             [89,91,90],
                             [96,99,100],
                             [73,66,70]])
y_train = torch.FloatTensor([[152],[185],[180],[196],[142]])


print(x_train)
print(x_train.shape)
print(y_train)
print(y_train.shape)

🔻가설 공식 

# 가설
# H = W1x1 + w2x2 + w3x3 +b
model = nn.Linear(3,1) # 3개가 들어가서 1개가 나온다.
print(model)

🗨 학습전 모델 파라미터 확인 input 3개, output 1개 

print(list(model.parameters()))

🔻 옵티마이저 설정

# 옵티마이저
optimizer = optim.SGD(model.parameters(), lr=0.00001)

🔻 학습

# 학습(Training) (반복 훈련을 해야한다!)
# 반복 훈련을 하면서 틀린 W,b를 수정하여 오차를 계속 줄여나감
# epochs: 반복 훈련 횟수
epochs = 1000

for epoch in range(epochs + 1):

  y_pred = model(x_train)
  loss = nn.MSELoss()(y_pred, y_train)
  optimizer.zero_grad()
  loss.backward()
  optimizer.step()

  if epoch % 100 == 0:
    print(f'Epoch {epoch}/{epochs} Loss: {loss:.6f}')

🗨 학습후 모델 파라미터 확인 input 3개, output 1개 

print(list(model.parameters()))

🔻예측

x_test = torch.FloatTensor([[82,92,82]])
y_pred = model(x_test)
print(y_pred)

🗨 다중 선형 회귀를 이용하여 input의 3개의 답안을 입력 하였고, 그에 따른 결과값 1개가 출력 되었다. 

애초에 모델 생성할때 우리는 input 3개 -> output 1개 짜리 모델을 생성 하였다. 


3.문제

🎈 temps.csv 데이터에서 기온에 다른 지면 온도를 예측해보자.

import pandas as pd
from sklearn.model_selection import train_test_split

🔻 데이터 불러오기

temps_df = pd.read_csv('/content/drive/MyDrive/7.머신러닝 딥러닝/실습데이터/temps.csv')
temps_df

🔻 데이터셋 확인하기 (전처리) 

temps_df.info()

🔻결측치 확인하기 (전처리)

# 결측치 확인하기 
temps_df.isnull().sum()

👀 기온에서 결측치 3개 발견 

🔻 결측치 제거하기  (전처리)

# 기온에 결측치 3개 삭제하기
temps_df = temps_df.dropna()
temps_df.isnull().sum()

🔻우리한테 필요 없는 칼럼 삭제하기  (전처리)

# 지점, 지점명 필요 없는 칼럼 삭제하기
temps_df.drop(['지점','지점명','일시'], axis=1)

🔻x,y데이터 텐서로 만들기 

x_data = temps_df[['기온(°C)']]
y_data = temps_df[['지면온도(°C)']]

x_data = torch.FloatTensor(x_data.values)
y_data = torch.FloatTensor(y_data .values)


print(x_data)
print(x_data.shape)
print(y_data)
print(y_data.shape)

🗨 위에서 전처리한 x와 y데이터를 FloatTensor만들어 줍니다. 

(FloatTensor로 변환 해주는것은 온도랑은 상관 없지만 어떤 데이터를 나중에 어떻게 사용지 모르기 때문에 많이들 Float형태로 바꿔준다. 혹시 나중에 스케일을 이용하여 값을 0과 1사이값으로 바꾼다고 한다면 처음부터 Float형으로 잡아두는것이 나중에 가공하기 편하기 때문이다. )

 

🔻 그래프 그리기 

# 그래프를 그려보겠습니다.
import matplotlib.pyplot as plt
plt.figure(figsize=(12,8))
plt.scatter(x_data, y_data)

🔻 단항 선형회귀 모델 생성과 옵티마이저(최적화)설정 

model = nn.Linear(1,1) # 1개가 들어가서 1개가 나온다.
optimizer = torch.optim.SGD(model.parameters(), lr=0.001)
# [[0.3917]],[0.9699]
print(list(model.parameters()))

🗨 최적의 파라미터값을 확인하기 

🔻학습 시키기

# 학습(Training) (반복 훈련을 해야한다!)
# 반복 훈련을 하면서 틀린 W,b를 수정하여 오차를 계속 줄여나감
# epochs: 반복 훈련 횟수
epochs = 1000

for epoch in range(epochs + 1):

  y_pred = model(x_data)
  loss = nn.MSELoss()(y_pred, y_data)
  optimizer.zero_grad()
  loss.backward()
  optimizer.step()

  if epoch % 100 == 0:
    print(f'Epoch {epoch}/{epochs} Loss: {loss:.6f}')

🗨 여러번 학습을 통해 Loss값을 점차 줄여 나감 

 

🔻기울기, 절편 확인해보기 

# W,b확인하기
print(list(model.parameters()))

🔻예측하기 

y_pred = model(x_data).detach().numpy()
y_pred

🔻 그래프 그려보기

# 입력받은 데이터값
plt.figure(figsize=(14,8))
plt.scatter(x_data, y_data)

# 예측선
plt.scatter(x_data, y_pred)

728x90