IT_World

[Pytorch] Python으로 딥 러닝 모델 개발하기 본문

Artificial intelligence, AI/Pytorch

[Pytorch] Python으로 딥 러닝 모델 개발하기

engine 2021. 5. 12. 10:32

딥 러닝을 통한 예측 모델링은 현대 개발자가 알아야 할 기술이다.

PyTorch는 Facebook에서 개발 및 유지 관리하는 최고의 오픈 소스 딥 러닝 프레임 워크이다.

핵심에서 PyTorch는 그래프 기반 모델에서 효율적인 계산과 자동 미분을 수행할 수 있는 수학적 라이브러리이다. 이를 직접 달성하는 것은 어렵지만 다행히도 최신 PyTorch API는 딥 러닝 모델 모음을 쉽게 개발할 수 있는 클래스와 관용구를 제공한다.

이 자습서에서는 PyTorch에서 딥 러닝 모델을 개발하기위한 단계별 가이드를 발견한다.

이 자습서를 완료하면 다음을 알게된다.

  • Torch와 PyTorch의 차이점과 PyTorch가 작동하는지 설치하고 확인하는 방법
  • PyTorch 모델의 5 단계 수명주기 및 모델 정의, 적합 및 평가 방법
  • 회귀, 분류 및 예측 모델링 작업을 위한 PyTorch 딥 러닝 모델을 개발하는 방법

PyTorch 튜토리얼 

이 튜토리얼의 초점은 일반적인 딥 러닝 모델 개발 작업에 PyTorch API를 사용하는 것이다. 우리는 딥 러닝의 수학과 이론에 뛰어들지 않을 것이다.

  1. PyTorch 설치 방법
    1. PyTorch 설치 방법
    2. PyTorch가 설치되었는지 확인하는 방법
  2. PyTorch 딥 러닝 모델 수명주기
    1. 1 단계 : 데이터 준비
    2. 2 단계 : 모델 정의
    3. 3 단계 : 모델 훈련
    4. 4 단계 : 모델 평가
    5. 5 단계 : 예측하기
  3. PyTorch 딥 러닝 모델을 개발하는 방법
    1. 이진 분류를 위한 MLP를 개발하는 방법
    2. 다중 클래스 분류를위한 MLP를 개발하는 방법
    3. 회귀 용 MLP를 개발하는 방법
    4. 이미지 분류를위한 CNN을 개발하는 방법

1. PyTorch 설치하기

ubuntu mac window cmd 창을 열고 밑 두줄을 입력해준다.

pip install torch
pip install torchvision

2. PyTorch가 설치되었는지 확인하는 방법

버전확인을 위한 파이썬 파일

import torch
print(torch.__version__)

torch 버전을 확인할 수 있다.

2. PyTorch 딥 러닝 모델 수명주기

이 섹션에서는 모델을 정의하는 데 사용할 수 있는 딥 러닝 모델 및 PyTorch API의 수명주기를 알아볼 수 있다.

모델에는 수명주기가 있다.

수명주기의 5 단계는 다음과 같다.

1. 데이터 준비

2. 모델 정의

3. 모델 훈련

4. 모델 평가

5. 예측

차례로 각 단계를 자세히 살펴보자

 

1 단계 : 데이터 준비

첫 번째 단계는 데이터를 로드하고 준비하는 것이다.

신경망 모델에는 숫자 입력 데이터와 숫자 출력 데이터가 필요하다.

표준 Python 라이브러리를 사용하여 CSV 파일과 같은 테이블 형식 데이터를 로드하고 준비할 수 있다. 예를 들어 Pandas를 사용하여 CSV 파일을 로드할 수 있고 scikit-learn의 도구를 사용하여 클래스 레이블과 같은 범주 형 데이터를 인코딩할 수 있다.

PyTorch는 dataset load하기 위해 확장하고 맞춤 설정할 수 있는 Dataset Class 제공한다 .

예를 들어 데이터 세트 개체의 생성자는 데이터 파일 (예 : CSV 파일)을 로드할 수 있다. 그런 다음 데이터 세트의 길이 (행 또는 샘플 수)를 가져오는 데 사용할 수 있는__len __ () 함수와 인덱스별로 특정 샘플을 가져오는 데 사용되는 __getitem __ () 함수 를 재정의 할 수 있다.

데이터 세트를 로드할 때 확장 또는 인코딩과 같은 필요한 변환을 수행할 수도 있다.

Custom Dataset 클래스의 스켈레톤은 아래와 같다.

# dataset definition
class CSVDataset(Dataset):
    # load the dataset
    def __init__(self, path):
        # store the inputs and outputs
        self.X = ...
        self.y = ...

    # number of rows in the dataset
    def __len__(self):
        return len(self.X)

    # get a row at an index
    def __getitem__(self, idx):
        return [self.X[idx], self.y[idx]]

로드되면 PyTorch는 모델 학습 및 평가 중에 Dataset 인스턴스 를 탐색할 수 있는Dataset Class 제공한다.

train dataset, test dataset 및 유효성 검사 데이터 세트에 대한 DataLoader 인스턴스를 만들 수 있다.

random_split () 함수는 열차 테스트 세트로 데이터 세트를 split 하는 데 사용될 수 있다.일단 분할되면 데이터 세트에서 선택한 행을 일괄 처리 크기 및 매 세대마다 shuffle 해야 하는지 여부와 함께 DataLoader에 제공할 수 있다.

예를 들어 데이터 세트에서 선택한 행 샘플을 전달하여DataLoader를 정의 할 수 있다 

...
# create the dataset
dataset = CSVDataset(...)
# select rows from the dataset
train, test = random_split(dataset, [[...], [...]])
# create a data loader for train and test sets
train_dl = DataLoader(train, batch_size=32, shuffle=True)
test_dl = DataLoader(test, batch_size=1024, shuffle=False)
...
# train the model
for i, (inputs, targets) in enumerate(train_dl):
	...

2 단계 : 모델 정의

다음 단계는 model definition 하는 것이다.

PyTorch에서 모델을 정의하는 관용구에는 Module Class를를 확장하는 클래스 정의가 포함된다.

클래스의 생성자는 모델의 레이어를 정의하고 forward () 함수는 모델의 정의된 레이어를 통해 입력을 전달하는 방법을 재정의한다.

완전히 연결된 계층을 위한 선형, 컨볼루션 레이어를 위한 Conv2 d, 풀링 레이어를 위한 MaxPool2d와 같은 많은 레이어를 사용할 수 있다. 활성화 함수는 ReLU, Softmax, Sigmoid와 같은 계층으로 정의될 수 있다.
아래는 하나의 레이어를 가진 단순한 MLP 모델의 예이다.

# model definition
class MLP(Module):
    # define model elements
    def __init__(self, n_inputs):
        super(MLP, self).__init__()
        self.layer = Linear(n_inputs, 1)
        self.activation = Sigmoid()

    # forward propagate input
    def forward(self, X):
        X = self.layer(X)
        X = self.activation(X)
        return X

주어진 레이어의 가중치는 레이어가 생성자에 정의된 후에 초기화될 수도 있다.
일반적인 예로는 Xavier 및 Heweight 초기화 체계가 있다. 

...
xavier_uniform_(self.layer.weight)

3단계: 모델 교육
교육 프로세스에서는 손실 함수와 최적화 알고리즘을 정의해야 한다.
일반적인 손실 함수는 다음과 같다.

BCELoss: 이진 분류를 위한 이진 교차 엔트로피 손실
CrossEntropyLoss: 다중 클래스 분류를 위한 범주형 교차 엔트로피 손실
MSELoss: 회귀 분석의 평균 제곱 손실

심층 학습 신경망 훈련을 위한 손실 및 손실 함수
확률적 경사 하강은 최적화를 위해 사용되며, 표준 알고리듬은 Adam(아담)과 같은 알고리즘의 다른 버전을 사용할 수 있지만 SGD 클래스에 의해 제공된다.

# define the optimization
criterion = MSELoss()
optimizer = SGD(model.parameters(), lr=0.01, momentum=0.9)

모델을 교육하려면 교육 데이터 세트에 대한 DataLoader를 열거해야 한다.
첫째, train epochs 의 수에 loop가필요하다. 그런 다음 stochastic gradient descent(확률적 경사 하강)에 대한 mini-batches(미니 배치)에 inner loop(내부 루프)가 필요하다.

...
# enumerate epochs
for epoch in range(100):
    # enumerate mini batches
    for i, (inputs, targets) in enumerate(train_dl):
    	...

모델에 대한 각 업데이트는 다음과 같은 일반적인 패턴을 포함한다.

  • 마지막 오류 그라디언트를 지운다.
  • 모델을 통해 입력을 전달한다.
  • 모델 출력에 대한 손실을 계산한다.
  • 모델을 통해 오류를 역전 파한다.
  • 손실을 줄이기 위해 모델을 업데이트하자
...
# clear the gradients
optimizer.zero_grad()
# compute the model output
yhat = model(inputs)
# calculate loss
loss = criterion(yhat, targets)
# credit assignment
loss.backward()
# update model weights
optimizer.step()

4 단계 : 모델 평가

모델이 적합하면 테스트 데이터 세트에서 평가할 수 있다.

이는 테스트 데이터 세트에 DataLoader 를 사용하고 테스트 세트에 대한 예측을 수집 한 다음 예측을 테스트 세트의 예상 값과 비교하고 성능 메트릭을 계산하여 수행할 수 있다.

...
for i, (inputs, targets) in enumerate(test_dl):
    # evaluate the model on the test set
    yhat = model(inputs)
    ...

5 단계 : 예측하기

적합 모델을 사용하여 새 데이터를 예측할 수 있다.

예를 들어 단일 이미지 또는 단일 데이터 행이 있고 예측을 원할 수 있다.

이를 위해서는 데이터를데이터 구조로 PyTorch Tensor에 래핑 해야 한다.

Tensor는 데이터를 보관하기 위한 NumPy 배열의 PyTorch 버전이며, 학습할 때 모델 그래프에서 backward () 호출과 같은 자동 미분 작업을 수행할 수 있다.

자동 미분 그래프에서 Tensor를 분리하고 NumPy 함수를 호출하여 NumPy 배열을 검색할 수 있지만 예측도 Tensor가 된다.가된다.

...
# convert row to data
row = Variable(Tensor([row]).float())
# make prediction
yhat = model(row)
# retrieve numpy array
yhat = yhat.detach().numpy()

이제 상위 수준 및 모델 수명주기에서 PyTorch API에 익숙해졌으므로 몇 가지 표준 딥 러닝 모델을 처음부터 개발할 수 있는 방법을 살펴보자.

 

3. PyTorch 딥 러닝 모델을 개발하는 방법

이 섹션에서는 MLP (Multilayer Perceptron) 및 CNN (Convolutional Neural Networks)을 포함한 표준 딥 러닝 모델을 사용하여 개발, 평가 및 예측하는 방법을 알아본다. Multilayer Perceptron 모델 또는 줄여서 MLP는 표준 완전 연결 신경망 모델이다. 각 노드는 이전 레이어의 모든 출력에 연결되고 각 노드의 출력은 다음 레이어의 노드에 대한 모든 입력에 연결되는 노드의 레이어로 구성된다. MLP는 하나 이상의 완전 연결 계층이 있는 모델이다. 이 모델은 테이블 형식 데이터, 즉 각 변수에 대해 하나의 열과 각 변수에 대해 하나의 행이 있는 테이블 또는 스프레드 시트에서 보는 데이터에 적합하다. MLP로 탐색할 수 있는 세 가지 예측 모델링 문제가 있다. 이진 분류, 다중 클래스 분류 및 회귀다. 이러한 각 경우에 대해 실제 데이터 세트에 모델을 맞춘다.

3.1. 이진 분류를 위한 MLP를 개발하는 방법

이진 분류를위한 MLP를 시연하기 위해 Ionosphere 바이너리 (2 클래스) 분류 데이터 세트를 사용한다.

이 데이터 세트에는 대기에 구조가 있는지 여부를 예측하는 것이 포함된다.

# pytorch mlp for binary classification
from numpy import vstack
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import accuracy_score
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
from torch.utils.data import random_split
from torch import Tensor
from torch.nn import Linear
from torch.nn import ReLU
from torch.nn import Sigmoid
from torch.nn import Module
from torch.optim import SGD
from torch.nn import BCELoss
from torch.nn.init import kaiming_uniform_
from torch.nn.init import xavier_uniform_

# dataset definition
class CSVDataset(Dataset):
    # load the dataset
    def __init__(self, path):
        # load the csv file as a dataframe
        df = read_csv(path, header=None)
        # store the inputs and outputs
        self.X = df.values[:, :-1]
        self.y = df.values[:, -1]
        # ensure input data is floats
        self.X = self.X.astype('float32')
        # label encode target and ensure the values are floats
        self.y = LabelEncoder().fit_transform(self.y)
        self.y = self.y.astype('float32')
        self.y = self.y.reshape((len(self.y), 1))

    # number of rows in the dataset
    def __len__(self):
        return len(self.X)

    # get a row at an index
    def __getitem__(self, idx):
        return [self.X[idx], self.y[idx]]

    # get indexes for train and test rows
    def get_splits(self, n_test=0.33):
        # determine sizes
        test_size = round(n_test * len(self.X))
        train_size = len(self.X) - test_size
        # calculate the split
        return random_split(self, [train_size, test_size])

# model definition
class MLP(Module):
    # define model elements
    def __init__(self, n_inputs):
        super(MLP, self).__init__()
        # input to first hidden layer
        self.hidden1 = Linear(n_inputs, 10)
        kaiming_uniform_(self.hidden1.weight, nonlinearity='relu')
        self.act1 = ReLU()
        # second hidden layer
        self.hidden2 = Linear(10, 8)
        kaiming_uniform_(self.hidden2.weight, nonlinearity='relu')
        self.act2 = ReLU()
        # third hidden layer and output
        self.hidden3 = Linear(8, 1)
        xavier_uniform_(self.hidden3.weight)
        self.act3 = Sigmoid()

    # forward propagate input
    def forward(self, X):
        # input to first hidden layer
        X = self.hidden1(X)
        X = self.act1(X)
         # second hidden layer
        X = self.hidden2(X)
        X = self.act2(X)
        # third hidden layer and output
        X = self.hidden3(X)
        X = self.act3(X)
        return X

# prepare the dataset
def prepare_data(path):
    # load the dataset
    dataset = CSVDataset(path)
    # calculate split
    train, test = dataset.get_splits()
    # prepare data loaders
    train_dl = DataLoader(train, batch_size=32, shuffle=True)
    test_dl = DataLoader(test, batch_size=1024, shuffle=False)
    return train_dl, test_dl

# train the model
def train_model(train_dl, model):
    # define the optimization
    criterion = BCELoss()
    optimizer = SGD(model.parameters(), lr=0.01, momentum=0.9)
    # enumerate epochs
    for epoch in range(100):
        # enumerate mini batches
        for i, (inputs, targets) in enumerate(train_dl):
            # clear the gradients
            optimizer.zero_grad()
            # compute the model output
            yhat = model(inputs)
            # calculate loss
            loss = criterion(yhat, targets)
            # credit assignment
            loss.backward()
            # update model weights
            optimizer.step()

# evaluate the model
def evaluate_model(test_dl, model):
    predictions, actuals = list(), list()
    for i, (inputs, targets) in enumerate(test_dl):
        # evaluate the model on the test set
        yhat = model(inputs)
        # retrieve numpy array
        yhat = yhat.detach().numpy()
        actual = targets.numpy()
        actual = actual.reshape((len(actual), 1))
        # round to class values
        yhat = yhat.round()
        # store
        predictions.append(yhat)
        actuals.append(actual)
    predictions, actuals = vstack(predictions), vstack(actuals)
    # calculate accuracy
    acc = accuracy_score(actuals, predictions)
    return acc

# make a class prediction for one row of data
def predict(row, model):
    # convert row to data
    row = Tensor([row])
    # make prediction
    yhat = model(row)
    # retrieve numpy array
    yhat = yhat.detach().numpy()
    return yhat

# prepare the data
path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/ionosphere.csv'
train_dl, test_dl = prepare_data(path)
print(len(train_dl.dataset), len(test_dl.dataset))
# define the network
model = MLP(34)
# train the model
train_model(train_dl, model)
# evaluate the model
acc = evaluate_model(test_dl, model)
print('Accuracy: %.3f' % acc)
# make a single prediction (expect class=1)
row = [1,0,0.99539,-0.05889,0.85243,0.02306,0.83398,-0.37708,1,0.03760,0.85243,-0.17755,0.59755,-0.44945,0.60536,-0.38223,0.84356,-0.38542,0.58212,-0.32192,0.56971,-0.29674,0.36946,-0.47357,0.56811,-0.51171,0.41078,-0.46168,0.21266,-0.34090,0.42267,-0.54487,0.18641,-0.45300]
yhat = predict(row, model)
print('Predicted: %.3f (class=%d)' % (yhat, yhat.round()))

실행하면 먼저 학습 및 테스트 데이터 세트의 모양을 보고 한 다음 모델을 적합하고 테스트 데이터 세트에서 평가한 다음 단일 데이터 행에 대한 예측이 이루어진다.

 

3.2. 다중 클래스 분류를 위한 MLP를 개발하는 방법

Iris flowers 다중 클래스 분류 데이터 세트를 사용하여 다중 클래스 분류를위한 MLP를 시연하자

이 문제는 꽃의 측정치가 주어진 붓꽃의 종을 예측하는 것과 관련이 있다.

다중 클래스 분류라는 점을 감안할 때 모델은 출력 계층의 각 클래스에 대해 하나의 노드를 가져야 하며 softmax 활성화 함수를 사용해야 한다.손실 함수는 정수 인코딩 된 클래스 레이블 (예 : 한 클래스의 경우 0, 다음 클래스의 경우 1 등)에 적합한 교차 엔트로피이다.

홍채 꽃 데이터 세트에서 MLP를 피팅하고 평가하는 전체 예제는 다음과 같다.

# pytorch mlp for multiclass classification
from numpy import vstack
from numpy import argmax
from pandas import read_csv
from sklearn.preprocessing import LabelEncoder
from sklearn.metrics import accuracy_score
from torch import Tensor
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
from torch.utils.data import random_split
from torch.nn import Linear
from torch.nn import ReLU
from torch.nn import Softmax
from torch.nn import Module
from torch.optim import SGD
from torch.nn import CrossEntropyLoss
from torch.nn.init import kaiming_uniform_
from torch.nn.init import xavier_uniform_

# dataset definition
class CSVDataset(Dataset):
    # load the dataset
    def __init__(self, path):
        # load the csv file as a dataframe
        df = read_csv(path, header=None)
        # store the inputs and outputs
        self.X = df.values[:, :-1]
        self.y = df.values[:, -1]
        # ensure input data is floats
        self.X = self.X.astype('float32')
        # label encode target and ensure the values are floats
        self.y = LabelEncoder().fit_transform(self.y)

    # number of rows in the dataset
    def __len__(self):
        return len(self.X)

    # get a row at an index
    def __getitem__(self, idx):
        return [self.X[idx], self.y[idx]]

    # get indexes for train and test rows
    def get_splits(self, n_test=0.33):
        # determine sizes
        test_size = round(n_test * len(self.X))
        train_size = len(self.X) - test_size
        # calculate the split
        return random_split(self, [train_size, test_size])

# model definition
class MLP(Module):
    # define model elements
    def __init__(self, n_inputs):
        super(MLP, self).__init__()
        # input to first hidden layer
        self.hidden1 = Linear(n_inputs, 10)
        kaiming_uniform_(self.hidden1.weight, nonlinearity='relu')
        self.act1 = ReLU()
        # second hidden layer
        self.hidden2 = Linear(10, 8)
        kaiming_uniform_(self.hidden2.weight, nonlinearity='relu')
        self.act2 = ReLU()
        # third hidden layer and output
        self.hidden3 = Linear(8, 3)
        xavier_uniform_(self.hidden3.weight)
        self.act3 = Softmax(dim=1)

    # forward propagate input
    def forward(self, X):
        # input to first hidden layer
        X = self.hidden1(X)
        X = self.act1(X)
        # second hidden layer
        X = self.hidden2(X)
        X = self.act2(X)
        # output layer
        X = self.hidden3(X)
        X = self.act3(X)
        return X

# prepare the dataset
def prepare_data(path):
    # load the dataset
    dataset = CSVDataset(path)
    # calculate split
    train, test = dataset.get_splits()
    # prepare data loaders
    train_dl = DataLoader(train, batch_size=32, shuffle=True)
    test_dl = DataLoader(test, batch_size=1024, shuffle=False)
    return train_dl, test_dl

# train the model
def train_model(train_dl, model):
    # define the optimization
    criterion = CrossEntropyLoss()
    optimizer = SGD(model.parameters(), lr=0.01, momentum=0.9)
    # enumerate epochs
    for epoch in range(500):
        # enumerate mini batches
        for i, (inputs, targets) in enumerate(train_dl):
            # clear the gradients
            optimizer.zero_grad()
            # compute the model output
            yhat = model(inputs)
            # calculate loss
            loss = criterion(yhat, targets)
            # credit assignment
            loss.backward()
            # update model weights
            optimizer.step()

# evaluate the model
def evaluate_model(test_dl, model):
    predictions, actuals = list(), list()
    for i, (inputs, targets) in enumerate(test_dl):
        # evaluate the model on the test set
        yhat = model(inputs)
        # retrieve numpy array
        yhat = yhat.detach().numpy()
        actual = targets.numpy()
        # convert to class labels
        yhat = argmax(yhat, axis=1)
        # reshape for stacking
        actual = actual.reshape((len(actual), 1))
        yhat = yhat.reshape((len(yhat), 1))
        # store
        predictions.append(yhat)
        actuals.append(actual)
    predictions, actuals = vstack(predictions), vstack(actuals)
    # calculate accuracy
    acc = accuracy_score(actuals, predictions)
    return acc

# make a class prediction for one row of data
def predict(row, model):
    # convert row to data
    row = Tensor([row])
    # make prediction
    yhat = model(row)
    # retrieve numpy array
    yhat = yhat.detach().numpy()
    return yhat

# prepare the data
path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/iris.csv'
train_dl, test_dl = prepare_data(path)
print(len(train_dl.dataset), len(test_dl.dataset))
# define the network
model = MLP(4)
# train the model
train_model(train_dl, model)
# evaluate the model
acc = evaluate_model(test_dl, model)
print('Accuracy: %.3f' % acc)
# make a single prediction
row = [5.1,3.5,1.4,0.2]
yhat = predict(row, model)
print('Predicted: %s (class=%d)' % (yhat, argmax(yhat)))

실행하면 먼저 학습 및 테스트 데이터 세트의 모양을 보고 한 다음 모델을 적합하고 테스트 데이터 세트에서 평가한다. 마지막으로 단일 데이터 행에 대한 예측이 이루어진다.

3.3. 회귀 용 MLP를 개발하는 방법

보스턴 주택 회귀 데이터 세트를 사용하여 회귀 예측 모델링을 위한 MLP를 시연한다.

이 문제는 집과 이웃의 속성을 기반으로 주택 가치를 예측하는 것과 관련이 있으며, 단일 숫자 값을 예측하는 회귀 문제이다. 따라서 출력 계층에는 단일 노드가 있으며 기본 또는 선형 활성화 함수 (활성화 함수 없음)를 사용한다. 모델을 피팅할 때 평균 제곱 오차 (mse) 손실이 최소화된다.

이것은 분류가 아니라 회귀이기 때문에 분류 정확도를 계산할 수 없다.

보스턴 주택 데이터 세트에서 MLP를 피팅하고 평가하는 전체 예제는 다음과 같다.

# pytorch mlp for regression
from numpy import vstack
from numpy import sqrt
from pandas import read_csv
from sklearn.metrics import mean_squared_error
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
from torch.utils.data import random_split
from torch import Tensor
from torch.nn import Linear
from torch.nn import Sigmoid
from torch.nn import Module
from torch.optim import SGD
from torch.nn import MSELoss
from torch.nn.init import xavier_uniform_

# dataset definition
class CSVDataset(Dataset):
    # load the dataset
    def __init__(self, path):
        # load the csv file as a dataframe
        df = read_csv(path, header=None)
        # store the inputs and outputs
        self.X = df.values[:, :-1].astype('float32')
        self.y = df.values[:, -1].astype('float32')
        # ensure target has the right shape
        self.y = self.y.reshape((len(self.y), 1))

    # number of rows in the dataset
    def __len__(self):
        return len(self.X)

    # get a row at an index
    def __getitem__(self, idx):
        return [self.X[idx], self.y[idx]]

    # get indexes for train and test rows
    def get_splits(self, n_test=0.33):
        # determine sizes
        test_size = round(n_test * len(self.X))
        train_size = len(self.X) - test_size
        # calculate the split
        return random_split(self, [train_size, test_size])

# model definition
class MLP(Module):
    # define model elements
    def __init__(self, n_inputs):
        super(MLP, self).__init__()
        # input to first hidden layer
        self.hidden1 = Linear(n_inputs, 10)
        xavier_uniform_(self.hidden1.weight)
        self.act1 = Sigmoid()
        # second hidden layer
        self.hidden2 = Linear(10, 8)
        xavier_uniform_(self.hidden2.weight)
        self.act2 = Sigmoid()
        # third hidden layer and output
        self.hidden3 = Linear(8, 1)
        xavier_uniform_(self.hidden3.weight)

    # forward propagate input
    def forward(self, X):
        # input to first hidden layer
        X = self.hidden1(X)
        X = self.act1(X)
         # second hidden layer
        X = self.hidden2(X)
        X = self.act2(X)
        # third hidden layer and output
        X = self.hidden3(X)
        return X

# prepare the dataset
def prepare_data(path):
    # load the dataset
    dataset = CSVDataset(path)
    # calculate split
    train, test = dataset.get_splits()
    # prepare data loaders
    train_dl = DataLoader(train, batch_size=32, shuffle=True)
    test_dl = DataLoader(test, batch_size=1024, shuffle=False)
    return train_dl, test_dl

# train the model
def train_model(train_dl, model):
    # define the optimization
    criterion = MSELoss()
    optimizer = SGD(model.parameters(), lr=0.01, momentum=0.9)
    # enumerate epochs
    for epoch in range(100):
        # enumerate mini batches
        for i, (inputs, targets) in enumerate(train_dl):
            # clear the gradients
            optimizer.zero_grad()
            # compute the model output
            yhat = model(inputs)
            # calculate loss
            loss = criterion(yhat, targets)
            # credit assignment
            loss.backward()
            # update model weights
            optimizer.step()

# evaluate the model
def evaluate_model(test_dl, model):
    predictions, actuals = list(), list()
    for i, (inputs, targets) in enumerate(test_dl):
        # evaluate the model on the test set
        yhat = model(inputs)
        # retrieve numpy array
        yhat = yhat.detach().numpy()
        actual = targets.numpy()
        actual = actual.reshape((len(actual), 1))
        # store
        predictions.append(yhat)
        actuals.append(actual)
    predictions, actuals = vstack(predictions), vstack(actuals)
    # calculate mse
    mse = mean_squared_error(actuals, predictions)
    return mse

# make a class prediction for one row of data
def predict(row, model):
    # convert row to data
    row = Tensor([row])
    # make prediction
    yhat = model(row)
    # retrieve numpy array
    yhat = yhat.detach().numpy()
    return yhat

# prepare the data
path = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv'
train_dl, test_dl = prepare_data(path)
print(len(train_dl.dataset), len(test_dl.dataset))
# define the network
model = MLP(13)
# train the model
train_model(train_dl, model)
# evaluate the model
mse = evaluate_model(test_dl, model)
print('MSE: %.3f, RMSE: %.3f' % (mse, sqrt(mse)))
# make a single prediction (expect class=1)
row = [0.00632,18.00,2.310,0,0.5380,6.5750,65.20,4.0900,1,296.0,15.30,396.90,4.98]
yhat = predict(row, model)
print('Predicted: %.3f' % yhat)

예제를 실행하면 먼저 학습 및 테스트 데이터 세트의 모양을 보고 한 다음 모델을 적합하고 테스트 데이터 세트에서 평가한다. 마지막으로 단일 데이터 행에 대한 예측이 이루어진다.

3.4. 이미지 분류를 위한 CNN을 개발하는 방법

Convolutional Neural Networks 또는 줄여서 CNN은 이미지 입력을 위해 설계된 네트워크 유형이다.

피처를 추출 하는convolutional layers(feature map)와 feature를를 가장 두드러진 요소로 추출하는 pooling layers가 있는가있는 모델로 구성된다.

CNN은 이미지를 입력으로 사용하는 다양한 작업에 사용될 수 있지만 이미지 분류 작업에 가장 적합하다.

사용된 dataset은 MNIST classification이다. 0에서 9 사이의 숫자로 분류되어야 하는 수만 개의 필기 숫자가 포함된다.

torchvision API는 이 데이터 세트를 직접 다운로드하고 로드할 수 있는 편리한 기능을 제공한다.

아래 예는 데이터 세트를 로드하고 처음 몇 개의 이미지를 플로팅 한다.

# load mnist dataset in pytorch
from torch.utils.data import DataLoader
from torchvision.datasets import MNIST
from torchvision.transforms import Compose
from torchvision.transforms import ToTensor
from matplotlib import pyplot
# define location to save or load the dataset
path = '~/.torch/datasets/mnist'
# define the transforms to apply to the data
trans = Compose([ToTensor()])
# download and define the datasets
train = MNIST(path, train=True, download=True, transform=trans)
test = MNIST(path, train=False, download=True, transform=trans)
# define how to enumerate the datasets
train_dl = DataLoader(train, batch_size=32, shuffle=True)
test_dl = DataLoader(test, batch_size=32, shuffle=True)
# get one batch of images
i, (inputs, targets) = next(enumerate(train_dl))
# plot some images
for i in range(25):
	# define subplot
	pyplot.subplot(5, 5, i+1)
	# plot raw pixel data
	pyplot.imshow(inputs[i][0], cmap='gray')
# show the figure
pyplot.show()

MNIST 데이터 세트에서 CNN 모델을 피팅하고 평가하는 전체 예제

# pytorch cnn for multiclass classification
from numpy import vstack
from numpy import argmax
from pandas import read_csv
from sklearn.metrics import accuracy_score
from torchvision.datasets import MNIST
from torchvision.transforms import Compose
from torchvision.transforms import ToTensor
from torchvision.transforms import Normalize
from torch.utils.data import DataLoader
from torch.nn import Conv2d
from torch.nn import MaxPool2d
from torch.nn import Linear
from torch.nn import ReLU
from torch.nn import Softmax
from torch.nn import Module
from torch.optim import SGD
from torch.nn import CrossEntropyLoss
from torch.nn.init import kaiming_uniform_
from torch.nn.init import xavier_uniform_

# model definition
class CNN(Module):
    # define model elements
    def __init__(self, n_channels):
        super(CNN, self).__init__()
        # input to first hidden layer
        self.hidden1 = Conv2d(n_channels, 32, (3,3))
        kaiming_uniform_(self.hidden1.weight, nonlinearity='relu')
        self.act1 = ReLU()
        # first pooling layer
        self.pool1 = MaxPool2d((2,2), stride=(2,2))
        # second hidden layer
        self.hidden2 = Conv2d(32, 32, (3,3))
        kaiming_uniform_(self.hidden2.weight, nonlinearity='relu')
        self.act2 = ReLU()
        # second pooling layer
        self.pool2 = MaxPool2d((2,2), stride=(2,2))
        # fully connected layer
        self.hidden3 = Linear(5*5*32, 100)
        kaiming_uniform_(self.hidden3.weight, nonlinearity='relu')
        self.act3 = ReLU()
        # output layer
        self.hidden4 = Linear(100, 10)
        xavier_uniform_(self.hidden4.weight)
        self.act4 = Softmax(dim=1)

    # forward propagate input
    def forward(self, X):
        # input to first hidden layer
        X = self.hidden1(X)
        X = self.act1(X)
        X = self.pool1(X)
        # second hidden layer
        X = self.hidden2(X)
        X = self.act2(X)
        X = self.pool2(X)
        # flatten
        X = X.view(-1, 4*4*50)
        # third hidden layer
        X = self.hidden3(X)
        X = self.act3(X)
        # output layer
        X = self.hidden4(X)
        X = self.act4(X)
        return X

# prepare the dataset
def prepare_data(path):
    # define standardization
    trans = Compose([ToTensor(), Normalize((0.1307,), (0.3081,))])
    # load dataset
    train = MNIST(path, train=True, download=True, transform=trans)
    test = MNIST(path, train=False, download=True, transform=trans)
    # prepare data loaders
    train_dl = DataLoader(train, batch_size=64, shuffle=True)
    test_dl = DataLoader(test, batch_size=1024, shuffle=False)
    return train_dl, test_dl

# train the model
def train_model(train_dl, model):
    # define the optimization
    criterion = CrossEntropyLoss()
    optimizer = SGD(model.parameters(), lr=0.01, momentum=0.9)
    # enumerate epochs
    for epoch in range(10):
        # enumerate mini batches
        for i, (inputs, targets) in enumerate(train_dl):
            # clear the gradients
            optimizer.zero_grad()
            # compute the model output
            yhat = model(inputs)
            # calculate loss
            loss = criterion(yhat, targets)
            # credit assignment
            loss.backward()
            # update model weights
            optimizer.step()

# evaluate the model
def evaluate_model(test_dl, model):
    predictions, actuals = list(), list()
    for i, (inputs, targets) in enumerate(test_dl):
        # evaluate the model on the test set
        yhat = model(inputs)
        # retrieve numpy array
        yhat = yhat.detach().numpy()
        actual = targets.numpy()
        # convert to class labels
        yhat = argmax(yhat, axis=1)
        # reshape for stacking
        actual = actual.reshape((len(actual), 1))
        yhat = yhat.reshape((len(yhat), 1))
        # store
        predictions.append(yhat)
        actuals.append(actual)
    predictions, actuals = vstack(predictions), vstack(actuals)
    # calculate accuracy
    acc = accuracy_score(actuals, predictions)
    return acc

# prepare the data
path = '~/.torch/datasets/mnist'
train_dl, test_dl = prepare_data(path)
print(len(train_dl.dataset), len(test_dl.dataset))
# define the network
model = CNN(1)
# # train the model
train_model(train_dl, model)
# evaluate the model
acc = evaluate_model(test_dl, model)
print('Accuracy: %.3f' % acc)

 

 

PyTorch Tutorial: How to Develop Deep Learning Models with Python

Predictive modeling with deep learning is a skill that modern developers need to know. PyTorch is the premier open-source deep […]

machinelearningmastery.com

 

Comments