Basic Classification with Pytorch

Basic Classification with Pytorch

  • 이번 post 는 pytorch 를 활용해 기초적인 분류 모델링을 해보면서, pytorch에 익숙함을 높이는 것이 목적입니다.
1
2
3
4
5
6
7
8
9
10
11
12
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim

import numpy as np
import matplotlib.pyplot as plt

import warnings
warnings.filterwarnings("ignore")
%matplotlib inline
%config InlineBackend.figure_format = 'retina'

1. Binary Classification

  1. Modeling
  2. Sigmoid
  3. Loss : Binary Cross Entropy

1.1 Generate Data

1
2
3
4
5
6
7
8
9
10
11
12
# plotting function
def plot_scatter(W_, xy, labels):
for k, color in [(0, 'b'), (1, 'r')]:
idx = labels.flatten() == k
plt.scatter(xy[idx, 0], xy[idx, 1], c=color)

x1 = np.linspace(-0.1, 1.1)
x2 = -W_[1] / W_[2] * x1 - W_[0] / W_[2]
plt.plot(x1, x2, '--k')

plt.grid()
plt.show()
1
2
3
4
5
6
7
# Generate data

W = np.array([-4./5, 3./4., 1.0])

xy = np.random.rand(30, 2)
labels = np.zeros(len(xy))
labels[W[0] + W[1] * xy[:, 0] + W[2] * xy[:, 1] > 0] = 1
1
plot_scatter(W, xy, labels)

png

1.2 Train data

  • Generate 한 data 로 부터, x 축 값, y 축 값, augmented term 으로 3가지 column 을 만들어 train data 로 만들어 줍니다.
  • 또한 대응 되는 label 도 model 에 적합한 모양으로 바꾸어 줍니다.
1
2
3
4
x_train = torch.FloatTensor([[1.0, xval, yval] for xval, yval in xy])
y_train = torch.FloatTensor(labels).view(-1, 1)
print(x_train[:5])
print(y_train[:5])
tensor([[1.0000, 0.0192, 0.6049],
        [1.0000, 0.0485, 0.2529],
        [1.0000, 0.2412, 0.9115],
        [1.0000, 0.9764, 0.1665],
        [1.0000, 0.9021, 0.5825]])
tensor([[0.],
        [0.],
        [1.],
        [1.],
        [1.]])

1.3 Modeling

  • Linear Model 형태와 Sigmoid 함수, Loss function 은 cross entropy 를 활용해 모델링을 합니다.
  • 여기선, 내장되어있는 함수들을 되도록 사용하지 않고, Low level 로 코드를 작성해 보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Low level modeling
parameter_W = torch.FloatTensor([[-0.5, 0.7, 1.8]]).view(-1, 1)
parameter_W.requires_grad_(True)

optimizer = optim.SGD([parameter_W], lr=0.01)

epochs = 10000

for epoch in range(1, epochs + 1):
# Prediction
y_hat = F.sigmoid(torch.matmul(x_train, parameter_W))

# Loss function
loss = (-y_train * torch.log(y_hat) - (1 - y_train) * torch.log((1 - y_hat))).sum().mean()

# Backprop & update
optimizer.zero_grad()
loss.backward()
optimizer.step()

if epoch % 1000 == 0:
print("epoch {} -- loss {}".format(epoch, loss.data))
epoch 1000 -- loss 6.368619441986084
epoch 2000 -- loss 4.5249152183532715
epoch 3000 -- loss 3.654862403869629
epoch 4000 -- loss 3.122910261154175
epoch 5000 -- loss 2.7545464038848877
epoch 6000 -- loss 2.4800000190734863
epoch 7000 -- loss 2.2651939392089844
epoch 8000 -- loss 2.091233253479004
epoch 9000 -- loss 1.9466761350631714
epoch 10000 -- loss 1.8241318464279175
1
parameter_W.data.numpy()
array([[-16.748823],
       [ 16.618748],
       [ 17.622692]], dtype=float32)
  • 아래 그림을 보면, Train이 잘 된 것을 알 수 있습니다.
1
plot_scatter(parameter_W.data.numpy(), xy, labels)

png

2. Multiclass Classification

2.1 Generate Data

  • 이번에는 3개의 label 을 가지고 있는 classification 을 Modeling 해 보겠습니다.
  • 또한, High Level 로 pytorch 의 추상 클래스를 이용해 모델링 해보겠습니다.
1
2
3
4
5
6
7
8
9
10
11
12
def plot_scatter(W1, W2, xy, labels):
for k, color in [(0, 'b'), (1, 'r'), (2, 'y')]:
idx = labels.flatten() == k
plt.scatter(xy[idx, 0], xy[idx, 1], c=color)

x1 = np.linspace(-0.6, 1.6)
x2 = -W1[1] / W1[2] * x1 - W1[0] / W1[2]
x3 = -W2[1] / W2[2] * x1 - W2[0] / W2[2]
plt.plot(x1, x2, '--k')
plt.plot(x1, x3, '--k')

plt.show()
1
2
3
4
5
6
7
8
9
# Generate data

W1 = np.array([-1, 3./4., 1.0])
W2 = np.array([-1./5, 3./4., 1.0])

xy = 2 * np.random.rand(100, 2) - 0.5
labels = np.zeros(len(xy))
labels[(W1[0] + W1[1] * xy[:, 0] + W1[2] * xy[:, 1] > 0)] = 1
labels[(W2[0] + W2[1] * xy[:, 0] + W2[2] * xy[:, 1] < 0)] = 2
1
plot_scatter(W1, W2, xy, labels)

png

2.2 Train data

1
2
3
4
x_train = torch.FloatTensor([[1.0, xval, yval] for xval, yval in xy])
y_train = torch.LongTensor(labels)
print(x_train[-5:])
print(y_train[-5:])
tensor([[ 1.0000,  0.9641,  1.3851],
        [ 1.0000, -0.4445,  1.0595],
        [ 1.0000,  1.0854, -0.1216],
        [ 1.0000,  0.8707,  0.1640],
        [ 1.0000,  0.7043,  1.3483]])
tensor([1, 0, 0, 0, 1])

2.3 Modeling

1
2
3
4
5
6
7
class MultiModel(nn.Module):
def __init__(self):
super().__init__()
self.linear = nn.Linear(3, 3)

def forward(self, x):
return self.linear(x)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
model = MultiModel()

optimizer = optim.SGD(model.parameters(), lr=0.01)

epochs = 10000

for epoch in range(1, epochs + 1):
y_hat = model(x_train)

loss = F.cross_entropy(y_hat, y_train)

optimizer.zero_grad()
loss.backward()
optimizer.step()

if epoch % 1000 == 0:
print("epoch {} -- loss {}".format(epoch, loss.data))
epoch 1000 -- loss 0.6635385155677795
epoch 2000 -- loss 0.5513403415679932
epoch 3000 -- loss 0.4890784025192261
epoch 4000 -- loss 0.44675758481025696
epoch 5000 -- loss 0.4151267111301422
epoch 6000 -- loss 0.39017024636268616
epoch 7000 -- loss 0.369760125875473
epoch 8000 -- loss 0.35262930393218994
epoch 9000 -- loss 0.3379631042480469
epoch 10000 -- loss 0.3252090811729431

2.4 Accuracy 계산

  • Accuracy 가 96 % 로 비교적 잘 분류 된 것을 확인 할 수 있습니다.
1
2
accuracy = (torch.ByteTensor(model(x_train).max(dim=1)[1] == y_train)).sum().item() / len(y_train)
print("Accuracy: {}".format(accuracy))
Accuracy: 0.96
Author

Emjay Ahn

Posted on

2019-05-06

Updated on

2019-07-17

Licensed under

Comments