이 기사에서는 신경망을 처음부터 구축하는 방법을 배우기 위해 신경망의 후드를 살펴볼 것입니다.
https://www.freecodecamp.org/news/how-to-build-a-neural-network-with-pytorch/
딥 러닝에서 저를 가장 흥분 시키는 한 가지는 처음부터 무언가를 빌드 하기 위해 코드를 수정하는 것입니다. 하지만 쉬운 일이 아니며 다른 사람에게 그렇게 하는 방법을 가르치는 것은 훨씬 더 어렵습니다.
저는 Fast.ai 과정을 통해 작업 해 왔으며 이 블로그는 제 경험에서 큰 영감을 받았습니다.
더 이상 지체하지 않고 신경망을 이해하는 멋진 여정을 시작하겠습니다.
신경망은 어떻게 작동합니까?
신경망의 높은 수준의 작동을 이해하는 것으로 시작하겠습니다.
신경망은 데이터 세트를 가져와 예측을 출력합니다. 그렇게 간단합니다.
예를 들어 보겠습니다.
축구 팬이 아닌 친구 중 한 명이 유명한 축구 선수의 오래된 사진 (예 : Lionel Messi)을 가리키고 그에 대해 묻는다고 가정 해 보겠습니다.
잠시 후 축구 선수를 식별 할 수 있습니다. 그 이유는 당신이 그의 사진을 천 번 본 적이 있기 때문입니다. 따라서 사진이 오래되었거나 희미한 조명에서 찍은 경우에도 그를 식별 할 수 있습니다.
하지만 내가 유명한 야구 선수의 사진을 보여 주면 어떻게 될까요 (그리고 전에는 야구 경기를 한 번도 본 적이 없습니다)? 해당 플레이어를 인식 할 수 없습니다. 이 경우 사진이 선명하고 밝아도 누구인지 알 수 없습니다.
이것은 신경망에 사용되는 것과 동일한 원리입니다. 우리의 목표가 고양이와 개를 인식하는 신경망을 구축하는 것이라면 신경망에 개와 고양이의 사진을 보여줍니다.
보다 구체적으로, 우리는 개의 신경망 사진을 보여주고 이것이 개라고 말합니다. 그런 다음 고양이 사진을 보여주고 고양이를 식별합니다.
고양이와 개 이미지로 신경망을 훈련하면 이미지에 고양이가 포함되어 있는지 개가 포함되어 있는지 쉽게 분류 할 수 있습니다. 요컨대 개에서 고양이를 인식 할 수 있습니다.
하지만 신경망에 말이나 독수리의 사진을 보여 주면 결코 말이나 독수리로 식별 되지 않습니다. 말이나 독수리의 사진을 본 적이 없기 때문입니다. 우리가 그 동물을 본 적이 없기 때문입니다.
신경망의 기능을 향상 시키려면 신경망이 분류하기를 원하는 모든 동물의 사진을 보여 주기만 하면 됩니다. 지금까지 알고 있는 것은 고양이와 개뿐입니다.
훈련에 사용하는 데이터 세트는 우리 손의 문제에 크게 의존합니다. 트윗에 긍정적인지 부정적인 감정이 있는지 분류하려면 해당 레이블이 긍정적 또는 부정적인 많은 트윗이 포함 된 데이터 세트를 원할 것입니다.
이제 데이터 세트에 대한 높은 수준의 개요와 신경망이 해당 데이터에서 학습하는 방법이 있으므로 신경망이 작동하는 방식에 대해 자세히 살펴 보겠습니다.
신경망 이해
이미지에서 숫자 3과 7을 분류하는 신경망을 구축 할 것입니다.
하지만 신경망을 구축하기 전에 어떻게 작동하는지 더 깊이 이해해야 합니다.
우리가 신경망에 전달하는 모든 이미지는 숫자의 무리 일뿐입니다. 즉, 각 이미지의 크기는 28x28입니다. 즉, 행렬처럼 28 개의 행과 28 개의 열이 있습니다.
우리는 각 숫자를 완전한 이미지로 보지만 신경망에서는 0에서 255까지 범위의 숫자 일뿐입니다.
다음은 숫자 5의 픽셀 표현입니다.
위에서 볼 수 있듯이 행렬처럼 28 개의 행과 28 개의 열 (인덱스가 0에서 시작하여 27에서 끝남)이 있습니다. 신경망은 이 28x28 행렬 만 볼 수 있습니다.
좀 더 자세한 내용을 보여주기 위해 픽셀 값과 함께 음영을 표시했습니다. 이미지를 자세히 살펴보면 255에 가까운 픽셀 값은 더 어둡고 0에 가까운 값은 더 밝다는 것을 알 수 있습니다.
PyTorch에서는 행렬이라는 용어를 사용하지 않습니다. 대신 텐서라는 용어를 사용합니다. PyTorch의 모든 숫자는 텐서로 표시됩니다. 이제부터는 행렬 대신 텐서라는 용어를 사용할 것입니다.
신경망 시각화
신경망은 여러 개의 뉴런과 계층을 가질 수 있습니다.
다음은 신경망의 모습입니다.
그림의 그리스 문자에 혼동하지 마십시오. 나는 당신을 위해 그것을 분해 할 것이다 :
환자의 이름, 체온, 혈압, 심장 상태, 월급 및 연령이 포함 된 데이터 세트를 기반으로 환자의 생존 여부를 예측하는 경우를 생각해보십시오.
우리의 데이터 세트에서는 환자의 생존 여부를 예측하는 데 온도, 혈압, 심장 상태 및 연령 만 매우 중요합니다. 따라서 더 높은 중요성을 보여주기 위해 이러한 값에 더 높은 가중치를 할당합니다.
그러나 환자의 이름과 월급과 같은 기능은 환자의 생존율에 거의 또는 전혀 영향을 미치지 않습니다. 따라서 중요성을 줄이기 위해 이러한 기능에 더 작은 가중치 값을 할당합니다.
위 그림에서 x1, x2, x3 ... xn은 위의 예에서와 같이 이미지 데이터 또는 혈압이나 심장 상태와 같은 특징의 경우 픽셀 값일 수 있는 데이터 세트의 특징입니다.
특성 값에는 w1j, w2j, w3j ... wnj라고 하는 해당 가중치 값이 곱해집니다. 곱해진 값은 합산 되어 다음 레이어로 전달됩니다.
최적의 가중치 값은 신경망 훈련 중에 학습됩니다. 가중치 값은 올바른 예측 수를 최대화하는 방식으로 지속적으로 업데이트 됩니다.
활성화 함수는 우리의 경우 시그 모이 드 함수일 뿐입니다. 시그 모이 드에 전달하는 모든 값은 0과 1 사이의 값으로 변환됩니다. 우리는 신경망 예측 위에 시그 모이 드 함수를 배치하여 0과 1 사이의 값을 얻습니다.
신경망 모델 구축을 시작하면 시그 모이 드 계층의 중요성을 이해할 수 있습니다.
시그 모이 드보다 배우기 훨씬 쉬운 다른 활성화 함수가 많이 있습니다.
다음은 시그 모이 드 함수의 방정식입니다.
다이어그램에서 원형 모양의 노드를 뉴런이라고 합니다. 신경망의 각 계층에서 가중치는 입력 데이터와 곱해집니다.
레이어 수를 늘려 신경망의 깊이를 늘릴 수 있습니다. 해당 계층의 뉴런 수를 늘림으로써 계층의 용량을 향상 시킬 수 있습니다.
데이터 세트 이해
신경망을 훈련하기 위해 가장 먼저 필요한 것은 데이터 세트입니다.
신경망의 목표는 이미지에 숫자 3 또는 7이 포함되어 있는지 분류하는 것이므로 3과 7의 이미지로 신경망을 훈련해야 합니다. 이제 데이터 세트를 구축해 보겠습니다.
다행히 데이터 세트를 처음부터 만들 필요가 없습니다. 우리의 데이터 세트는 이미 PyTorch에 있습니다. 우리가 해야 할 일은 다운로드하고 기본적인 작업을 하는 것 뿐입니다.
PyTorch의 torchvision 라이브러리에서 MNIST (Modified National Institute of Standards and Technology)라는 데이터 세트를 다운로드해야 합니다.
이제 데이터 세트를 더 자세히 살펴 보겠습니다.
MNIST 데이터 세트 란 무엇입니까?
MNIST 데이터 세트에는 아래와 같이 해당 레이블과 함께 0에서 9까지의 손으로 쓴 숫자가 포함됩니다.
그래서 우리가 하는 일은 단순히 신경망에 숫자의 이미지와 그에 상응하는 레이블을 제공하여 신경망에 이것이 3 또는 7임을 알리는 것입니다.
데이터 세트를 준비하는 방법
다운로드 한 MNIST 데이터 세트에는 이미지와 해당 레이블이 있습니다.
레이블이 3 또는 7 인 이미지 만 인덱싱 하는 코드를 작성합니다. 따라서 우리는 3과 7의 데이터 세트를 얻습니다.
먼저 필요한 모든 라이브러리를 가져 오겠습니다.
import torch
from torchvision import datasets
import matplotlib.pyplot as plt
신경망 구축을 위한 PyTorch 라이브러리와 MNIST 데이터 세트 다운로드를 위한 torchvision 라이브러리를 가져옵니다. Matplotlib 라이브러리는 데이터 세트의 이미지를 표시하는 데 사용됩니다.
이제 데이터 세트를 준비하겠습니다.
mnist = datasets.MNIST('./data', download=True)
threes = mnist.data[(mnist.targets == 3)]/255.0
sevens = mnist.data[(mnist.targets == 7)]/255.0
len(threes), len(sevens)
위에서 배운 것처럼 PyTorch의 모든 것은 텐서로 표현됩니다. 따라서 데이터 세트도 텐서의 형태입니다.
첫 번째 줄에서 데이터 세트를 다운로드합니다. 대상 값이 3 또는 7 인 이미지 만 인덱싱하고 255로 나누어 정규화하여 별도로 저장합니다.
3과 7 텐서의 이미지 수를 제공하는 마지막 줄의 코드를 실행하여 인덱싱이 제대로 수행되었는지 확인할 수 있습니다.
이제 데이터 세트를 올바르게 준비했는지 확인하겠습니다.
def show_image(img):
plt.imshow(img)
plt.xticks([])
plt.yticks([])
plt.show()
show_image(threes[3])
show_image(sevens[8])
Matplotlib 라이브러리를 사용하여 이미지를 표시하는 함수를 만듭니다.
텐서의 모양을 인쇄하여 빠른 온 전성 검사를 수행해 보겠습니다.
print(threes.shape, sevens.shape)
모든 것이 올바르게 진행되면 3과 7의 크기가 각각 ([6131, 28, 28]) 및 ([6265, 28, 28])로 표시됩니다. 즉, 3 개의 경우 28x28 크기의 이미지가 6131 개이고 7 개의 경우 28x28 크기의 이미지가 6265 개 있습니다.
우리는 3과 7의 이미지로 두 개의 텐서를 만들었습니다. 이제 우리는 신경망에 공급할 단일 데이터 세트로 결합해야 합니다.
combined_data = torch.cat([threes, sevens])
combined_data.shape
PyTorch를 사용하여 두 개의 텐서를 연결하고 결합 된 데이터 세트의 모양을 확인합니다.
이제 데이터 세트의 이미지를 병합합니다.
flat_imgs = combined_data.view((-1, 28*28))
flat_imgs.shape
28x28 크기 이미지 각각이 784 개의 열 (28x28 = 784)이있는 단일 행이 되도록 이미지를 병합합니다. 따라서 모양은 ([12396, 784])로 변환됩니다.
결합 된 데이터 세트의 이미지에 해당하는 레이블을 만들어야 합니다.
target = torch.tensor([1]*len(threes)+[2]*len(sevens))
target.shape
3을 포함하는 이미지에 레이블 1을 할당하고 7을 포함하는 이미지에 레이블 0을 할당합니다.
신경망 훈련 방법
신경망을 훈련하려면 다음 단계를 따르십시오.
1 단계 : 모델 구축
아래에서 신경망의 작동 방식을 보여주는 가장 간단한 방정식을 볼 수 있습니다.
y = Wx + b
여기서 'y'라는 용어는 우리의 예측, 즉 3 또는 7을 나타냅니다. 'W'는 가중치 값을, 'x'는 입력 이미지를, 'b'는 편향 (가중치와 함께 예측에 도움이 됨)입니다.
간단히 말해 각 픽셀 값에 가중치 값을 곱하고 바이어스 값에 더합니다.
가중치와 바이어스 값은 예측하는 동안 각 픽셀 값의 중요성을 결정합니다.
우리는 3과 7을 분류하고 있으므로 예측할 클래스는 2 개뿐입니다.
따라서 이미지가 3이면 1, 이미지가 7이면 0을 예측할 수 있습니다. 이 단계에서 얻은 예측은 실수 일 수 있지만 모델 (신경망)이 0과 1 사이의 값을 예측하도록해야합니다.
이를 통해 0.5의 임계 값을 만들 수 있습니다. 즉, 예측 값이 0.5보다 작 으면 7입니다. 그렇지 않으면 3입니다.
시그 모이 드 함수를 사용하여 0과 1 사이의 값을 얻습니다.
앞에서 보여준 것과 동일한 방정식을 사용하여 시그 모이 드 함수를 생성합니다. 그런 다음 신경망의 값을 시그 모이 드로 전달합니다.
단일 레이어 신경망을 만들 것입니다.
비용이 매우 비싸기 때문에 각 가중치 값을 이미지의 각 픽셀과 곱하는 루프를 많이 만들 수 없습니다. 따라서 우리는 행렬 곱셈을 사용하여 한 번에 전체 곱셈을 수행하는 마술을 사용할 수 있습니다.
def sigmoid(x): return 1/(1+torch.exp(-x))
def simple_nn(data, weights, bias): return sigmoid((data@weights) + bias)
2 단계 : 손실 정의
이제 예측 값이 Ground Truth의 값과 얼마나 다른지 계산하려면 손실 함수가 필요합니다.
예를 들어, 예측 값이 0.3이지만 실측 값이 1이면 손실이 매우 높습니다. 따라서 우리 모델은 가중치와 편향을 업데이트하여 이러한 손실을 줄이려고 노력하여 예측이 실제 사실에 가까워 지도록 합니다.
손실 값을 확인하기 위해 평균 제곱 오차를 사용할 것입니다. 평균 제곱 오차는 예측 값과 실측 값 간의 차이 제곱의 평균을 찾습니다.
def error(pred, target): return ((pred-target)**2).mean()
3 단계 : 가중치 값 초기화
가중치와 편향을 무작위로 초기화합니다. 나중에 최상의 예측을 얻기 위해 이러한 값이 어떻게 업데이트 되는지 살펴 보겠습니다.
w = torch.randn((flat_imgs.shape[1], 1), requires_grad=True)
b = torch.randn((1, 1), requires_grad=True)
가중치 값의 모양은 다음과 같은 형식이어야 합니다.
(이전 계층의 뉴런 수, 다음 계층의 뉴런 수)
기울기 하강 법이라는 방법을 사용하여 가중치와 편향을 업데이트하여 올바른 예측 수를 최대로 만듭니다.
우리의 목표는 손실을 최적화 하거나 줄이는 것이므로 가장 좋은 방법은 기울기를 계산하는 것입니다.
손실 함수와 관련하여 각각의 모든 가중치와 편향을 미분해야 합니다. 그런 다음 가중치와 편향에서 이 값을 빼야 합니다.
이러한 방식으로 가중치와 편향 값이 업데이트 되어 모델이 좋은 예측을 할 수 있습니다.
함수를 최적화 하기 위해 매개 변수를 업데이트하는 것은 새로운 것이 아닙니다. 그라디언트를 사용하여 임의의 함수를 최적화 할 수 있습니다.
가중치 및 편향의 기울기를 계산하기 위해 특수 매개 변수 (Requires_grad라고 함)를 true로 설정했습니다.
4 단계 : 가중치 업데이트
우리의 예측이 사실에 가깝지 않다면 그것은 우리가 잘못된 예측을 했다는 것을 의미합니다. 이것은 우리의 가중치가 정확하지 않다는 것을 의미합니다. 따라서 좋은 예측을 얻을 때까지 가중치를 업데이트해야 합니다.
이를 위해 위의 모든 단계를 for 루프에 넣고 원하는 횟수만큼 반복 할 수 있도록 합니다.
각 반복에서 손실이 계산되고 가중치와 편향이 업데이트 되어 다음 반복에서 더 나은 예측을 얻을 수 있습니다.
따라서 우리의 모델은 작업에 적합한 최적의 가중치 값을 찾아 매번 반복 할 때마다 더 좋아집니다.
각 작업에는 다른 가중치 값 세트가 필요하므로 동물 분류를 위해 훈련 된 신경망이 악기 분류에서 잘 수행 될 것으로 기대할 수 없습니다.
모델 학습은 다음과 같습니다.
for i in range(2000):
pred = simple_nn(flat_imgs, w, b)
loss = error(pred, target.unsqueeze(1))
loss.backward()
w.data -= 0.001*w.grad.data
b.data -= 0.001*b.grad.data
w.grad.zero_()
b.grad.zero_()
print("Loss: ", loss.item())
앞서 만든 함수를 호출하여 예측을 계산하고 'pred'변수에 저장합니다. 그런 다음 평균 제곱 오차 손실을 계산합니다.
그런 다음 가중치와 편향에 대한 모든 그라디언트를 계산하고 해당 그라디언트를 사용하여 값을 업데이트합니다.
그래디언트에 0.001을 곱한 것을 학습률이라고합니다. 이 값은 모델이 학습하는 속도를 결정합니다. 너무 낮으면 모델이 느리게 학습하거나 손실이 천천히 감소합니다.
학습률이 너무 높으면 모델이 안정적이지 않아 다양한 손실 값 사이에서 뛰어 오릅니다. 이것은 수렴에 실패 함을 의미합니다.
위의 단계를 2000 번 수행하고 모델이 가중치와 편향 값을 업데이트하여 손실을 줄이려고 할 때마다 수행합니다.
우리는 모델의 학습에 영향을 미칠 불필요한 그라디언트가 메모리에 축적되지 않도록 각 루프 또는 에포크의 끝에서 그라디언트를 제로화해야 합니다.
우리의 모델은 매우 작기 때문에 2000 epoch 또는 반복을 위해 훈련하는 데 많은 시간이 걸리지 않습니다. 2000 epoch 이후, 우리의 신경망은 이러한 작은 모델에서 나쁘지 않은 0.6805의 손실 값을 제공했습니다.
결론
우리가 방금 만든 모델에 개선을 위한 거대한 공간이 있습니다.
이것은 단순한 모델 일 뿐이며 레이어 수, 각 레이어의 뉴런 수를 늘리거나 epoch 수를 늘려 실험 할 수 있습니다.
간단히 말해, 기계 학습은 수학을 사용하는 마법과도 같습니다. 항상 기초적인 개념을 배우십시오. 지루할 수 있지만, 결국 여러분은 그 지루한 수학 개념이 딥 페이크와 같은 최첨단 기술을 만들었음을 이해할 것입니다.
GitHub에서 전체 코드를 얻거나 Google colab에서 코드를 가지고 놀 수 있습니다.
등록된 댓글이 없습니다.