๋”ฅ๋Ÿฌ๋‹/Today I learned :

ํŒŒ์ดํ† ์น˜๋กœ ๊ฐ„๋‹จํ•œ ์ธ๊ณต์‹ ๊ฒฝ๋ง ๊ตฌํ˜„ํ•˜๊ธฐ (๋ถ„๋ฅ˜)

์ฃผ์˜ ๐Ÿฑ 2022. 12. 29. 01:54
728x90

ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ž„ํฌํŠธ

import torch
import numpy as np
from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
import torch.nn.functional as F

๋ฐ์ดํ„ฐ์…‹ ์ƒ์„ฑ

n_dim=2
x_train, y_train = make_blobs(n_samples=50, n_features=n_dim, 
                              centers=[[1,1],[-1,-1],[1,-1],[-1,1]],
                              shuffle=True, cluster_std=0.3)
x_test, y_test = make_blobs(n_samples=20, n_features=n_dim, 
                              centers=[[1,1],[-1,-1],[1,-1],[-1,1]],
                              shuffle=True, cluster_std=0.3)
#make_blobs - ์˜ˆ์ œ์šฉ ๋ฐ์ดํ„ฐ์…‹์„ ๋งŒ๋“ค์–ด์ฃผ๋Š” ํ•จ์ˆ˜
#0,1,2,3ํด๋Ÿฌ์Šคํ„ฐ๋กœ ์ธ๋ฑ์‹ฑ

๊ฐ„๋‹จํ•œ ๋ถ„๋ฅ˜ 0๋˜๋Š” 1์„ ํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. 4๊ฐœ ๋ถ„๋ฅ˜๋ฅผ 2๊ฐœ๋กœ ์ค„์—ฌ 0๋˜๋Š” 1๋กœ ๋ผ๋ฒจ๋งํ•ฉ๋‹ˆ๋‹ค. 

#๋ ˆ์ด๋ธ” 2๊ฐœ๋กœ ์ค„์ด๊ธฐ 0,1
def label_map(y_, from_, to_):
  y = np.copy(y_)
  for f in from_:
    y[y_ ==f] = to_
  return y

y_train = label_map(y_train, [0,1],0)
y_train = label_map(y_train, [2,3],1)
y_test = label_map(y_test, [0,1],0)
y_test = label_map(y_test, [2,3],1)
y_train
array([1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0])

์ž˜ ๋ณ€ํ™˜๋˜์—ˆ๊ตฐ์š”

 

x_train= torch.FloatTensor(x_train)
y_train= torch.FloatTensor(y_train)
x_test= torch.FloatTensor(x_test)
y_test= torch.FloatTensor(y_test)
#numpy vector->pytorch tensor

๋„˜ํŒŒ์ด ๋ฒกํ„ฐ๋ฅผ ํŒŒ์ดํ† ์น˜ ํ…์„œ๋“ค๋กœ ๋ฐ”๊พธ๋ฉด ๋ฐ์ดํ„ฐ๋Š” ์ค€๋น„๊ฐ€ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. 

์ธ๊ณต์‹ ๊ฒฝ๋ง์„ NNํด๋ž˜์Šค๋กœ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. 

class NN(torch.nn.Module):
  def __init__(self,input_size,hidden_size):
    super(NN,self).__init__()
    #super(): NNํด๋ž˜์Šค๋Š” nn.Module ํด๋ž˜์Šค์˜ ์†์„ฑ๋“ค์„ ๊ฐ€์ง€๊ณ  ์ดˆ๊ธฐํ™”๋จ
    #input_size -nn์— ์ž…๋ ฅ๋˜๋Š” ๋ฐ์ดํ„ฐ์˜ ์ฐจ์›
    self.input_size = input_size
    self.hidden_size = hidden_size

    self.linear_1= torch.nn.Linear(self.input_size, self.hidden_size)
    self.relu = torch.nn.ReLU()
    self.linear_2= torch.nn.Linear(self.hidden_size,1)
    self.sigmoid = torch.nn.Sigmoid()

  def forward(self, input_tensor):#init์—์„œ ์ •์˜ํ•œ ํ•จ์ˆ˜๋ฅผ ์ฐจ๋ก€๋กœ ์ˆ˜ํ–‰ํ•ด์š”
    linear1 = self.linear_1(input_tensor)
    relu = self.relu(linear1)
    linear2 = self.linear_2(relu)
    output= self.sigmoid(linear2)
    return output

ํ•˜์ดํผํŒŒ๋ผ๋ฏธํ„ฐ ์„ค์ •

model= NN(2,5)
lr = 0.01
criterion = torch.nn.BCELoss()#์ด์ง„๊ต์ฐจ์—”ํŠธ๋กœํ”ผ, loss ์—ฐ์‚ฐ์„ ์œ„ํ•œ ํ•จ์ˆ˜
epochs=2500
optimizer= torch.optim.SGD(model.parameters(), lr)
#์ตœ์ ํ™”๋Š” ํ™•๋ฅ ์  ๊ฒฝ์‚ฌํ•˜๊ฐ•๋ฒ•(SGD)
#optimizer๋Š” step()ํ•จ์ˆ˜๋ฅผ ๋ถ€๋ฅผ๋•Œ๋งˆ๋‹ค ๊ฐ€์ค‘์น˜๋ฅผ ํ•™์Šต๋ฅ ๋งŒํผ ์—…๋ฐ์ดํŠธํ•˜๊ธฐ ๋•Œ๋ฌธ์— model.parameter()๋กœ ์ถ”์ถœํ•œ ๋ชจ๋ธ ๋‚ด๋ถ€์˜ ๊ฐ€์ค‘์น˜๋กธ ํ•™์Šต๋ฅ ์„ ์ž…๋ ฅ

ํ•™์Šต ์—†์ด ํ…Œ์ŠคํŠธํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. 

model.eval()
test_loss_before = criterion(model(x_test).squeeze(),y_test)#์Šค๋ฎˆ์ฆˆ๋กœ ๋ ˆ์ด๋ธ”๊ณผ ๋ชจ๋ธ์˜ ๊ฒฐ๊ด๊ฐ’์˜ ์ฐจ์›์„ ๋งž์ถฐ์คŒ
print("Before training, test loss is {}".format(test_loss_before.item()))

Before training, test loss is 0.750939667224884

loss ๊ฐ€ 0.75, 100๋ฒˆ ์ค‘์— 75๋ฒˆ์€ ํ‹€๋ฆฐ๋‹ค๋Š” ๋ง์ž…๋‹ˆ๋‹ค. ์ด๊ฑด ๋ถ„๋ฅ˜ ๋ชจ๋ธ์ด ๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค!

ํ•™์Šต์„ ์‹œ์ผœ์•ผ๊ฒ ์Šต๋‹ˆ๋‹ค. 

for epoch in range(epochs):
  model.train()
  optimizer.zero_grad()#๊ฒฝ์‚ฟ๊ฐ’์„ 0์œผ๋กœ ์„ค์ •
  train_output = model(x_train)#์ƒ์„ฑํ•œ ๋ชจ๋ธ์— ํ•™์Šต๋ฐ์ดํ„ฐ๋ฅผ ์ž…๋ ฅํ•ด ๊ฒฐ๊ด๊ฐ’์„ ๊ณ„์‚ฐํ•œ๋‹ค. 
  train_loss = criterion(train_output.squeeze(), y_train)#๊ฒฐ๊ด๊ฐ’์˜ ์ฐจ์›์„ ๋ ˆ์ด๋ธ”์˜ ์ฐจ์›๊ณผ ๊ฐ™๊ฒŒ ํ•˜๊ณ  ์˜ค์ฐจ ๊ณ„์‚ฐ
  if epoch % 100 ==0:
    print("train loss at {} is {}".format(epoch, train_loss.item()))
  train_loss.backward()#์‹ ๊ฒฝ๋ง์˜ ํ•ต์‹ฌ์ธ ์—ญ์ „ํŒŒ ์ˆ˜ํ–‰ - ์˜ค์ฐจ๊ฐ€ ์ค„์–ด๋“ฆ
  optimizer.step()

train loss at 0 is 0.7390405535697937
train loss at 100 is 0.7161856293678284
train loss at 200 is 0.7002339363098145
train loss at 300 is 0.6866344213485718
train loss at 400 is 0.6734730005264282
train loss at 500 is 0.6594039797782898
train loss at 600 is 0.6435436010360718
train loss at 700 is 0.6267176270484924
train loss at 800 is 0.6092957854270935
train loss at 900 is 0.5918593406677246
train loss at 1000 is 0.5747905969619751
train loss at 1100 is 0.5576883554458618
train loss at 1200 is 0.5419909954071045
train loss at 1300 is 0.5264553427696228
train loss at 1400 is 0.510536789894104
train loss at 1500 is 0.49399593472480774
train loss at 1600 is 0.4769943654537201
train loss at 1700 is 0.45882469415664673
train loss at 1800 is 0.4398338198661804
train loss at 1900 is 0.4197229743003845
train loss at 2000 is 0.3998076319694519
train loss at 2100 is 0.3801983892917633
train loss at 2200 is 0.36158764362335205
train loss at 2300 is 0.34393927454948425
train loss at 2400 is 0.3267700970172882

model.eval()
test_loss_before = criterion(model(x_test).squeeze(),y_test)#์Šค๋ฎˆ์ฆˆ๋กœ ๋ ˆ์ด๋ธ”๊ณผ ๋ชจ๋ธ์˜ ๊ฒฐ๊ด๊ฐ’์˜ ์ฐจ์›์„ ๋งž์ถฐ์คŒ
print("test loss is {}".format(test_loss_before.item()))

์ด์ œ ํ•™์Šต๋œ ๋ชจ๋ธ์„ state_dict() ํ•จ์ˆ˜ ํ˜•ํƒœ๋กœ ๋ฐ”๊ฟ”์ค€ ํ›„ .pt ํŒŒ์ผ๋กœ ์ €์žฅํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. state_dict() ํ•จ์ˆ˜๋Š” ๋ชจ๋ธ ๋‚ด ๊ฐ€์ค‘์น˜๋“ค์ด {์—ฐ์‚ฐ์ด๋ฆ„ : ๊ฐ€์ค‘์น˜ ํ…์„œ์™€ ํŽธํ–ฅ ํ…์„œ}์™€ ๊ฐ™์€ ๋”•์…”๋„ˆ๋ฆฌ ํ˜•ํƒœ์˜ ๋ฐ์ดํ„ฐ๋“ค๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค.

torch.save(model.state_dict(), './model.pt')
print('state_dict format of the model: {}'.format(model.state_dict()))

state_dict format of the model: OrderedDict([('linear_1.weight', tensor([[-0.8449,  0.5479],
        [-0.7441, -0.6253],
        [-0.5887, -0.4028],
        [-1.2672, -1.0648],
        [ 0.5069, -0.8319]])), ('linear_1.bias', tensor([-0.1316, -0.1784,  0.8995, -0.3038,  0.2025])), ('linear_2.weight', tensor([[ 0.7081, -0.8817,  0.9360, -1.5587,  0.6440]])), ('linear_2.bias', tensor([-0.2706]))])

 

์ด .pt ํŒŒ์ผ๋กœ ์ƒˆ๋กœ์šด ์‹ ๊ฒฝ๋ง ๊ฐ์ฒด์— ์ด๋ฏธ ํ•™์Šต๋œ๊ฐ€์ค‘์น˜๋ฅผ ๋ฐ”๋กœ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

new_model = NN(2,5)
new_model.load_state_dict(torch.load('./model.pt'))

<All keys matched successfully>

new_model.eval()
print('๋ฒกํ„ฐ [-1,1]์ด ๋ ˆ์ด๋ธ” 1์„ ๊ฐ€์งˆ ํ™•๋ฅ ์€ {}'.format(new_model(torch.FloatTensor([-1,1])).item()))


๋ฒกํ„ฐ [-1,1]์ด ๋ ˆ์ด๋ธ” 1์„ ๊ฐ€์งˆ ํ™•๋ฅ ์€ 0.8373079299926758

 

 

์ „์ฒด ์ฝ”๋“œ ๊ตฌ๊ธ€ ์ฝ”๋žฉ์—์„œ ๋Œ๋ ค๋ณด๊ธฐ :

https://colab.research.google.com/drive/1fgFpuioEYbD-hVF6kdCG7Ulyn0RXvu1t?usp=sharing

๋ฐ˜์‘ํ˜•