웹사이트 검색

TensorFlow로 필기 숫자를 인식하는 신경망 구축 방법


소개

신경망은 인공 지능의 많은 하위 분야 중 하나인 딥 러닝의 방법으로 사용됩니다. 그들은 훨씬 더 단순화된 형태이지만 인간의 두뇌가 작동하는 방식을 시뮬레이션하려는 시도로 약 70년 전에 처음 제안되었습니다. 개별 '뉴런'은 신호가 네트워크를 통해 전파될 때 뉴런이 어떻게 반응하는지 결정하기 위해 할당된 가중치와 함께 레이어로 연결됩니다. 이전에는 신경망이 시뮬레이션할 수 있는 뉴런의 수가 제한되어 있어 달성할 수 있는 학습의 복잡성이 제한되었습니다. 그러나 최근 몇 년 동안 하드웨어 개발의 발전으로 인해 우리는 매우 깊은 네트워크를 구축할 수 있었고 기계 지능의 획기적인 발전을 달성하기 위해 방대한 데이터 세트에 대해 교육할 수 있었습니다.

이러한 혁신을 통해 기계는 특정 작업을 수행하는 데 있어 인간의 능력을 능가할 수 있습니다. 그러한 작업 중 하나는 객체 인식입니다. 역사적으로 기계는 인간의 시각을 따라잡을 수 없었지만 최근 딥 러닝의 발전으로 사물, 얼굴, 텍스트, 심지어 감정까지 인식할 수 있는 신경망을 구축할 수 있게 되었습니다.

이 자습서에서는 개체 인식의 작은 하위 섹션인 숫자 인식을 구현합니다. 딥 러닝 연구를 위해 Google Brain 연구소에서 개발한 오픈 소스 Python 라이브러리인 TensorFlow를 사용하여 숫자 0-9의 손으로 그린 이미지를 만들고 신경망을 구축 및 훈련하여 숫자에 대한 올바른 레이블을 인식하고 예측합니다. 표시됩니다.

이 튜토리얼을 따라하기 위해 실제 딥 러닝 또는 TensorFlow에 대한 사전 경험이 필요하지는 않지만 학습 및 테스트, 기능 및 레이블, 최적화 및 평가와 같은 기계 학습 용어 및 개념에 어느 정도 익숙하다고 가정합니다. 기계 학습 소개에서 이러한 개념에 대해 자세히 알아볼 수 있습니다.

전제 조건

이 자습서를 완료하려면 다음이 필요합니다.

  • 가상 환경을 만들기 위한 로컬 환경

참고: TensorFlow에는 최소 Python 버전 3.5가 필요하며 최대 3.8 버전을 지원합니다. 이전 또는 최신 버전의 Python은 지원되지 않습니다. 이 튜토리얼은 TensorFlow 버전 1.4.0-1.15.5와 Python 3.6에서 작동하도록 설계되었습니다. 새 버전이나 이전 버전은 설치 또는 런타임 오류가 발생할 수 있습니다. Windows, macOS 및 Linux에 대한 전체 버전 요구 사항 목록을 보려면 TensorFlow 사이트의 pip로 TensorFlow 설치 페이지를 방문하세요.

1단계 - 프로젝트 구성

인식 프로그램을 개발하기 전에 몇 가지 종속성을 설치하고 파일을 보관할 작업 공간을 만들어야 합니다.

Python 3 가상 환경을 사용하여 프로젝트의 종속성을 관리합니다. 프로젝트의 새 디렉터리를 만들고 새 디렉터리로 이동합니다.

  1. mkdir tensorflow-demo
  2. cd tensorflow-demo

이 튜토리얼의 가상 환경을 설정하려면 다음 명령을 실행하십시오.

  1. python3 -m venv tensorflow-demo
  2. source tensorflow-demo/bin/activate

다음으로 이 자습서에서 사용할 라이브러리를 설치합니다. 요구 사항과 필요한 버전을 지정하는 프로젝트 디렉터리에 requirements.txt 파일을 생성하여 이러한 라이브러리의 특정 버전을 사용합니다. requirements.txt 파일을 생성합니다.

  1. touch requirements.txt

텍스트 편집기에서 파일을 열고 다음 줄을 추가하여 Image, NumPy 및 TensorFlow 라이브러리와 해당 버전을 지정합니다.

requirements.txt
image==1.5.20 numpy==1.14.3 tensorflow==1.4.0

파일을 저장하고 편집기를 종료합니다. 그런 다음 다음 명령을 사용하여 이러한 라이브러리를 설치합니다.

  1. pip install -r requirements.txt

종속성이 설치되면 프로젝트 작업을 시작할 수 있습니다.

2단계 - MNIST 데이터 세트 가져오기

이 튜토리얼에서 사용할 데이터 세트는 MNIST 데이터 세트라고 하며 기계 학습 커뮤니티의 고전입니다. 이 데이터 세트는 28x28픽셀 크기의 필기 숫자 이미지로 구성됩니다. 다음은 데이터 세트에 포함된 숫자의 몇 가지 예입니다.

이 데이터 세트로 작업할 Python 프로그램을 만들어 봅시다. 이 자습서에서는 모든 작업에 하나의 파일을 사용합니다. main.py라는 새 파일을 만듭니다.

  1. touch main.py

이제 선택한 텍스트 편집기에서 이 파일을 열고 이 코드 줄을 파일에 추가하여 TensorFlow 라이브러리를 가져옵니다.

import tensorflow as tf

파일에 다음 코드 줄을 추가하여 MNIST 데이터 세트를 가져오고 mnist 변수에 이미지 데이터를 저장합니다.

...
from tensorflow.examples.tutorials.mnist import input_data


mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)  # y labels are oh-encoded

데이터를 읽을 때 우리는 원-핫-인코딩을 사용하여 이미지의 레이블(실제로 그려진 숫자, 예: "3\)을 나타냅니다. 원-핫 인코딩은 다음의 벡터를 사용합니다. 이진 값은 숫자 또는 범주 값을 나타냅니다. 레이블이 숫자 0-9에 대한 것이므로 벡터에는 가능한 각 숫자에 하나씩 10개의 값이 포함됩니다. 이 값 중 하나는 1로 설정되어 해당 인덱스의 숫자를 나타냅니다. 벡터이고 나머지는 0으로 설정됩니다. 예를 들어 숫자 3은 벡터 [0, 0, 0, 1, 0, 0, 0, 0, 0, 0]를 사용하여 표시됩니다. 인덱스 3의 값이 1로 저장되므로 벡터는 숫자 3을 나타냅니다.

실제 이미지 자체를 나타내기 위해 28x28 픽셀은 크기가 784픽셀인 1D 벡터로 병합됩니다. 이미지를 구성하는 각 784개의 픽셀은 0에서 255 사이의 값으로 저장됩니다. 이미지가 흑백으로만 표시되므로 픽셀의 회색조가 결정됩니다. 따라서 검은색 픽셀은 255로, 흰색 픽셀은 0으로 표시되며 그 사이 어딘가에 다양한 회색 음영이 있습니다.

mnist 변수를 사용하여 방금 가져온 데이터 세트의 크기를 확인할 수 있습니다. 3개의 하위 집합 각각에 대한 num_examples를 살펴보면 데이터 세트가 교육용 이미지 55,000개, 검증용 이미지 5000개, 테스트용 이미지 10,000개로 분할되었음을 확인할 수 있습니다. 파일에 다음 줄을 추가합니다.

...
n_train = mnist.train.num_examples  # 55,000
n_validation = mnist.validation.num_examples  # 5000
n_test = mnist.test.num_examples  # 10,000

이제 데이터를 가져왔으므로 신경망에 대해 생각할 시간입니다.

3단계 - 신경망 아키텍처 정의

신경망의 아키텍처는 네트워크의 레이어 수, 각 레이어의 단위 수 및 레이어 간에 단위가 연결되는 방식과 같은 요소를 나타냅니다. 신경망은 인간 두뇌의 작용에서 느슨하게 영감을 받았기 때문에 여기서 단위라는 용어는 우리가 생물학적으로 뉴런이라고 생각하는 것을 나타내는 데 사용됩니다. 뇌 주위에 신호를 전달하는 뉴런처럼 단위는 이전 단위의 일부 값을 입력으로 받아 계산을 수행한 다음 새 값을 다른 단위의 출력으로 전달합니다. 이러한 단위는 값을 입력하기 위한 하나의 레이어와 값을 출력하기 위한 하나의 레이어로 최소한 시작하여 네트워크를 형성하기 위해 계층화됩니다. 숨겨진 레이어라는 용어는 입력 레이어와 출력 레이어 사이에 있는 모든 레이어, 즉 실제 세계에서 숨겨진 레이어에 사용됩니다.

성능은 매개 변수, 데이터 및 훈련 기간과 같은 무엇보다도 아키텍처의 함수로 생각할 수 있기 때문에 서로 다른 아키텍처는 극적으로 다른 결과를 산출할 수 있습니다.

파일에 다음 코드 줄을 추가하여 전역 변수에 레이어당 단위 수를 저장합니다. 이를 통해 한 곳에서 네트워크 아키텍처를 변경할 수 있으며 튜토리얼이 끝날 때 다른 수의 레이어와 단위가 모델 결과에 어떤 영향을 미치는지 직접 테스트할 수 있습니다.

...
n_input = 784  # input layer (28x28 pixels)
n_hidden1 = 512  # 1st hidden layer
n_hidden2 = 256  # 2nd hidden layer
n_hidden3 = 128  # 3rd hidden layer
n_output = 10  # output layer (0-9 digits)

다음 다이어그램은 각 레이어가 주변 레이어에 완전히 연결된 상태에서 우리가 설계한 아키텍처의 시각화를 보여줍니다.

\심층 신경망\이라는 용어는 숨겨진 계층의 수와 관련이 있으며, \얕은\은 일반적으로 하나의 숨겨진 계층을 의미하고 \깊은\은 여러 숨겨진 계층을 나타냅니다. 충분한 훈련 데이터가 주어지면 얕은 신경망은 충분한 수의 단위는 이론적으로 심층 신경망이 할 수 있는 모든 기능을 나타낼 수 있어야 하지만, 기하급수적으로 더 많은 숨겨진 단위가 있는 얕은 네트워크가 필요한 동일한 작업을 달성하기 위해 더 작은 심층 신경망을 사용하는 것이 계산적으로 더 효율적인 경우가 많습니다. 얕은 신경망은 또한 네트워크가 본질적으로 본 훈련 데이터를 기억하고 새로운 데이터에 대한 지식을 일반화할 수 없는 과적합이 종종 발생합니다.이것이 심층 신경망이 더 일반적으로 사용되는 이유입니다. 입력 데이터와 출력 레이블을 통해 네트워크는 다양한 추상화 수준에서 기능을 학습할 수 있으므로 네트워크 자체가 더 잘 일반화될 수 있습니다.

여기서 정의해야 하는 신경망의 다른 요소는 하이퍼파라미터입니다. 훈련 중에 업데이트되는 매개변수와 달리 이러한 값은 처음에 설정되며 프로세스 전체에서 일정하게 유지됩니다. 파일에서 다음 변수와 값을 설정합니다.

...
learning_rate = 1e-4
n_iterations = 1000
batch_size = 128
dropout = 0.5

학습률은 학습 프로세스의 각 단계에서 매개변수가 조정되는 정도를 나타냅니다. 이러한 조정은 교육의 핵심 구성 요소입니다. 네트워크를 통과할 때마다 가중치를 약간 조정하여 손실을 줄이려고 합니다. 학습 속도가 클수록 더 빨리 수렴할 수 있지만 업데이트될 때 최적 값을 초과할 가능성도 있습니다. 반복 횟수는 학습 단계를 얼마나 많이 거치는지, 배치 크기는 각 단계에서 사용하는 학습 예제의 수를 나타냅니다. dropout 변수는 일부 단위를 무작위로 제거하는 임계값을 나타냅니다. 우리는 최종 히든 레이어에서 드롭아웃을 사용하여 각 유닛이 모든 훈련 단계에서 제거될 확률을 50%로 줄 것입니다. 이는 과적합을 방지하는 데 도움이 됩니다.

이제 신경망의 아키텍처와 학습 프로세스에 영향을 미치는 하이퍼파라미터를 정의했습니다. 다음 단계는 네트워크를 TensorFlow 그래프로 구축하는 것입니다.

4단계 - TensorFlow 그래프 작성

네트워크를 구축하기 위해 네트워크를 TensorFlow가 실행할 계산 그래프로 설정합니다. TensorFlow의 핵심 개념은 배열이나 목록과 유사한 데이터 구조인 텐서입니다. 그래프를 통과하면서 초기화되고 조작되며 학습 프로세스를 통해 업데이트됩니다.

나중에 값을 입력할 텐서인 자리 표시자로 3개의 텐서를 정의하는 것으로 시작하겠습니다. 파일에 다음을 추가합니다.

...
X = tf.placeholder("float", [None, n_input])
Y = tf.placeholder("float", [None, n_output])
keep_prob = tf.placeholder(tf.float32)

선언 시 지정해야 하는 유일한 매개변수는 공급할 데이터의 크기입니다. X의 경우 [None, 784] 모양을 사용합니다. 여기서 None은 정의되지 않은 수의 784픽셀 이미지를 공급하므로 모든 양을 나타냅니다. Y의 모양은 [None, 10]입니다. 정의되지 않은 수의 레이블 출력에 대해 10개의 가능한 클래스와 함께 사용할 것이기 때문입니다. keep_prob 텐서는 드롭아웃 비율을 제어하는 데 사용되며 교육에 동일한 텐서를 사용하기를 원하기 때문에 불변 변수가 아닌 자리 표시자로 초기화합니다(드롭아웃0.5로 설정됨) 및 테스트(dropout1.0로 설정된 경우).

훈련 과정에서 네트워크가 업데이트할 매개변수는 weightbias 값이므로 빈 자리 표시자가 아닌 초기 값을 설정해야 합니다. 이 값은 기본적으로 네트워크가 학습을 수행하는 위치이며, 뉴런의 활성화 기능에 사용되어 단위 간 연결 강도를 나타냅니다.

훈련 중에 값이 최적화되기 때문에 지금은 값을 0으로 설정할 수 있습니다. 그러나 초기 값은 실제로 모델의 최종 정확도에 상당한 영향을 미칩니다. 가중치에 대해 잘린 정규 분포의 임의 값을 사용합니다. 우리는 그것들이 0에 가까워지기를 원합니다. 그래서 그것들은 양의 방향이나 음의 방향으로 조정될 수 있고 약간 다르기 때문에 서로 다른 오류를 생성합니다. 이렇게 하면 모델이 유용한 정보를 학습할 수 있습니다. 다음 줄을 추가합니다.

...
weights = {
    'w1': tf.Variable(tf.truncated_normal([n_input, n_hidden1], stddev=0.1)),
    'w2': tf.Variable(tf.truncated_normal([n_hidden1, n_hidden2], stddev=0.1)),
    'w3': tf.Variable(tf.truncated_normal([n_hidden2, n_hidden3], stddev=0.1)),
    'out': tf.Variable(tf.truncated_normal([n_hidden3, n_output], stddev=0.1)),
}

바이어스의 경우 작은 상수 값을 사용하여 텐서가 초기 단계에서 활성화되어 전파에 기여하도록 합니다. 가중치 및 편향 텐서는 쉽게 액세스할 수 있도록 사전 객체에 저장됩니다. 이 코드를 파일에 추가하여 바이어스를 정의합니다.

...
biases = {
    'b1': tf.Variable(tf.constant(0.1, shape=[n_hidden1])),
    'b2': tf.Variable(tf.constant(0.1, shape=[n_hidden2])),
    'b3': tf.Variable(tf.constant(0.1, shape=[n_hidden3])),
    'out': tf.Variable(tf.constant(0.1, shape=[n_output]))
}

다음으로 텐서를 조작할 작업을 정의하여 네트워크 계층을 설정합니다. 파일에 다음 줄을 추가합니다.

...
layer_1 = tf.add(tf.matmul(X, weights['w1']), biases['b1'])
layer_2 = tf.add(tf.matmul(layer_1, weights['w2']), biases['b2'])
layer_3 = tf.add(tf.matmul(layer_2, weights['w3']), biases['b3'])
layer_drop = tf.nn.dropout(layer_3, keep_prob)
output_layer = tf.matmul(layer_3, weights['out']) + biases['out']

각 히든 레이어는 이전 레이어의 출력과 현재 레이어의 가중치에 대해 행렬 곱셈을 실행하고 이 값에 바이어스를 추가합니다. 마지막 히든 레이어에서 keep_prob 값 0.5를 사용하여 드롭아웃 작업을 적용합니다.

그래프 작성의 마지막 단계는 최적화하려는 손실 함수를 정의하는 것입니다. TensorFlow 프로그램에서 널리 사용되는 손실 함수는 로그 손실이라고도 하는 교차 엔트로피이며 두 가지 확률 분포(예측 및 레이블) 간의 차이를 정량화합니다. . 완벽한 분류는 교차 엔트로피가 0이 되고 손실이 완전히 최소화됩니다.

또한 손실 함수를 최소화하는 데 사용할 최적화 알고리즘을 선택해야 합니다. 기울기 하강법 최적화라는 프로세스는 음의(내림차순) 방향으로 기울기를 따라 반복적인 단계를 수행하여 함수의 (로컬) 최소값을 찾는 일반적인 방법입니다. TensorFlow에 이미 구현된 몇 가지 경사 하강법 최적화 알고리즘이 있으며 이 자습서에서는 Adam 최적화 프로그램을 사용할 것입니다. 이것은 기울기의 기하급수적으로 가중된 평균을 계산하고 이를 조정에 사용함으로써 프로세스 속도를 높이는 모멘텀을 사용하여 기울기 하강법 최적화로 확장됩니다. 파일에 다음 코드를 추가합니다.

...
cross_entropy = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits(
        labels=Y, logits=output_layer
        ))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

이제 네트워크를 정의하고 TensorFlow로 구축했습니다. 다음 단계는 그래프를 통해 데이터를 공급하여 훈련시킨 다음 실제로 무언가를 배웠는지 테스트하는 것입니다.

5단계 - 교육 및 테스트

교육 프로세스에는 그래프를 통해 교육 데이터 세트를 공급하고 손실 함수를 최적화하는 작업이 포함됩니다. 네트워크가 더 많은 훈련 이미지 배치를 반복할 때마다 표시되는 숫자를 더 정확하게 예측하기 위해 손실을 줄이기 위해 매개변수를 업데이트합니다. 테스트 프로세스에는 훈련된 그래프를 통해 테스트 데이터 세트를 실행하고 정확도를 계산할 수 있도록 올바르게 예측된 이미지 수를 추적하는 작업이 포함됩니다.

교육 프로세스를 시작하기 전에 정확도를 평가하는 방법을 정의하여 교육하는 동안 데이터의 미니 배치에 인쇄할 수 있습니다. 이 인쇄된 진술을 통해 첫 번째 반복에서 마지막 반복까지 손실이 감소하고 정확도가 증가함을 확인할 수 있습니다. 또한 일관되고 최적의 결과에 도달하기 위해 충분한 반복을 실행했는지 여부를 추적할 수 있습니다.

...
correct_pred = tf.equal(tf.argmax(output_layer, 1), tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))

correct_pred에서 arg_max 함수를 사용하여 output_layer(예측) 및 Y를 보고 올바르게 예측되는 이미지를 비교합니다. (레이블), equal 함수를 사용하여 이를 부울 목록으로 반환합니다. 그런 다음 이 목록을 float로 캐스팅하고 평균을 계산하여 총 정확도 점수를 얻을 수 있습니다.

이제 그래프 실행을 위한 세션을 초기화할 준비가 되었습니다. 이 세션에서 우리는 훈련 예제를 네트워크에 공급하고, 일단 훈련되면 동일한 그래프에 새로운 테스트 예제를 공급하여 모델의 정확도를 결정합니다. 파일에 다음 코드 줄을 추가합니다.

...
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)

딥 러닝에서 훈련 과정의 본질은 손실 함수를 최적화하는 것입니다. 여기서 우리는 이미지의 예측 레이블과 이미지의 실제 레이블 간의 차이를 최소화하는 것을 목표로 합니다. 이 프로세스에는 설정된 반복 횟수 동안 반복되는 4단계가 포함됩니다.

  • 네트워크를 통해 값 전달
  • 손실 계산
  • 네트워크를 통해 역방향 값 전파
  • 매개변수 업데이트

각 훈련 단계에서 다음 단계의 손실을 줄이기 위해 매개변수를 약간 조정합니다. 학습이 진행됨에 따라 손실이 감소하는 것을 볼 수 있고 결국 훈련을 중단하고 네트워크를 새로운 데이터를 테스트하기 위한 모델로 사용할 수 있습니다.

이 코드를 파일에 추가합니다.

...
# train on mini batches
for i in range(n_iterations):
    batch_x, batch_y = mnist.train.next_batch(batch_size)
    sess.run(train_step, feed_dict={
        X: batch_x, Y: batch_y, keep_prob: dropout
        })

    # print loss and accuracy (per minibatch)
    if i % 100 == 0:
        minibatch_loss, minibatch_accuracy = sess.run(
            [cross_entropy, accuracy],
            feed_dict={X: batch_x, Y: batch_y, keep_prob: 1.0}
            )
        print(
            "Iteration",
            str(i),
            "\t| Loss =",
            str(minibatch_loss),
            "\t| Accuracy =",
            str(minibatch_accuracy)
            )

네트워크를 통해 이미지의 미니 배치를 공급하는 각 훈련 단계를 100회 반복한 후 해당 배치의 손실과 정확도를 출력합니다. 값이 전체 모델이 아니라 배치당이므로 여기에서 손실 감소 및 정확도 증가를 기대해서는 안 됩니다. 훈련 과정을 가속화하고 매개변수를 업데이트하기 전에 네트워크가 다양한 예를 볼 수 있도록 개별적으로 이미지를 공급하는 대신 이미지의 미니 배치를 사용합니다.

교육이 완료되면 테스트 이미지에서 세션을 실행할 수 있습니다. 이번에는 1.0keep_prob 드롭아웃 비율을 사용하여 테스트 프로세스에서 모든 장치가 활성화되도록 합니다.

이 코드를 파일에 추가합니다.

...
test_accuracy = sess.run(accuracy, feed_dict={X: mnist.test.images, Y: mnist.test.labels, keep_prob: 1.0})
print("\nAccuracy on test set:", test_accuracy)

이제 프로그램을 실행하고 신경망이 이러한 손글씨 숫자를 얼마나 정확하게 인식할 수 있는지 확인할 차례입니다. main.py 파일을 저장하고 터미널에서 다음 명령을 실행하여 스크립트를 실행합니다.

  1. python main.py

개별 손실 및 정확도 결과가 약간 다를 수 있지만 다음과 유사한 출력이 표시됩니다.

Output
Iteration 0 | Loss = 3.67079 | Accuracy = 0.140625 Iteration 100 | Loss = 0.492122 | Accuracy = 0.84375 Iteration 200 | Loss = 0.421595 | Accuracy = 0.882812 Iteration 300 | Loss = 0.307726 | Accuracy = 0.921875 Iteration 400 | Loss = 0.392948 | Accuracy = 0.882812 Iteration 500 | Loss = 0.371461 | Accuracy = 0.90625 Iteration 600 | Loss = 0.378425 | Accuracy = 0.882812 Iteration 700 | Loss = 0.338605 | Accuracy = 0.914062 Iteration 800 | Loss = 0.379697 | Accuracy = 0.875 Iteration 900 | Loss = 0.444303 | Accuracy = 0.90625 Accuracy on test set: 0.9206

모델의 정확도를 개선하거나 하이퍼파라미터 조정의 영향에 대해 자세히 알아보기 위해 학습률, 드롭아웃 임계값, 배치 크기 및 반복 횟수를 변경하는 효과를 테스트할 수 있습니다. 또한 은닉층의 단위 수를 변경하고 은닉층 자체의 양을 변경하여 다양한 아키텍처가 모델 정확도를 높이거나 낮추는 방법을 확인할 수 있습니다.

네트워크가 실제로 손으로 그린 이미지를 인식하는지 보여주기 위해 우리 자신의 단일 이미지에서 테스트해 봅시다.

로컬 컴퓨터에 있고 손으로 직접 그린 숫자를 사용하려는 경우 그래픽 편집기를 사용하여 숫자의 고유한 28x28 픽셀 이미지를 만들 수 있습니다. 그렇지 않으면 curl을 사용하여 다음 샘플 테스트 이미지를 서버나 컴퓨터에 다운로드할 수 있습니다.

  1. curl -O https://raw.githubusercontent.com/do-community/tensorflow-digit-recognition/master/test_img.png

편집기에서 main.py 파일을 열고 파일 상단에 다음 코드 줄을 추가하여 이미지 조작에 필요한 두 개의 라이브러리를 가져옵니다.

import numpy as np
from PIL import Image
...

그런 다음 파일 끝에 다음 코드 줄을 추가하여 손으로 쓴 숫자의 테스트 이미지를 로드합니다.

...
img = np.invert(Image.open("test_img.png").convert('L')).ravel()

Image 라이브러리의 open 기능은 3개의 RGB 색상 채널과 알파 투명도를 포함하는 4D 배열로 테스트 이미지를 로드합니다. 이것은 이전에 TensorFlow로 데이터 세트를 읽을 때 사용한 것과 같은 표현이 아니므로 형식을 일치시키기 위해 몇 가지 추가 작업을 수행해야 합니다.

먼저 convert 기능을 L 매개변수와 함께 사용하여 4D RGBA 표현을 하나의 그레이스케일 색상 채널로 줄입니다. 우리는 이것을 numpy 배열로 저장하고 np.invert를 사용하여 반전합니다. 왜냐하면 현재 매트릭스는 검은색을 0으로, 흰색을 255로 나타내기 때문입니다. 반면 우리는 그 반대가 필요합니다. 마지막으로 ravel을 호출하여 배열을 평면화합니다.

이제 이미지 데이터가 올바르게 구조화되었으므로 이전과 동일한 방식으로 세션을 실행할 수 있지만 이번에는 테스트를 위해 단일 이미지만 제공합니다.

파일에 다음 코드를 추가하여 이미지를 테스트하고 출력된 레이블을 인쇄합니다.

...
prediction = sess.run(tf.argmax(output_layer, 1), feed_dict={X: [img]})
print ("Prediction for test image:", np.squeeze(prediction))

np.squeeze 함수는 예측에서 호출되어 배열에서 단일 정수를 반환합니다(즉, [2]에서 2로 이동). 결과 출력은 네트워크가 이 이미지를 숫자 2로 인식했음을 보여줍니다.

Output
Prediction for test image: 2

더 복잡한 이미지(예: 다른 숫자처럼 보이는 숫자 또는 잘못 그려진 숫자)로 네트워크를 테스트하여 얼마나 잘 작동하는지 확인할 수 있습니다.

결론

이 자습서에서는 약 92%의 정확도로 MNIST 데이터 세트를 분류하도록 신경망을 성공적으로 교육하고 자신의 이미지에서 테스트했습니다. 현재 최첨단 연구는 컨볼루션 레이어를 포함하는 보다 복잡한 네트워크 아키텍처를 사용하여 동일한 문제에 대해 약 99%를 달성합니다. 모든 픽셀을 784 단위의 하나의 벡터로 병합하는 방법과 달리 콘텐츠를 더 잘 표현하기 위해 이미지의 2D 구조를 사용합니다. MNIST 웹사이트에서 이 주제에 대한 자세한 내용을 읽을 수 있습니다.

이제 신경망을 구축하고 교육하는 방법을 알았으므로 자체 데이터에서 이 구현을 시도하고 사용하거나 보다 일반적인 이미지 인식을 위해 CIFAR-10 데이터 세트와 같은 다른 인기 있는 데이터 세트에서 테스트할 수 있습니다.