본문 바로가기
인공지능/인공지능개론

[AI] Neural Networks (6-2)

by 주황딱지 2024. 6. 28.

 

텐서플로우(Tesnsorflow)

 

파이썬에서 흔히 그렇듯이, 여러 라이브러리는 이미 역전파 알고리즘을 사용하는 신경망을 구현하고 있으며, TensorFlow는 그러한 라이브러리 중 하나이다. 이 웹 애플리케이션에서 TensorFlow 신경망을 실험해 볼 수 있다. 네트워크의 다양한 속성을 정의하고 실행하여 출력을 시각화할 수 있다. 이제 TensorFlow를 사용하여 지난번에 논의한 작업, 즉 위조지폐와 진짜 지폐를 구별하는 작업을 수행하는 방법의 예를 살펴볼 것이다.

import csv
import tensorflow as tf
from sklearn.model_selection import train_test_split

 

TensorFlow를 임포트하고  tf라고 정의한다(별다줄).

# Read data in from file
with open("banknotes.csv") as f:
    reader = csv.reader(f)
    next(reader)

    data = []
    for row in reader:
        data.append({
            "evidence": [float(cell) for cell in row[:4]],
            "label": 1 if row[4] == "0" else 0
        })

# Separate data into training and testing groups
evidence = [row["evidence"] for row in data]
labels = [row["label"] for row in data]
X_training, X_testing, y_training, y_testing = train_test_split(
    evidence, labels, test_size=0.4
)

 

우리는 CSV 데이터를 모델에 제공한다. 우리의 작업은 종종 라이브러리가 요구하는 형식에 맞게 데이터를 만드는 데 필요하다. 실제로 모델을 코딩하는 어려운 부분은 이미 우리를 위해 구현되어 있다.

# Create a neural network
model = tf.keras.models.Sequential()

 

케라스는 다양한 머신 러닝 알고리즘이 접근하는 API이다. 순차적 모델은 layer가 서로를 따르는 모델이다(지금까지 본 것과 같다).

# Add a hidden layer with 8 units, with ReLU activation
model.add(tf.keras.layers.Dense(8, input_shape=(4,), activation="relu"))

 

dense layer은 현재 계층의 각 노드가 이전 계층의 모든 노드에 연결된 계층이다. 숨겨진 계층을 생성할 때 위에서 언급한 ReLU 활성화 함수를 사용하여 각각 4개의 입력 뉴런을 갖는 8개의 dense layer을 만든다.

# Add output layer with 1 unit, with sigmoid activation
model.add(tf.keras.layers.Dense(1, activation="sigmoid"))

 

출력 계층에서는 시그모이드 활성화 함수를 사용하는 하나의 밀집 계층을 생성하고 싶다. 시그모이드 활성화 함수는 출력이 0과 1 사이의 값인 활성화 함수이다.

# Train neural network
model.compile(
    optimizer="adam",
    loss="binary_crossentropy",
    metrics=["accuracy"]
)
model.fit(X_training, y_training, epochs=20)

# Evaluate how well model performs
model.evaluate(X_testing, y_testing, verbose=2)

 

마지막으로, 모델을 컴파일하고, 어떤 알고리즘이 최적화해야 하는지, 어떤 유형의 손실 함수를 사용하는지, 그리고 어떻게 성공 여부를 측정하고 싶은지(우리의 경우 출력의 정확도에 관심이 있습니다)를 지정한다. 마지막으로, 20번의 반복(에포크)으로 훈련 데이터에 모델을 적용한 다음, 테스트 데이터에서 평가한다.


컴퓨터 비전(Computer Vision)

 

컴퓨터 비전은 디지털 이미지를 분석하고 이해하기 위한 다양한 계산 방법을 포괄하며, 종종 신경망을 사용하여 달성된다. 예를 들어, 소셜 미디어가 얼굴 인식을 사용하여 사진 속 사람을 자동으로 태그 할 때 컴퓨터 비전이 사용된다. 다른 예로는 필기 인식 및 자율 주행 자동차가 있다.

 

이미지는 픽셀로 구성되며, 픽셀은 0~255 범위의 세 가지 값, 즉 빨간색, 초록색, 파란색으로 표현된다. 이러한 값은 종종 RGB라는 약어로 불린다. 이를 사용하여 각 픽셀의 각 색상 값이 입력이고, 숨겨진 계층이 있으며, 출력이 이미지에 표시된 내용을 알려주는 여러 개의 단위인 신경망을 만들 수 있다. 그러나 이 접근 방식에는 몇 가지 단점이 있다. 첫째, 이미지를 픽셀과 색상 값으로 분해하면 이미지의 구조를 보조 도구로 사용할 수 없다(분해하는 순간 분해된 이미지의 구조 외 전체 이미지와의 연관성이 떨어진다). 반면에 인간은 얼굴의 일부를 보면 나머지 얼굴도 볼 수 있을 것으로 예상하고 이를 통해 계산이 빨라진다. 따라서 우리는 신경망에서도 비슷한 이점을 활용할 수 있기를 원한다. 둘째, 입력의 수가 매우 많아서 많은 가중치를 계산해야 한다.


이미지 합성곱(Image Convolution)

 

이미지 합성곱은 이미지의 각 픽셀 값을 이웃에 더하는 필터를 적용하는 것으로, 커널 행렬에 따라 가중치가 적용된다. 이렇게 하면 이미지가 변경되고 신경망이 처리하는 데 도움이 될 수 있다.

 

아래 예시를 보면서 이해해 보자:

 

커널은 파란색 행렬이고 이미지는 왼쪽에 있는 큰 행렬이다. 필터링된 결과 이미지는 오른쪽 하단에 있는 작은 행렬이다. 커널로 이미지를 필터링하려면 이미지의 왼쪽 상단에 있는 값 20의 픽셀(노란색 20)부터 시작한다. 그런 다음 주변의 모든 값을 커널의 해당 값으로 곱하고 합산한다(10*0 + 20*(-1) + 30*0 + 10*(-1) + 20*5 + 30*(-1) + 20*0 + 30*(-1) + 40*0). 그러면 값 10이 생성됩니다. 그런 다음 오른쪽 픽셀(30), 첫 번째 픽셀 아래의 픽셀(30), 이 픽셀의 오른쪽 픽셀(40)에 대해서도 같은 작업을 수행한다. 그러면 오른쪽 하단에 보이는 값을 갖는 필터링된 이미지가 생성된다.

 

다른 커널은 다른 작업을 수행할 수 있다. 에지 감지(edge detection)의 경우, 다음 커널이 종종 사용된다:

다른 커널임

 

여기서 아이디어는 픽셀이 모든 이웃과 유사할 때, 서로 상쇄되어 0의 값을 제공해야 한다는 것이다. 따라서 픽셀이 유사할수록 이미지의 부분이 어두워지고, 차이가 클수록 더 밝아진다. 이 커널을 이미지(왼쪽)에 적용하면 뚜렷한 모서리가 있는 이미지(오른쪽)가 생성된다.

적용되기 전(좌) / 적용된 후(우)

 

이미지 합성곱의 구현을 해보자. 우리는 PIL 라이브러리(Python Imaging Library의 약자)를 사용하는데, 이 라이브러리는 우리를 대신해 대부분의 어려운 작업을 해준다.

import math
import sys

from PIL import Image, ImageFilter

# Ensure correct usage
if len(sys.argv) != 2:
    sys.exit("Usage: python filter.py filename")

# Open image
image = Image.open(sys.argv[1]).convert("RGB")

# Filter image according to edge detection kernel
filtered = image.filter(ImageFilter.Kernel(
    size=(3, 3),
    kernel=[-1, -1, -1, -1, 8, -1, -1, -1, -1],
    scale=1
))

# Show resulting image
filtered.show()

 

그래도 신경망에서 이미지를 처리하는 것은 신경망에 입력으로 사용되는 픽셀 수로 인해 계산 비용이 많이 든다.

 

이를 해결하는 또 다른 방법은 풀링(Pooling)으로, 입력의 영역에서 샘플링하여 입력 크기를 줄이는 것이다. 서로 옆에 있는 픽셀은 이미지에서 같은 영역에 속하므로 유사할 가능성이 높다. 따라서 하나의 픽셀을 사용하여 전체 영역을 나타낼 수 있다. 이를 수행하는 한 가지 방법은 최대 풀링(Max-Pooling)으로, 선택된 픽셀은 같은 영역에서 다른 모든 픽셀 중 가장 높은 값을 갖는 픽셀이다. 예를 들어, 왼쪽 사각형(아래)을 이 입력에서 최대 풀링하여 2X2 사각형 4개로 나누면 오른쪽의 작은 사각형을 얻게 된다.

Max-Pooling (2X2정사각형으로 나누고 가장 큰 값 선택)


합성곱 신경망(Convolitional Neural Networks)

 

합성곱 신경망은 일반적으로 이미지 분석에 합성곱을 사용하는 신경망이다. 다양한 커널을 사용하여 이미지의 일부 기능을 추출하는 데 도움이 될 수 있는 필터를 적용하는 것부터 시작된다. 이러한 필터는 출력 오류를 기반으로 커널을 조정하여 신경망의 다른 가중치와 동일한 방식으로 개선될 수 있다. 그런 다음, 결과 이미지가 풀링(pooling)된 후 픽셀이 기존 신경망에 입력으로 공급된다(평탄화(flattening) 과정으로 불림).

합성곱 신경망

 

합성곱 및 풀링 단계를 여러 번 반복하여 추가 기능을 추출하고 신경망에 대한 입력 크기를 줄일 수 있다. 이러한 프로세스의 이점 중 하나는 합성곱 및 풀링을 통해 신경망이 변동에 덜 민감해진다는 것이다. 즉, 동일한 사진을 약간 다른 각도에서 촬영하면 합성곱 신경망의 입력은 유사하지만 컨볼루션 및 풀링이 없으면 각 이미지의 입력이 크게 달라진다.

 

코드에서 합성곱 신경망은 기존 신경망과 크게 다르지 않다. TensorFlow는 모델을 테스트할 데이터 세트를 제공한다. 흑백으로 손으로 쓴 숫자의 사진이 들어 있는 MNIST를 사용한다. 이제 합성곱 신경망이 숫자를 인식하도록 훈련할 것이다.

import sys
import tensorflow as tf

# Use MNIST handwriting dataset
mnist = tf.keras.datasets.mnist

# Prepare data for training
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
y_train = tf.keras.utils.to_categorical(y_train)
y_test = tf.keras.utils.to_categorical(y_test)
x_train = x_train.reshape(
    x_train.shape[0], x_train.shape[1], x_train.shape[2], 1
)
x_test = x_test.reshape(
    x_test.shape[0], x_test.shape[1], x_test.shape[2], 1
)

# Create a convolutional neural network
model = tf.keras.models.Sequential([

    # Convolutional layer. Learn 32 filters using a 3x3 kernel
    tf.keras.layers.Conv2D(
        32, (3, 3), activation="relu", input_shape=(28, 28, 1)
    ),

    # Max-pooling layer, using 2x2 pool size
    tf.keras.layers.MaxPooling2D(pool_size=(2, 2)),

    # Flatten units
    tf.keras.layers.Flatten(),

    # Add a hidden layer with dropout
    tf.keras.layers.Dense(128, activation="relu"),
    tf.keras.layers.Dropout(0.5),

    # Add an output layer with output units for all 10 digits
    tf.keras.layers.Dense(10, activation="softmax")
])

# Train neural network
model.compile(
    optimizer="adam",
    loss="categorical_crossentropy",
    metrics=["accuracy"]
)
model.fit(x_train, y_train, epochs=10)

# Evaluate neural network performance
model.evaluate(x_test,  y_test, verbose=2)

 

모델을 훈련하는 데 시간이 걸리므로 이미 훈련된 모델을 저장하여 나중에 사용할 수 있다.

# Save model to file
if len(sys.argv) == 2:
    filename = sys.argv[1]
    model.save(filename)
    print(f"Model saved to {filename}.")

 

이제 손으로 그린 ​​숫자를 입력으로 받는 프로그램을 실행하면 모델을 사용하여 숫자를 분류하고 출력할 수 있다. 구현된 프로그램은 아래의 recognition.py를 참조하자.

recognition.py
0.00MB

 


순환 신경망(Recurrent Neural Networks)

 

순방향 신경망(Feed-Forward Neural Networks)은 지금까지 논의한 신경망 유형으로, 입력 데이터가 네트워크에 제공되어 결국 어떤 출력을 생성한다. 순방향 신경망이 작동하는 방식에 대한 다이어그램은 아래에서 볼 수 있다.

순방향 신경망

 

이와 반대로, 순환 신경망(Recurrent Neural Networks)은 네트워크가 자체 출력을 입력으로 사용하는 비선형 구조로 구성된다. 예를 들어, Microsoft의 캡션봇은 문장의 단어로 이미지의 내용을 설명할 수 있다. 이는 이미지의 속성에 따라 출력 길이가 달라질 수 있다는 점에서 분류와 다르다. 순방향 신경망은 출력 수를 변경할 수 없지만 순환 신경망은 구조상 이를 변경할 수 있다. 캡션 작업에서 네트워크는 입력을 처리하여 출력을 생성한 다음 해당 지점에서 처리를 계속하여 다른 출력을 생성하고 필요한 만큼 반복한다.

순환 신경망

 

순환 신경망은 네트워크가 단일 개별 개체가 아닌 시퀀스를 처리하는 경우에 유용하다. 위에서는 신경망이 일련의 단어를 생성해야 했다. 그러나 일련의 이미지로 구성된 비디오 파일을 분석하거나 일련의 입력(소스 언어의 단어)을 처리하여 일련의 출력(원어의 단어)을 생성하는 번역 작업에도 동일한 원칙이 적용될 수 있다.


이로서 우리는 신경망 챕터를 알아봤다. 다음에는 인공지능이 인건의 언어를 처리하는 법을 알아볼 것이다.

반응형

'인공지능 > 인공지능개론' 카테고리의 다른 글

[AI] Language (7)  (0) 2024.07.01
[AI] Neural Networks (6-1)  (0) 2024.06.28
[AI] Learning (5-3)  (0) 2024.06.25
[AI] Learning (5-2)  (0) 2024.06.24
[AI] Uncertainty (3-3)  (2) 2024.06.24