Python

pytorch 이미지 모델링 II

해파리냉채무침 2024. 2. 26. 01:38

모델 정의

nn.Module 상속 클래스 정의

  • nn.Module을 상속받는 클래스 정의
  • __init__(): 모델에서 사용될 모듈과 활성화 함수 등을 정의
  • forward(): 모델에서 실행되어야 하는 연산을 정의
class Model(nn.Module):
  def __init__(self,inputs):#초기화
    super(Model,self).__init__()
    self.layer = nn.Linear(inputs,1)
    self.activation = nn.Sigmoid()

  def forward(self,x):
    x = self.layer(x)
    x = self.activation(x)
    return x
model = Model(1)
print(list(model.children()))
print(list(model.modules()))

 

nn.Sequential을 이용한 신경망 정의

  • nn.Sequential 객체로 그 안에 각 모듈을 순차적으로 실행
  • __init__()에서 사용할 네트워크 모델들을 nn.Sequential로 정의 가능
  • forward()에서 실행되어야 할 계산을 가독성 높게 작성 가능
#여러 layer를 시퀀스로 묶어서 실행
class Model(nn.Module):
  def __init__(self):
    super(Model,self).__init__()
    self.layer1 = nn.Sequential(
        nn.Conv2d(in_channels=3,out_channels=64,kernel_size= 5),
        nn.ReLU(inplace=True),
        nn.MaxPool2d(2)
            )
    self.layer2 = nn.Sequential(
        nn.Conv2d(in_channels=64,out_channels=30,kernel_size= 5),
        nn.ReLU(inplace=True),
        nn.MaxPool2d(2)
            )
    self.layer3= nn.Sequential(
        nn.Linear(in_features=30*5*5,out_features=10,bias=True),
        nn.ReLU(inplace=True)
            )

    def forward(self,x):
      x = self.layer1(x)
      x = self.layer2(x)
      x= x.view(x.shape[0],-1) #텐서 모양변경, shape 첫번째값 기준으로 알아서 쫙 알아서 계산되게
      x = self.layer3(x)
      return x

모델 파라미터

손실 함수(Loss function)

  • 예측 값과 실제 값 사이의 오차 측정
  • 학습이 진행되면서 해당 과정이 얼마나 잘 되고 있는지 나타내는 지표
  • 모델이 훈련되는 동안 최소화될 값으로 주어진 문제에 대한 성공 지표
  • 손실 함수에 따른 결과를 통해 학습 파라미터를 조정
  • 최적화 이론에서 최소화 하고자 하는 함수
  • 미분 가능한 함수 사용
  • 파이토치의 주요 손실 함수
    • torch.nn.BCELoss: 이진 분류를 위해 사용
    • torch.nn.CrossEntropyLoss: 다중 클래스 분류를 위해 사용
    • torch.nn.MSELoss: 회귀 모델에서 사용
criterion = nn.MSELoss()
criterion = nn.CrossEntropyLoss()

옵티마이저(Optimizer)

  • 손실 함수를 기반으로 모델이 어떻게 업데이트되어야 하는지 결정 (특정 종류의 확률적 경사 하강법 구현)
  • optimizer는 step()을 통해 전달받은 파라미터를 모델 업데이트
  • 모든 옵티마이저의 기본으로 torch.optim.Optimizer(params, defaults) 클래스 사용
  • zero_grad()를 이용해 옵티마이저에 사용된 파라미터들의 기울기를 0으로 설정
  • torch.optim.lr_scheduler를 이용해 에포크(epochs)에 따라 학습률(learning rate) 조절
  • 파이토치의 주요 옵티마이저: optim.Adadelta, optim.Adagrad, optim.Adam, optim.RMSprop, optim.SGD
 

학습률 스케줄러(Learning rate scheduler)

  • 학습시 특정 조건에 따라 학습률을 조정하여 최적화 진행
  • 일정 횟수 이상이 되면 학습률을 감소(decay)시키거나 전역 최소점(global minimum) 근처에 가면 학습률을 줄이는 등
  • 파이토치의 학습률 스케줄러 종류
    • optim.lr_scheduler.LambdaLR: 람다(lambda) 함수를 이용해 그 결과를 학습률로 설정
    • optim.lr_scheduler.StepLR: 단계(step)마다 학습률을 감마(gamma) 비율만큼 감소
    • optim.lr_scheduler.MultiStepLR: StepLR과 비슷하지만 특정 단계가 아니라 지정된 에포크에만 감마 비율로 감소
    • optim.lr_scheduler.ExponentialLR: 에포크마다 이전 학습률에 감마만큼 곱함
    • optim.lr_scheduler.CosineAnnealingLR: 학습률을 코사인(cosine) 함수의 형태처럼 변화시켜 학습률을 커지기도 하고 작아지기도 함
    • optim.lr_scheduler.ReduceLROnPlateau: 학습이 잘되는지 아닌지에 따라 동적으로 학습률 변화

지표(metrics)

  • 모델의 학습과 테스트 단계를 모니터링
import torchmetrics
preds = torch.randn(10,5).softmax(dim=-1) #마지막 차원 선택
target = torch.randint(5, (10,))
print(preds,target)

acc = torchmetrics.functional.accuracy(preds, target,multiclass=True)

print(acc)

이런 에러가 발생하는데 해결을 못했다..

선형 회귀 모델 (Linear Regression Model)

 데이터 생성

X = torch.randn(200,1)*10
y = X+3 * torch.randn(200,1)
plt.scatter(X.numpy(),y.numpy())
plt.ylabel('y')
plt.xlabel('x')
plt.grid()
plt.show()

모델 정의 및 파라미터

class LinearRegressionModel(nn.Module):
  def __init__(self):
    super(LinearRegressionModel,self).__init__()
    self.linear = nn.Linear(1,1)

  def forward(self,x):
    pred = self.linear(x)
    return pred
model = LinearRegressionModel()
print(model)
print(list(model.parameters()))

w,b = model.parameters()
w1,b1 =w[0][0].item(),b[0].item()
x1= np.array([-30,30])
y1= w1*x1+b1
plt.plot(x1,y1,'r')
plt.scatter(X,y)
plt.grid()
plt.show()

손실함수 및 옵티마이저

import torch.optim as optim
criterion = nn.MSELoss()
optimizer = optim.SGD(model.parameters(),lr=0.001)

모델 학습

epochs = 100
losses = []
for epoch in range(epochs):
  optimizer.zero_grad()

  y_pred = model(X)
  loss = criterion(y_pred,y)
  losses.append(loss.item())
  loss.backward()

  optimizer.step()
plt.plot(range(epochs),losses)
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.show()

w,b = model.parameters()
w1,b1 =w[0][0].item(),b[0].item()
x1= np.array([-30,30])
y1= w1*x1+b1
plt.plot(x1,y1,'r')
plt.scatter(X,y)
plt.grid()
plt.show()

FashionMNIST 분류 모델

gpu 설정

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
device
device(type='cpu')

데이터 로드

transform = transforms.Compose([transforms.ToTensor(),
                              transforms.Normalize((0.5,),(0.5,))])
trainset = datasets.FashionMNIST(root='/content/',
                                train=True, download=True,
                                transform= transform)
testset = datasets.FashionMNIST(root='/content/',
                                train=False, download=True,
                                transform= transform)
train_loader = DataLoader(trainset,batch_size=128,shuffle=True,num_workers=2)
test_loader = DataLoader(testset,batch_size=128,shuffle=False,num_workers=2)
images,labels = next(iter(train_loader))
images.shape,labels.shape
(torch.Size([128, 1, 28, 28]), torch.Size([128]))
labels_map = {
    0: 'T-shirt',
    1: 'Trouser',
    2: 'Pullover',
    3: 'Dress',
    4: 'Coat',
    5: 'Sandal',
    6: 'Shirt',
    7: 'Sneaker',
    8 : 'Bag',
    9: 'Ankle Boot',
}
figure = plt.figure(figsize=(12,12))
cols,rows = 4,4
for i in range(1,cols*rows+1):
  image = images[i].squeeze()
  label_idx = labels[i].item()
  label = labels_map[label_idx]

  figure.add_subplot(rows,cols,i)
  plt.title(label)
  plt.axis('off')
  plt.imshow(image,cmap='gray')

plt.show()

모델 정의 및 파라미터

class NeuralNet(nn.Module):
  def __init__(self):
    super(NeuralNet,self).__init__()

    self.conv1 = nn.Conv2d(1,6,3)
    self.conv2 = nn.Conv2d(6,16,3)
    self.fc1 = nn.Linear(16*5*5,120)
    self.fc2 = nn.Linear(120,84) #in feature out feature
    self.fc3 = nn.Linear(84,10)

  def forward(self,x):
    x = F.max_pool2d(F.relu(self.conv1(x)),(2,2))
    x = F.max_pool2d(F.relu(self.conv2(x)),2)
    x = x.view(-1,self.num_flat_features(x))
    x = F.relu(self.fc1(x))
    x = F.relu(self.fc2(x))
    x = self.fc3(x)
    return x #x?

  def num_flat_features(self,x):
    size = x.size()[1:]
    num_features =1
    for s in size:
      num_features *=  s

    return num_features

net = NeuralNet()
print(net)

params = list(net.parameters())
print(len(params))
print(params[0].size())
10
torch.Size([6, 1, 3, 3])
input = torch.randn(1,1,28,28)
out = net(input)
print(out)

tensor([[ 0.0138, 0.0918, -0.0301, 0.1120, -0.0359, 0.0909, -0.0113, 0.1072, 0.0808, 0.1693]], grad_fn=<AddmmBackward0>)

손실함수와 옵티마이저

criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(),lr=0.001,momentum=0.9)

모델학습

배치수 확인

total_batch = len(train_loader)
print(total_batch)

469

for epoch in range(10):
  running_loss = 0.0

  for i, data in enumerate(train_loader,0):
    inputs,labels = data

    optimizer.zero_grad() #초기화

    output= net(inputs)
    loss = criterion(output,labels)
    loss.backward()
    optimizer.step()

    running_loss += loss.item()

    if i% 100 == 99:
      print('Epoch : {}, iter: {}, loss {}'.format(epoch+1,i+1,running_loss/2000))
      running_loss = 0.0

모델의 저장 및 로드

  • torch.save: net.state_dict()를 저장
  • torch.load: load_state_dict로 모델을 로드
path = './fahion_mnist.pth'
torch.save(net.state_dict(),path) #현재 상태를 해당하는 path에 저장
net = NeuralNet()
net.load_state_dict(torch.load(path))
net.parameters

 

모델 테스트

def imshow(image):
  image = image/2 +0.5
  npimg = image.numpy()
  fig = plt.figure(figsize=(16,8))
  plt.imshow(np.transpose(npimg,(1,2,0)))
  plt.show()
import torchvision

dataiter = iter(test_loader)
images,labels = next(dataiter)
imshow(torchvision.utils.make_grid(images[:6]))

outputs= net(images)
_,predicted = torch.max(outputs,1)#10개중에 하나고르기
print(predicted)

print(''.join('{}.'.format(labels_map[int(predicted[j].numpy())]) for j in  range(0,6)  ))

Ankle Boot.Pullover.Trouser.Trouser.Shirt.Trouser.

correct = 0
total = 0
with torch.no_grad():
  for data in test_loader:
    images,labels = data
    outputs = net(images)
    _,predicted = torch.max(outputs.data,1)
    total += labels.size(0)
    correct += (predicted ==labels).sum().item()

print(100 * correct / total)

82. 25

 

 

출처

https://youtu.be/k60oT_8lyFw?si=9hjnyJLzxR4sVyZ4