1.단항 선형 회귀
- 한 개의 입력이 들어가서 한 개의 출력이 나오는 구조
import torch
import torch.nn as nn
import torch.optim as optim
import matplotlib.pyplot as plt
torch.manual_seed(2024)
파이토치에서 토치 변수가 랜덤한값을 2024로 고정하는 것입니다
.데이터를 3개를 만들었습니다. 3번들어가는겁니다.
레이블이 3개!
1->2
2->4
3->6 이렇게 되는거죠
x_train = torch.FloatTensor([[1], [2], [3]])
y_train = torch.FloatTensor([[2] ,[4], [6]])
print(x_train, x_train.shape)
print(y_train, y_train.shape)
시각화하기
plt.figure(figsize=(6,4))
plt.scatter(x_train, y_train)
모델만들기 Linear(입력받는 개수, 출력하는 개수) 를 이용해서
model = nn.Linear(1,1)을 입력했습니다.
# y = Wx + b
model = nn.Linear(1, 1)#입력을 1개를 받아서 출력을 1개 해주겠다는 의미
model
#Linear(in_features=1, out_features=1, bias=True)
bias=False를 사용하면 절편을 안쓰게됨.
y_pred = model(x_train)
y_pred
값은 랜덤으로 나오게됩니다. 이유는 아직 x_train학습이 전혀 되지않았기에
랜덤값이 나옵니다.
그래서 잘 맞추고 있다고 할 수 없겠죠.
일단, 위에 y_pred 결과가 어떻게 나왔는지 확인하기 위해서 직접 계산도 해보았습니다.
파라미터를 찍어보고 W과 b의 값을 넣어서 계산을 해보았고 그 값이 y_pred값과 맞는지도 확인했습니다.
list(model.parameters()) # W: 0.0634, b: 0.6625
#[Parameter containing:
# tensor([[0.0634]], requires_grad=True),
# Parameter containing:
# tensor([0.6625], requires_grad=True)]
# y = Wx+b
# x=1, 0.0634 * 1 + 0.6625 = 0.7259
#x=2일때는 0.0634*2 + 0.0625 = 0.7893
그렇지만 아직 x_train 학습이 되지않았기때문에 잘 맞추고 있다고 확신할 수 없습니다.
그래서 학습을 시켜주려고 합니다.
먼저 실제값과 예측값을 비교를 해봐야하는데 오차를 계산해주는 방법인 MSE를 활용하게 됩니다.
#MSE 공식
((y_pred - y_train)**2).mean()
#tensor(12.8082, grad_fn=<MeanBackward0>)
예측값- 실제값을 뺀 후 제곱을 해주고 평균을 내줍니다.
#mse함수를 구해주는 함수
loss = nn.MSELoss()(y_pred, y_train)
loss
#1번 괄호의미 == nn.MSELoss()
#2번 괄호의미 == (예측값, 학습값)
#tensor(12.8082, grad_fn=<MseLossBackward0>)
*헷갈려서 다시 메모
즉 볼때는 nn.MSELoss() 객체생성 후 (y_pred, y_train)를 실행한다고 보면됩니다.
mse = nn.MSELoss()
mse(y_pred, y_train)
의 의미와 같습니다. 만들어진 클래스가 실제 내부적으로 __call이라는 매소드를 가지고있기때문에 실행됩니다.
즉 손으로 계산한거랑 함수를 사용해도 값이 같음을 확인할 수 있습니다.
이제 오차값을 최소로 하는 값을 찾아내야하고 그것이 중요합니다.!!!!
2.최적화(Optimization)
- 학습 모델의 손실함수(loss function)의 최소값을 찾아가는 과정
- 학습 데이터를 입력하여 파라미터를 걸쳐 예측 값을 받음 -> 예측값과 실제 정답과 차이를 비교하는 것이 손실함수이고, 예측값과 실젯값 차이를 최소화 하는 파라미터를 찾는 과정이 <최적화>라고 합니다.
= loss를 최소로 만드는 과정을 최적화라고 합니다.
2-1. 경사하강법(Gradient Descent)
- 딥러닝 알고리즘 학습 시 사용되는 최적화 방법 중 하나
- 최적화 옵티마이저 알고리즘을 통해서 최적의 W와 b를 찾아내는 과정을 "학습"이라고 부릅니다.
어느쪽으로 가면 cost값이 낮아질지 방향을 찾게 됩니다. 방향을 찾게 되지만 어떤 값을 넣었을때 가장최적의 값을 찾을 수 있는지는 아무도 모르기때문에 Increment Step(학습률)을 이용해서 조금씩 w을 수정하게 됩니다.
2-2. 학습률(Learning rate) = lr
*학습률은 값을 내가 직접 주는것입니다.그래서 엉뚱하게 넣으면 제대로 값이 안나올 수 있습니다.
- 한 번의 W를 움직이는 거리(increment step)
- 0 ~ 1 사이의 실수값
- 학습률이 너무 크면 한 지점으로 수렴하는것이 아니라 발산할 가능성이 존재합니다.
- 그렇다고 너무 작은 학습률을 택할 때에는 수렴이 늦어지고, 시작점을 어디로 잡느냐에 따라 수렴 지점이 달라집니다.
너무 촘촘하게 값을 주다보면 global minimum임에도 불구하고 local minimum이 가장 최적값이라고 생각할 수 있다.
그래서 loss값을찍다가 내려갔다가 올라갔다가 이럴수도있다는것을 확인할 수 있습니다.
아직 경험이 많이 없는 저는 발산된다고 생각할 수 있지만 경험이 쌓이다보면
저런 곡선을 넘는것이라는것을 알 수 있습니다.
2-3. 경사 하강법의 한계
- 많은 연산량과 컴퓨터 자원을 소모함
- 데이터(입력값) 하나가 모델을 지날 때마다 모든 가중치를 한 번씩 업데이트 함
- 이때 가중치가 적은 모델의 경우 문제가 없으나, 모델의 가중치가 매우 많다면 모든 가중치에 대해 연산을 적용하기 때문에 많은 연산량을 요구할 수 있습니다.
- Global Minimum은 목표 함수 그래프 전체를 고려했을 때 최솟값을 의미하고, Local Minimum은 그래프 내 일부만 고려햇을 때 최솟값을 의미 -> 경사 하강법으로 최적의 값인 줄 알았던 값이 Local Minimum으로 결과가 나올 수 있음.
경사 하강법의 종류중 하나인
종류1. SGD(Stochastic Grdient Descemt) :
1.랜덤하게 데이터를 하나씩 뽑아서 loss를 만듦.
2.그 다음 데이터를 넣고 다시 데이터를 뽑고를 반복합니다 (랜덤포레스트 데이터 뽑는것과 비슷)
장점은 빠르게 방향을 결정할 수 있습니다.
optimizer = optim.SGD(model.parameters(), lr=0.01)
optimizer객체를 생성했습니다.
아까 위에서 수기로loss를 만들었지만 이것을 객체로 만들 수 있죠.
loss = nn.MSELoss()(y_pred, y_train)
예측값과 실제값을 연산할 수 있게 loss객체를 만들어놓았습니다.
여기까지 준비는 완료!되었습니다.
1.옵티마이저.
2.오차함수 준비완료
학습을 해야하고 처음으로 초기화를 합니다.
optimizer 초기화
optimizer.zero_grad()
optimizer을 초기화 해주는 이유는 loss값이 누적되어서 보이기에 학습이 제대로 되지않기때문입니다.
**초기화 할 경우에 아래와같이 됩니다.
학습1) model training loss : 1.5
학습2) model training loss : 1.4
학습3) model training loss : 1.3
....
**초기화 하지 않을 경우에 아래와같이 됩니다.
학습1) model training loss : 1.5
학습2) model training loss : 2.9
학습3) model training loss : 4.2
....
이렇게 되면 안되기에 loss.backward()를 사용하고
loss.backward() 호출될 때 초기설정은 gradient를 더해주는 것으로 되어있습니다.
학습 loop를 돌 때 이상적으로 학습이 이루어지기 위해서 한 번의 학습이 완료되어지면 LOSS값이 누적되지 않도록
gradient를 항상 0으로 만들어주어야 합니다.
optimizer.zero_grad()
#역전파: 비용 함수를 미분하여 gradient 계산
loss.backward()
#가중치 업데이트 함수 : 계산된 gradient를 사용하여 파라미터를 업데이트합니다.
optimizer.step()
위 3개의 코드는 항상 붙어다닌다는것을 확인하기!!
# list(model.parameters()) # W:0.0634 b: 0.6625
list(model.parameters()) # W:0.2177 b: 0.7267
웨이트와 바이어스가 변경된것을 확인할 수 있습니다.
반복학습을 통해 오차가 있는 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}')
100바퀴마다 한번씩 loss값을 찍어주는것을 확인하겠습니다.
loss:.6f = 소수 6자리까지라는 의미입니다.
에포크를 돌릴때마다 loss값이 많이 줄어드는것을 확인할 수 있씁니다.
아래는 파라미터를 확인하고있습니다.
print(list(model.parameters())) #W:1.9499, b:0.1138
x_test = torch.FloatTensor([[5]])
y_pred = model(x_test)
y_pred
5를 넣고 답을 10을 예측했지만 우리는 9.8이 나왔으니 어느정도 잘 맞추고 있다는것을 확인할 수 있습니다.
3. 다중 선형 회귀
- 여러 개의 입력이 들어가서 한 개의 출력이 나오는 구조
X_train = torch.FloatTensor([[73, 80, 75],
[93, 88, 93],
[89, 91, 90],
[96, 98, 100],
[73, 66, 70]])
y_train =torch.FloatTensor([[220], [270], [265], [290], [200]])
이것같은경우는 3개가 들어가서 1개가 나오는 구조입니다.
print(X_train, X_train.shape)
print(y_train, y_train.shape)
이것들을 모델로 넣어서 학습시키려고 합니다.
입력은 3개 출력은 1개가 되는 모델입니다.
# y= W1x1 + W2x2 + WW3x3 + b
model = nn.Linear(3,1)
model
#Linear(in_features=3, out_features=1, bias=True)
optimizer = optim.SGD(model.parameters(), lr=0.00001)
epochs = 20000
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}')
list(model.parameters())#W: [[0.6814, 0.8616, 1.3889]], b:[-0.2950]
x_test = torch.FloatTensor([[100, 100, 100]])
y_pred = model(x_test)
y_pred
#tensor([[292.8991]], grad_fn=<AddmmBackward0>)
완벽한 답으로는 300이 나와야하지만 292.9정도가 나온것을 보니 학습 및 예측이 잘 되는것으로 확인됩니다.
4. temps.csv 데이터에서 기온에 따른 지면 온도를 예측하기
#강사님 코드
import pandas as pd
df = pd.read_csv('경로)
df.info()
df.isnull().mean()
df=dr.dropna()
df.isnull().mean()
x_data = df[['기온(°C)']]
y_data = df[[지면온도(°C)']]
x_data = torch.FloatTensor(x_data.values)
y_data = torch.FloatTensor(y_daya.values)
print(x_train, x_train.shape)
print(y_train, y_train.shape)
x_data
y_daya
plt.figure(figsize=(8, 6))
plt.scatter(x_data, y_data)
model = nn.Linear(1,1)
optimizer = optim.SGD(model.parameters(), lr=0.001)
list(model.parameters())#W:-0.5700, b:0.2403
epochs= 30000
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}')
list(model.parameters())
y_pred = model(x)Daya)
y_pred
plt.figure(figsize=(8,6))
plt.scatter(x_data, y_data)
plt.scatter(x_data, y_pred.detach().numpy())
#기온 만들기
result = model(torch.FloaatTensor([[40]]))
result
#내가 짠 코드
#판다스 임포트
import pandas as pd
#csv파일 가져오기 & 확인
df = pd.read_csv('경로')
df
#필요없는 데이터들 drop
df.drop(columns=['지점', '지점명', '일시'],inplace=True)
#파일 내 가지고있는 데이터로 학습
x_train = torch.FloatTensor([[-8.7], [-7.3], [-6.7],
[-6.2], [-5.9]])
y_train = torch.FloatTensor([[-2.9], [-2.4], [-2.2],
[-2.0], [-1.9]])
#사이즈확인
print(x_train, x_train.shape)
print(y_train, y_train.shape)
#학습모델 만들기
model = nn.Linear(1,1)
model
#학습
optimizer = optim.SGD(model.parameters(), lr=0.001)
epochs= 10000
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}')
list(model.parameters())
# 새로운데이터넣고 예측
x_test = torch.FloatTensor([-8.8])
y_pred = model(x_test)
y_pred
torch.nn | 모델관련 껍데기 제공 |
torch.optim | 학습하는 모듈(가중치:웨이트값을 예측할 수 있는 것) |
torch.manual_seed() | 랜덤값을 고정시켜줌 |
nn.MSELoss()(예측값, 학습값) | MSELoss함수 |
optim.SGD(model.parameters(), lr=0.01) | optim안에 SGD라는 함수(model.parameters(), 예측률=0~1사이 값) |
optimizer.zero_grad() | 옵티마이저 초기화 |
loss.backward() | (역전파) 호출될 때 추기설정은 gradient를 더해주는것으로 되어있음 |
optimizer.step() | 가중치 업데이트 함 |
torch.FloatTensor([]) | |
'AI 컴퓨터 비전프로젝트 > [ML,DL]머신러닝,딥러닝' 카테고리의 다른 글
[DL] CNN 기초, 체험사이트 (0) | 2024.07.27 |
---|---|
[DL] 비선형 활성화 함수, 역전파 (0) | 2024.07.26 |
[DL] 딥러닝_뉴런, 퍼셉트론,히든레이어... (1) | 2024.07.25 |
[ML/DL] 데이터로더의 의미를 확인 후 손글씨 데이터셋으로 테스트해보기 (3) | 2024.07.25 |
[ML/DL] 파이토치,텐서,GPU (0) | 2024.07.18 |