검색
검색
공개 노트 검색
회원가입로그인

파이토치로 인공신경망 만들기 (how to make neural network)

PyTorch로 간단한 신경망 만들기 (MLP - Multilayer Perceptron 예제)

일단 인공 신경망을 배워야 하는 이유는 지금 모든 AI 의 핵심이기 때문이다.

LLM은 인공 신경망의 한 종류일 뿐이다. (강력하기는 하지만...ㅋㅋ)

인공신경망은 입력값과 출력값의 데이터 셋이 있으면 모든 종류의 패턴을 학습할 수 있다.

오늘은 이 인공신경망을 만들고 활용하면서 이해해 보자.

신경망을 쉽게 쓸 수 있게 만들어 놓은 파이토치를 사용해서 진행해 보자.

import torch
import torch.nn as nn
import torch.optim as optim

# 1. 데이터 생성
num_samples = 100
x_train = torch.rand(num_samples, 2) * 10
y_train = (x_train.sum(dim=1) >= 5).float().unsqueeze(1)

x_test = torch.rand(20, 2) * 10
y_test = (x_test.sum(dim=1) >= 5).float().unsqueeze(1)

# 2. 모델 정의
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(2, 8)
        self.fc2 = nn.Linear(8, 1)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = self.sigmoid(self.fc2(x))
        return x

model = SimpleNN()

# 3. 손실 함수와 옵티마이저
criterion = nn.BCELoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

# 4. 학습
epochs = 20
for epoch in range(epochs):
    model.train()
    optimizer.zero_grad()
    outputs = model(x_train)
    loss = criterion(outputs, y_train)
    loss.backward()
    optimizer.step()
    print(f"Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}")

# 5. 평가
model.eval()
with torch.no_grad():
    predictions = model(x_test)
    predictions = (predictions > 0.5).float()
    accuracy = (predictions == y_test).sum() / y_test.size(0)
    print(f"Test Accuracy: {accuracy:.4f}")

파이토치가 깔려 있지 않다면 pip install pytorch

x_train 에 입력 데이터를 만들어 주고 y_train 에 결과 데이터를 만들어 준다. 두 데이터의 합이 5 이상이면 1, 5미만이면 0을 출력하는 간단한 인공 신경망을 만들어 보자.

num_samples = 100
x_train = torch.rand(num_samples, 2) * 10
y_train = (x_train.sum(dim=1) >= 5).float().unsqueeze(1)

x_test = torch.rand(20, 2) * 10
y_test = (x_test.sum(dim=1) >= 5).float().unsqueeze(1)

나중에 모델이 나왔을 때 테스트해서 정확도를 측정하기 위해 test 셋도 만들어 준다.

그 다음에 모델을 정의해 준다.

# 2. 모델 정의
class SimpleNN(nn.Module):
    def __init__(self):
        super(SimpleNN, self).__init__()
        self.fc1 = nn.Linear(2, 8)
        self.fc2 = nn.Linear(8, 1)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        x = torch.relu(self.fc1(x))
        x = self.sigmoid(self.fc2(x))
        return x

입력 값은 2이고, 두번째 층에서는 8개의 은닉층을 가진다. 마지막으로 1개의 출력 값을 내보낸다.

즉 숫자 2개를 넣으면 그 합이 5이상인지 미만인지 파악을 해주는 간단한 인공 신경망이다.

forward 함수는 다음 층으로 이동할 때 처리를 하는 함수이다.

relu 는 가중치를 곱하고 더한 후 bias 를 더한 값이 0보다 작으면 0을 출력하고 이보다 크면 그대로 출력하는 방식이다.

sigmoid 는 0~1 사이의 값을 출력해서 확률값처럼 사용할 수 있다.

model = SimpleNN()

# 3. 손실 함수와 옵티마이저
criterion = nn.BCELoss()
optimizer = optim.Adam(model.parameters(), lr=0.01)

모델을 로드하고 손실함수와 옵티마이저를 세팅해준다. 옵티마이저는 Adam 을 활용했다.

# 4. 학습
epochs = 20
for epoch in range(epochs):
    model.train()
    optimizer.zero_grad()
    outputs = model(x_train)
    loss = criterion(outputs, y_train)
    loss.backward()
    optimizer.step()
    print(f"Epoch [{epoch+1}/{epochs}], Loss: {loss.item():.4f}")

실제로 학습을 하는 부분이다.

20번의 배치를 돈다. 모델에 x_train 값을 넣고 손실을 측정한 후 역전파 알고리즘으로 가중치를 조정해준다.

이 가중치가 신경망이 학습하는 핵심 요소이다.

단순 선형 모델을 생각해 보자.

y=w1​⋅x1​+w2​⋅x2​+b

w가 가중치이고 x가 입력 데이터이다. b는 bias를 각 뉴런의 결과값에 추가적으로 더해지는 값이다.

이렇게 해서 하나의 굉장히 큰 식이 나오게 되고 이것이 우리가 말하는 인공 지능 모델이 된다.

파이토치로 인공신경망 만들기 (how to make neural network) image 1

(여기에서 매개 변수의 수는 가중치와 바이어스 개수를 모두 더한 값이 된다.)

위의 코드는 위와 같은 식의 인공 신경망이 된다.

input 1과 2에 1.0 과 3.0의 값을 입력하는 예시를 생각해 보자.

먼저 인공 신경망이 이 값을 처리한다. 그 후 답을 보여줘서 역전파 알고리즘과 옵티마이저로 가중치와 바이어스를 조정한다.

그 다음 데이터를 넣고 이 과정을 반복하면서 가중치와 바이어스를 조정한다.

이렇게 해서 하나의 모델이 나오게 된다.

이제 학습한 모델을 평가하고 새로운 데이터셋으로 사용까지 해보자.

# 5. 평가
model.eval()
with torch.no_grad():
    predictions = model(x_test)
    predictions = (predictions > 0.5).float()
    accuracy = (predictions == y_test).sum() / y_test.size(0)
    print(f"Test Accuracy: {accuracy:.4f}")

# 새로운 데이터 입력
new_data = torch.tensor([[1.0, 10.0]])  # 입력 데이터는 2개의 숫자로 이루어져야 함

# 모델 예측
model.eval()  # 평가 모드
with torch.no_grad():  # 학습 비활성화
    prediction = model(new_data)  # 모델에 입력 데이터 전달
    prediction_class = (prediction > 0.5).float()  # 0.5 이상이면 1, 아니면 0

print(
    f"Input: {new_data.tolist()}, Prediction: {prediction.item():.4f}, Class: {int(prediction_class.item())}"
)

Test Accuracy: 0.9500

Input: [[1.0, 10.0]], Prediction: 0.9940, Class: 1

이런 식으로 테스트 정확도가 95%가 나왔고,

1.0과 10.0을 입력했을 때 1로 합이 5보다 크다는 결과가 나왔다.

이게 인공 신경망이다.

이 모델을 사용해서 이제 데이터를 처리할 수 있다.

예를 들어 1.0과 3.0을 입력했다.

위의 인공 신경망 그림에서 각 선은 가중치이고 이를 곱한다. 두번째 층에서 각 값을 합한 후 바이어스를 더한다.

0보다 작으면 0을 출력하고 0보다 크면 그대로 나간다. (relu)

이와 같은 방식으로 진행해서 마지막 출력이 0인지 1인지를 본다.

이렇게 해서 각 입력값들의 합이 5보다 작은지 큰지 알 수 있는 것이다.

마지막 코드로는 모델을 저장하고 불러온 후 가중치를 출력까지 해보자.

# 모델 저장
torch.save(model.state_dict(), "model.pth")

# 모델 불러오기
model = SimpleNN()
model.load_state_dict(torch.load("model.pth"))

# 가중치와 편향 출력
print(model.state_dict())

이렇게 나온다.

OrderedDict({
'fc1.weight': 
tensor([[-0.6229,  0.1654],
        [-0.4121,  0.0796],
        [ 0.8066,  0.6311],
        [-0.4425, -0.4426],
        [-0.2636,  0.8107],
        [ 0.4037, -0.4993],
        [-0.2698, -0.0083],
        [ 0.4120, -0.3938]]),
'fc1.bias': 
tensor([-0.6044,  0.4252, -0.5025,  0.4929,  0.2736,  0.4973, -0.4285,  0.5349]), 
'fc2.weight': tensor([[-0.1019, -0.2412,  0.1628,  0.2304,  0.4744,  0.0496, -04,  0.4744,  0.0496, -0.0103,  0.4446]]), 
'fc2.bias': tensor([0.4292])})

예를 들어 1.0과 3.0을 입력했을 때 [1.0, 3.0]

첫번째 레이어의 첫번째 뉴런은 1.0*-0.6229+3.0*0.1654-0.6044 = −0.7311 이 되고 ReLU에 의해서 0이 된다.

이런 식으로 쭈욱 계산이 되어 마지막 출력에 0 또는 1이 나온다.

이게 chatgpt, 테슬라 자동운전 등 모든 인공 신경망에 쓰이는 원리이다.

다른 데이터 적용

간단한 문자 데이터 처리 예제

문장을 입력받아 긍정(1)인지 부정(0)인지 예측하는 신경망

import torch
import torch.nn as nn
import torch.optim as optim
from sklearn.feature_extraction.text import CountVectorizer

# 데이터 준비
texts = ["I love this", "This is bad", "I hate it", "So good", "Really bad"]
labels = [1, 0, 0, 1, 0]  # 긍정: 1, 부정: 0

# 텍스트를 숫자로 변환 (원-핫 인코딩 유사 방식)
vectorizer = CountVectorizer()  # 단어 빈도 기반 벡터화
X = vectorizer.fit_transform(texts).toarray()  # 텍스트 → 숫자
X = torch.tensor(X, dtype=torch.float32)
y = torch.tensor(labels, dtype=torch.float32).unsqueeze(1)

# 간단한 신경망 정의
class SimpleNN(nn.Module):
    def __init__(self, input_size):
        super(SimpleNN, self).__init__()
        self.fc = nn.Linear(input_size, 1)  # 입력 크기 → 출력 1개
        self.sigmoid = nn.Sigmoid()  # 활성화 함수

    def forward(self, x):
        x = self.fc(x)
        return self.sigmoid(x)

# 모델 초기화
model = SimpleNN(input_size=X.size(1))

# 손실 함수와 옵티마이저
criterion = nn.BCELoss()  # 이진 크로스엔트로피 손실
optimizer = optim.Adam(model.parameters(), lr=0.01)

# 학습
for epoch in range(100):
    optimizer.zero_grad()
    outputs = model(X)
    loss = criterion(outputs, y)
    loss.backward()
    optimizer.step()

# 예측
new_texts = ["I love it", "Really hate this"]
new_X = vectorizer.transform(new_texts).toarray()  # 텍스트 → 숫자
new_X = torch.tensor(new_X, dtype=torch.float32)
predictions = model(new_X)
print(predictions)

이런 식으로 다양한 데이터를 처리할 수 있다.

이미지

이미지의 경우 픽셀 값으로 이미 숫자로 표현되어 있다. 이를 0과 1사이로 정규화한 후 CNN (합성곱 신경망을) 사용해 처리하면 된다.

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms

# 데이터셋 로드 및 전처리
transform = transforms.Compose([
    transforms.ToTensor(),  # 이미지를 텐서로 변환
    transforms.Normalize((0.5,), (0.5,))  # 정규화
])
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
train_loader = torch.utils.data.DataLoader(train_dataset, batch_size=32, shuffle=True)

# 간단한 CNN 정의
class SimpleCNN(nn.Module):
    def __init__(self):
        super(SimpleCNN, self).__init__()
        self.conv1 = nn.Conv2d(1, 32, kernel_size=3)  # 합성곱 레이어
        self.fc1 = nn.Linear(32 * 26 * 26, 10)  # 완전 연결 레이어

    def forward(self, x):
        x = torch.relu(self.conv1(x))  # 합성곱 + ReLU
        x = x.view(x.size(0), -1)  # Flatten
        x = self.fc1(x)  # 완전 연결 레이어
        return x

# 모델 초기화
model = SimpleCNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# 학습
for epoch in range(1):
    for images, labels in train_loader:
        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

print("Training Complete!")

CNN은 이미지나 시각 데이터에서 패턴을 자동으로 찾아내는 신경망이다. 예를 들어, 고양이 사진을 입력받으면 고양이의 모양, 귀, 눈 같은 특징을 인식해서 "고양이"인지 판단할 수 있다.

시사점

인공 신경망은 입력과 출력의 데이터셋을 준비할 수 있는 모든 데이터의 패턴을 학습할 수 있다.

내가 자주 쓰는 작업들을 학습시킬 수 도 있고 chatgpt 처럼 거대한 언어 모델을 학습할 수 도 있다.

이것이 우리의 삶을 변화시킬까? 아마 거의 모든 것이 바뀌지 않을까.

공유하기
카카오로 공유하기
페이스북 공유하기
트위터로 공유하기
url 복사하기
조회수 : 202
heart
T
페이지 기반 대답
AI Chat