많으면 달라진다 – 언어모델의 스케일이 크면 성능이 좋다

대규모 언어 모델의 스케일이 성능 향상과 관련된 논문이 있습니다. GPT-3와 같은 대형 언어 모델은 많은 양의 훈련 데이터와 매개 변수를 사용하여 학습됩니다. 이러한 모델은 매우 큰 규모로 설계되었기 때문에 더욱 복잡하고 다양한 언어 특성을 학습할 수 있습니다.

예를 들어, “Language Models are Unsupervised Multitask Learners“라는 논문에서는 GPT-3 모델의 성능과 스케일 간의 관계에 대해 다루고 있습니다. 이 논문은 GPT-3 모델의 크기가 성능에 미치는 영향을 실험적으로 조사하고, 모델 크기가 증가할수록 언어 이해와 생성 과제에서 성능이 향상되는 것을 보여줍니다.

또한, “BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding” 논문에서도 BERT라는 대규모 언어 모델이 다양한 언어 이해 태스크에서 우수한 성능을 보여준다는 것을 보여주고 있습니다.

이러한 논문들은 대규모 언어 모델의 스케일이 언어 이해와 생성 과제에 대한 성능 향상에 중요한 역할을 한다는 점을 제시하고 있습니다.

“많으면 달라진다”라는 말은 언어 모델의 크기가 커질수록 모델의 성능이 향상될 수 있다는 의미입니다. 즉, 모델의 규모가 커질수록 언어 이해와 생성 과제에서 더 좋은 성능을 보일 수 있다는 것을 의미합니다.

이는 대부분의 경우에 해당하지만, 항상 절대적인 규칙은 아닙니다. 성능은 모델의 크기뿐만 아니라 데이터의 품질, 훈련 방법, 모델 아키텍처 등 다른 요소들에도 영향을 받을 수 있기 때문입니다. 그러나 일반적으로 말하면, 더 큰 규모의 언어 모델은 더 복잡한 언어 패턴을 학습하고 더 정확한 예측을 수행할 수 있으므로, 더 좋은 성능을 보이는 경향이 있습니다.

디스코 디퓨전: 텍스트에서 탄생한 AI 예술의 환상적인 세계 (진행중)

디스코 디퓨전(Disco Diffusion)은 텍스트 설명을 기반으로 인공지능(AI)이 예술 작품을 생성하는 모델입니다. 이 모델은 딥 러닝과 생성 모델링 기술을 활용하여 이미지를 생성하는데 사용됩니다. 디스코 디퓨전은 기존의 텍스트 입력을 받아들여 이미지를 생성하는 과정에서 차별화되는 특징을 가지고 있습니다.

디스코 디퓨전은 클립(guided diffusion) 기반의 모델로, 텍스트 입력과 함께 이미지 생성에 필요한 가이드 역할을 하는 이미지 클립(Image CLIP) 모델을 활용합니다. 이 모델은 텍스트와 이미지를 연결시켜주는 중간 매개체 역할을 수행하며, 텍스트 설명을 기반으로 실제 이미지를 생성하는 과정에서 디퓨전(확산) 알고리즘을 활용합니다.

디스코 디퓨전은 예술적인 이미지 생성을 위해 컴퓨터 비전과 자연어 처리 기술을 결합합니다. 이를 통해 텍스트 설명에 따라 강렬한 색상 조합, 독특한 이미지 구성, 상세한 디테일을 가진 추상적인 예술 작품을 생성할 수 있습니다. 디스코 디퓨전은 AI를 통해 예술적 창의성을 자동화하고, 텍스트 입력을 통해 다양한 예술 작품을 만들어냅니다.

콜랩 예)

 

[cafe AI] 머신러닝을 이용한 이미지 인식

  • 이 강의는 shop2world 의 캐나다 몬트리올에서 진행되는 일반인 대상의 AI 강의인 cafe AI 2023 강의 시리즈 교재입니다.
  • 강의 참여를 원하시는 분은 info@shop2world.com 으로 신청 주세요.
    강의 언어는 영어, 불어, 한국어 입니다.
  • 강의 결과 실행: [cafe AI] 머신러닝을 이용한 이미지 인식기법

머신러닝을 이용하여 이미지를 인식하는 예시로는, 손글씨 숫자 인식 프로그램이 있습니다. 이 프로그램은 숫자가 쓰인 이미지를 입력으로 받아 머신러닝 알고리즘을 통해 숫자를 인식합니다.

머신러닝 알고리즘은 먼저 숫자 이미지 데이터셋을 사용해 학습합니다. 학습을 통해 이미지에서 특징을 추출하고, 이를 바탕으로 숫자를 인식할 수 있는 모델을 만들어냅니다. 이렇게 만들어진 모델은 새로운 이미지를 입력으로 받아, 학습한 내용을 바탕으로 숫자를 인식할 수 있습니다.

이러한 손글씨 숫자 인식 프로그램은 손글씨 숫자를 자동으로 인식해주는데 사용될 수 있습니다. 이를 응용하여 우편물에서 우편번호를 인식하는 등 다양한 분야에서 활용될 수 있습니다.

먼저 실행을 해 보겠습니다.
실행하기

이 예제에서는 MNIST 데이터셋을 사용합니다. MNIST는 0부터 9까지의 숫자 이미지 데이터셋으로, 이미지 분류 문제에서 가장 대표적인 데이터셋 중 하나입니다.
Keras가 제공하는 데이터셋을 이용합니다.

먼저, 필요한 라이브러리와 데이터를 불러옵니다.

import tensorflow as tf
from tensorflow import keras
import numpy as np
mnist = keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

이제 데이터셋을 살펴보겠습니다.

print(train_images.shape)   # (60000, 28, 28)
print(len(train_labels))    # 60000
print(test_images.shape)    # (10000, 28, 28)
print(len(test_labels))     # 10000

총 60,000개의 학습 데이터와 10,000개의 테스트 데이터가 있습니다. 각 이미지는 28×28 크기의 흑백 이미지입니다.

데이터 전처리를 수행합니다. 픽셀값을 0과 1 사이로 정규화하고, 레이블을 범주형으로 변환합니다.

train_images = train_images / 255.0
test_images = test_images / 255.0
train_labels = keras.utils.to_categorical(train_labels)
test_labels = keras.utils.to_categorical(test_labels)

이제 모델을 구성합니다. 2개의 은닉층과 1개의 출력층으로 구성된 인공신경망을 사용합니다.

model = keras.Sequential([
    keras.layers.Flatten(input_shape=(28, 28)),
    keras.layers.Dense(128, activation=tf.nn.relu),
    keras.layers.Dense(64, activation=tf.nn.relu),
    keras.layers.Dense(10, activation=tf.nn.softmax)
])

이제 모델을 컴파일합니다.

model.compile(optimizer='adam',
              loss='categorical_crossentropy',
              metrics=['accuracy'])

모델을 학습시킵니다.

model.fit(train_images, train_labels, epochs=5)

마지막으로 모델을 평가합니다.

test_loss, test_acc = model.evaluate(test_images, test_labels)
print('Test accuracy:', test_acc)

전체 코드는 다음과 같습니다.

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
from tensorflow.keras.datasets import mnist

# MNIST 데이터셋 로드
(x_train, y_train), (x_test, y_test) = mnist.load_data()

# 데이터 전처리
x_train = x_train / 255.0
x_test = x_test / 255.0

# 모델 구성
model = tf.keras.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dense(10, activation='softmax')
])

# 모델 컴파일
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

# 모델 훈련
model.fit(x_train, y_train, epochs=5, validation_data=(x_test, y_test))

# 모델 평가
test_loss, test_acc = model.evaluate(x_test, y_test, verbose=2)
print('\nTest accuracy:', test_acc)

# 예측 결과 확인
predictions = model.predict(x_test)

# 예측 결과 시각화
num_rows = 5
num_cols = 3
num_images = num_rows*num_cols
plt.figure(figsize=(2*2*num_cols, 2*num_rows))
for i in range(num_images):
  plt.subplot(num_rows, 2*num_cols, 2*i+1)
  plt.imshow(x_test[i], cmap='gray')
  plt.axis('off')
  predicted_label = np.argmax(predictions[i])
  true_label = y_test[i]
  if predicted_label == true_label:
    color = 'blue'
  else:
    color = 'red'
  plt.subplot(num_rows, 2*num_cols, 2*i+2)
  plt.bar(range(10), predictions[i], color=color)
  plt.xticks(range(10))
  plt.ylim([0, 1])
  plt.tight_layout()

이 코드는 TensorFlow를 사용하여 MNIST 데이터셋에 있는 손글씨 숫자 이미지를 분류하는 모델을 학습하고, 학습된 모델을 이용하여 테스트 데이터셋에 있는 이미지를 분류하는 코드입니다. 코드 실행을 위해서는 TensorFlow와 NumPy, Matplotlib 라이브러리가 필요합니다. 또한, Google Colab에서 실행할 경우 !pip install tensorflow numpy matplotlib 명령어를 사용하여 라이브러리를 설치해야 합니다.

[양자코딩] 양자 컴퓨팅으로 1과 2를 더하면 100이 될 수도 있다.

다음의 양자 코드를 (Corlab) 실행해 봅니다.

이것은 1과 2를 더한 것입니다.

실행하기

실행결과는 Counter({2: 10}) 라고 나옵니다.

뜻은 2라는 결과가 10번 나왔다고 합니다.
위의 코드에서 2가 출력된 이유는 1과 2를 더하는 양자 게이트가 실험을 실행할 때 2가 나오는 경우가 10번 발생했기 때문입니다. 즉, 1과 2를 더해서 3이라는 값이 나올 확률은 0이었거나 매우 작았기 때문에, 2가 나온 횟수가 더 많았던 것입니다.

양자 컴퓨팅에서는 측정 과정에서 확률적인 결과가 나타납니다. 따라서 1과 2를 더한 결과가 3이 나올 확률은 높지만, 2가 나올 확률도 있습니다. 이러한 확률적인 특성 때문에 양자 컴퓨팅에서는 동일한 계산을 여러 번 실행해서 결과를 확인하는 등의 작업이 필요합니다.

양자 컴퓨터는 일반적인 논리 게이트가 아닌 양자 게이트를 사용하기 때문에, 때로는 다른 결과를 낼 수 있습니다. 예를 들어, 두 개의 양자 비트를 더하는 과정에서 캐리(Carry) 값이 발생할 수 있고, 이 캐리 값은 고전 컴퓨팅에서는 필요하지 않은 개념입니다. 따라서 양자 컴퓨터는 덧셈 연산에서도 다른 결과를 낼 수 있습니다.

 

import cirq

# 입력 비트를 저장할 양자 비트
qubits = [cirq.LineQubit(i) for i in range(2)]

# 양자 게이트를 사용하여 입력을 준비합니다.
circuit = cirq.Circuit(
    cirq.X(qubits[0]), # 1을 나타내는 비트를 설정합니다.
    cirq.X(qubits[1]), # 2를 나타내는 비트를 설정합니다.
    cirq.CNOT(qubits[0], qubits[1]), # XOR 게이트를 수행합니다.
    cirq.measure(*qubits, key='result') # 결과를 측정합니다.
)

# 시뮬레이터를 만들고 양자 회로를 실행합니다.
simulator = cirq.Simulator()
result = simulator.run(circuit, repetitions=10)

# 결과를 출력합니다.
print(result.histogram(key='result'))

 

그럼 3이라는 결과를 내기 위해서는?

양자컴퓨터에서 측정결과는 확률적으로 나타나며, 계산의 정확성은 측정 횟수에 따라 달라집니다.

위에서는 repetitions 값을 10으로 설정하여, 측정을 10번 수행한 결과가 출력되었습니다. 그러나 양자컴퓨터에서는 계산 중간에 상태벡터가 존재하며, 이는 양자역학의 원리에 따라 확률적인 값으로 나타나게 됩니다.

따라서 덧셈 게이트를 사용하여 계산한 후, 측정을 수행하여 3이 출력될 확률이 높은 것으로 나타납니다. 하지만 측정결과는 2가 나올 확률이 존재하기 때문에, 반복횟수를 늘리면 더욱 정확한 결과를 얻을 수 있습니다.

양자 컴퓨팅으로 1과 2를 더하면 3이 아닌 100이 될 수도 있는가?

양자 컴퓨팅에서도 계산에는 오류가 존재할 수 있습니다. 이러한 오류는 노이즈와 양자 비트의 불안정성으로 인해 발생합니다. 그러나 오류는 확률적인 형태로 발생하며, 오류가 발생할 확률은 특히 오류 정정 기술을 이용하여 줄일 수 있습니다. 따라서 이론적으로 가능성은 낮지만 양자 컴퓨팅에서 1과 2를 더하면 3이 아닌 100이 될 수 있는 가능성이 존재합니다.

고성능 딥러닝 프레임워크 JAX (Corlab)

JAX (Just After eXecution;실행직후)
JAX 라이브러리는 TensorFlow와 유사한 기능을 가지고 있으며, 특히 자동 미분과 XLA(accelerated linear algebra) 및 JIT(just-in-time) 컴파일 기능을 강조합니다. 이러한 기능은 머신러닝 알고리즘을 더욱 효율적으로 구현하고 최적화하는 데 도움이 됩니다.

JAX 라이브러리가 “Just After eXecution”의 약자로 실행직후 라는 이름을 가지게 된것은,  NumPy, SciPy, PyTorch 등과 같은 수치 연산 라이브러리와 같이 계산 그래프를 구성하고 실행하기 직전까지 모든 것이 동적으로 결정되는 동적 계산 그래프 (dynamic computation graph) 라이브러리이기 때문입니다. 이러한 동적 계산 그래프 방식은 머신러닝 프레임워크에서 일반적으로 사용되는 정적 계산 그래프와 대조적입니다. JAX는 JIT(Just-In-Time) 컴파일러와 함께 사용되어 동적 계산 그래프를 효율적으로 컴파일하여 실행 시간을 최적화합니다. 따라서 “Just After eXecution”이라는 이름이 지어진 것입니다.

JAX는 pip로 설치할 수 있으며, 아래 명령어를 사용하여 설치할 수 있습니다.

pip install jax jaxlib

다만, JAX는 GPU를 사용하기 때문에 GPU가 없는 경우 CPU 버전으로 설치해야 합니다. GPU가 없는 경우 아래 명령어를 사용하여 설치할 수 있습니다.

pip install jax jaxlib==0.1.70+cpu -f https://storage.googleapis.com/jax-releases/jax_releases.html

 

아래는 JAX를 사용하여 간단한 선형 회귀 모델을 구현하는 예시입니다.GPU 가 없는 컴퓨터를 사용하시는 분을 위해 구글 colab에서 실행 가능하도록 작성되었습니다.

실행하기

 import jax.numpy as jnp
from jax import grad

# 선형회귀 모델 함수
def linear_regression(X, w):
    return jnp.dot(X, w.T)

# 평균제곱오차 손실 함수
def mse_loss(y_true, y_pred):
    return jnp.mean((y_true - y_pred) ** 2)

# 경사하강법 함수
def gradient_descent(w, X, y, learning_rate):
    grad_func = grad(mse_loss)
    grad_w = grad_func(y, linear_regression(X, w))
    return w - learning_rate * grad_w

# 입력과 출력 정의
X = jnp.array([[1., 1.], [2., 2.], [3., 3.], [4., 4.]])
y = jnp.array([[2.], [4.], [6.], [8.]])

# 가중치 초기값 설정
w = jnp.array([[1., 1.]])

# 학습
for epoch in range(10):
    # 예측 계산
    y_pred = linear_regression(X, w)

    # 손실 계산
    loss = mse_loss(y, y_pred)
    print(f"에포크 {epoch}\n가중치: {w}\n손실: {loss}\n예측결과: {y_pred}")

    # 경사하강법을 사용하여 가중치 갱신
    w = gradient_descent(w, X, y, 0.1)

git

JAX가 tensorflow 보다  쌘놈인가?

 

JAX (Just After eXecution) 는 기계 학습 라이브러리로, Google에서 개발했습니다. TensorFlow와 마찬가지로 JAX도 딥 러닝 모델을 만들고 훈련시키는 데 사용됩니다. 그러나 TensorFlow와 JAX 사이에는 몇 가지 차이점이 있습니다.

첫째, JAX는 미분 가능한 함수만 허용합니다. 이는 딥 러닝 모델을 구축하는 데 도움이 됩니다. 미분 가능한 함수는 모든 미분 가능한 지점에서 기울기를 가지기 때문입니다. JAX는 이러한 함수만 지원하므로 모델에서 발생할 수 있는 다양한 오류를 방지할 수 있습니다.

둘째, JAX는 함수를 컴파일하고 JIT(Just-in-time) 컴파일러로 컴파일합니다. 이는 계산 속도를 빠르게 만들어줍니다. TensorFlow와 같은 라이브러리는 모델을 그래프로 변환한 다음 실행합니다. 반면 JAX는 모델을 즉시 컴파일하고 실행합니다.

셋째, JAX는 TensorFlow와 비교해 더 깔끔한 구문을 제공합니다. TensorFlow는 상태 변수와 그래프를 별도로 추적해야 하지만 JAX는 함수형 프로그래밍을 사용하여 코드를 작성하므로 보다 간결합니다.

JAX와 TensorFlow는 모두 딥러닝 라이브러리이지만, 각각의 장단점이 있습니다. 따라서 뛰어난 것은 사용하는 목적과 상황에 따라 다릅니다.

JAX는 JAX를 이용한 코드는 다른 프레임워크와 달리 일부 또는 전체가 컴파일됩니다. 이는 빠른 속도와 함께 간소화된 코드를 제공합니다. 또한 JAX는 XLA 컴파일러를 사용하므로, TPU에서 더 빠르게 실행할 수 있습니다.

반면, TensorFlow는 이미 매우 널리 사용되고 있으며, TensorFlow 기반의 라이브러리 및 프레임워크가 많이 개발되어 있습니다. TensorFlow는 또한 다양한 하드웨어를 지원하며, 자체적으로 GPU를 활용하여 연산을 가속화할 수 있습니다.

따라서 뛰어난 것은 사용하는 목적과 상황에 따라 다르므로, 적절한 상황에서 적합한 도구를 선택하는 것이 중요합니다.

다음은 위에 JAX로 작성된 선형 회귀 모델 코드를 TensorFlow로 변환한 예시입니다.
JAX는 TensorFlow와 비슷한 API를 가지고 있기 때문에 코드 변환이 그리 어렵지 않습니다. 그러나 두 라이브러리의 내부 구현 방식이 다르기 때문에 성능 차이가 있을 수 있습니다. 또한 TensorFlow는 GPU를 이용한 병렬 처리에 대한 지원이 더욱 뛰어나기 때문에 대규모 데이터에 대한 학습 속도에서 우위를 보입니다.

import tensorflow as tf
import numpy as np

# 입력과 출력 정의
X = np.array([[1., 1.], [2., 2.], [3., 3.], [4., 4.]])
y = np.array([[2.], [4.], [6.], [8.]])

# 가중치 초기값 설정
w = tf.Variable(np.array([[1., 1.]]))

# 선형 회귀 모델 함수
def linear_regression(X, w):
    return tf.matmul(X, tf.transpose(w))

# 평균제곱오차 손실 함수
def mse_loss(y_true, y_pred):
    return tf.reduce_mean(tf.square(y_true - y_pred))

# 경사하강법 함수
def gradient_descent(w, X, y, learning_rate):
    with tf.GradientTape() as tape:
        y_pred = linear_regression(X, w)
        loss = mse_loss(y, y_pred)
    grads = tape.gradient(loss, w)
    w.assign_sub(learning_rate * grads)
    return w

# 학습
for epoch in range(10):
    # 예측 계산
    y_pred = linear_regression(X, w)

    # 손실 계산
    loss = mse_loss(y, y_pred)
    print(f"에포크 {epoch}\n가중치: {w}\n손실: {loss}\n예측결과: {y_pred.numpy()}")

    # 경사하강법을 사용하여 가중치 갱신
    w = gradient_descent(w, X, y, 0.1)

 

아래는 jax로 작성된 코드를 tensorflow도 사용하지 말고, python으로 코딩한 예시입니다. 속도 측면에서는 jax나 tensorflow보다 느릴 수 있습니다.

 

import numpy as np

# 선형회귀 모델 함수
def linear_regression(X, w):
    return np.dot(X, w.T)

# 평균제곱오차 손실 함수
def mse_loss(y_true, y_pred):
    return np.mean((y_true - y_pred) ** 2)

# 경사하강법 함수
def gradient_descent(w, X, y, learning_rate):
    def mse_grad(y, y_pred):
        return -2 * np.mean((y - y_pred) * X, axis=0)
    
    grad_w = mse_grad(y, linear_regression(X, w))
    return w - learning_rate * grad_w

# 입력과 출력 정의
X = np.array([[1., 1.], [2., 2.], [3., 3.], [4., 4.]])
y = np.array([[2.], [4.], [6.], [8.]])

# 가중치 초기값 설정
w = np.array([[1., 1.]])

# 학습
for epoch in range(10):
    # 예측 계산
    y_pred = linear_regression(X, w)

    # 손실 계산
    loss = mse_loss(y, y_pred)
    print(f"에포크 {epoch}\n가중치: {w}\n손실: {loss}\n예측결과: {y_pred}")

    # 경사하강법을 사용하여 가중치 갱신
    w = gradient_descent(w, X, y, 0.1)

JAX의 자동 미분 기능

JAX는 자동 미분 기능을 내장하고 있기 때문에 딥러닝 모델의 학습에 필요한 그래디언트 계산을 자동으로 수행할 수 있습니다.딥러닝에서 모델 학습은 주로 그래디언트 기반 최적화 알고리즘을 사용하여 이루어집니다. 그래디언트 기반 최적화 알고리즘은 손실 함수의 그래디언트를 계산하여 모델 파라미터를 업데이트하는 방식으로 작동합니다. 따라서 자동 미분 기능이 없으면 그래디언트를 직접 계산해야 하는 번거로움이 있습니다.

JAX는 그래디언트 자동 계산 기능을 제공함으로써 이러한 번거로움을 줄여줍니다. 이를 통해 개발자는 모델 학습에 집중할 수 있습니다.

예를 들어, 다음과 같은 간단한 신경망 모델이 있다고 가정해봅시다.

실행#JAX의 자동 미분 기능

import jax.numpy as jnp
from jax import grad

def loss_fn(params, x, y_true):
    y_pred = jnp.dot(x, params)
    loss = jnp.mean((y_pred - y_true) ** 2)
    return loss

params = jnp.array([0.5, -0.2, 1.0])
x = jnp.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
y_true = jnp.array([10, 20, 30])

grad_loss_fn = grad(loss_fn)

grad_params = grad_loss_fn(params, x, y_true)

print(grad_params)

위 코드에서는 간단한 3개의 입력값과 1개의 출력값을 가지는 선형 회귀 모델을 정의하였습니다. 이 모델의 손실 함수(loss function)는 평균 제곱 오차(Mean Squared Error)를 사용하였습니다. 그리고 이 손실 함수의 그래디언트(gradient)를 자동으로 계산하기 위해 JAX의 grad 함수를 이용하였습니다.

grad 함수는 함수의 인수로 전달된 함수의 그래디언트를 계산하여 반환하는 함수입니다. grad 함수가 반환한 그래디언트 값은 params에 대한 손실 함수의 편미분값이므로, 이 값은 params를 어떻게 업데이트해야 하는지 알려주는 방향성을 가집니다. 따라서 이 값을 이용하여 모델의 가중치(weight)를 업데이트하면 됩니다.

위 코드를 실행하면, grad_params의 값으로[-128.40001, -154.40001, -180.40001] 이 출력됩니다. 이 값은 입력값 x가 [1.0, 2.0, 3.0]일 때, 손실 함수를 x의 각 요소에 대해서 미분한 그래디언트 벡터를 의미합니다.

keras의 내장된 datasets

Keras는 딥 러닝 모델을 개발할 때 데이터셋을 준비하는 것이 매우 중요하다는 것을 인식하고 있습니다. 따라서 Keras는 기본적으로 사용자들이 쉽게 활용할 수 있는 몇 가지 대표적인 데이터셋을 내장하고 있습니다.

이러한 내장된 데이터셋은 딥 러닝 알고리즘 개발 및 테스트를 위해 사용될 수 있습니다. 또한 이러한 데이터셋을 사용하면 실제 문제와 비교적 유사한 가상 문제를 다룰 수 있으므로 딥 러닝 모델의 효과적인 훈련 및 성능 향상을 위한 기반을 제공합니다.

내장된 데이터셋을 활용하면 데이터 수집, 전처리 및 로딩 등의 불필요한 작업을 줄일 수 있으며, 쉽게 사용 가능한 예제 데이터를 통해 새로운 딥 러닝 모델 개발에 대한 진입 장벽을 낮출 수 있습니다. 이는 개발자들이 더 높은 수준의 추상화를 통해 딥 러닝 모델을 구축할 수 있도록 하여 생산성을 높이고 딥 러닝 기술의 보급과 발전을 촉진하는 데 기여합니다.

 

Keras는 다음과 같은 다양한 내장 데이터셋을 제공합니다.

  1. CIFAR10과 CIFAR100: 10개 또는 100개의 클래스로 구성된 32×32 크기의 컬러 이미지 데이터셋입니다. (https://www.cs.toronto.edu/~kriz/cifar.html)
  2. MNIST: 10개의 클래스로 구성된 28×28 흑백 손글씨 이미지 데이터셋입니다. (http://yann.lecun.com/exdb/mnist/)
  3. Fashion-MNIST: 10개의 클래스로 구성된 28×28 흑백 의류 이미지 데이터셋입니다. (https://github.com/zalandoresearch/fashion-mnist)
  4. IMDB: 영화 리뷰의 텍스트 데이터셋으로 긍정적인 리뷰와 부정적인 리뷰를 구분하는 이진 분류 문제입니다. (https://ai.stanford.edu/~amaas/data/sentiment/)
  5. Reuters: 뉴스 기사의 텍스트 데이터셋으로 46개의 클래스로 구성된 다중 분류 문제입니다. (https://archive.ics.uci.edu/ml/datasets/reuters-21578+text+categorization+collection)
  6. Boston Housing: 보스턴의 주택 가격과 주택 가격에 영향을 미치는 여러 가지 요소들의 데이터셋입니다. (https://archive.ics.uci.edu/ml/datasets/Housing)
  7. MNIST Fashion: 패션 이미지를 10개의 클래스로 분류하는 데이터셋입니다. (https://github.com/zalandoresearch/fashion-mnist)

이 외에도 Keras는 다양한 외부 데이터셋을 불러오고 활용할 수 있도록 API를 제공합니다.

머신러닝 이용 뇌종양 MRI 사진 판독 웹 앱 서비스 만들기

프로젝트 구현 사이트 보기 : 머신러닝 이용 뇌종양 MRI 사진 판독 서비스

 

여기서는  Streamlit 을 사용한 웹 앱으로 서비스를 만들어 봅니다.
이미지 분류는 이미지 파일의 내용을 기반으로 미리 정의 된 특정 클래스에 이미지를 할당 할 수있는 컴퓨터 시각인식 모델 알고리즘 입니다.
이를 통해 우리가 서비스할 프로그램이 이미지 데이터에 대한 분류 및 정렬 작업을 수행 할 수 있도록하는 데 사용됩니다.
여기서 사용할 분류기는 Google Teachable Machine을 이용해 사전 훈련된 모델을 이용할 것이며 Python을 사용합니다.

이 강좌는 다음의 사전 지식을 기반으로 진행합니다.

  1.  app.py라는 파일을 만듭니다. 웹 페이지에 콘텐츠를 표시하는 Streamlit 코드를 포함하는 파일입니다.

 

 

import streamlit as st
from PIL import Image

st.set_option('deprecation.showfileUploaderEncoding', False) # deprecation 표시 안함 
st.title("머신러닝 이용 뇌종양 MRI 사진 판독 서비스")
st.markdown("""
뇌종양 MRI 사진을 분류합니다. 
이 서비스는 의사들의 뇌 MRI 사진 판독의 도우미일 뿐입니다. 
정확한 최종 진단 결과는 반드시 전문 담당 의사의 확인과 승인을 거치십시요.""")

image2 = Image.open('brain.jpg')
st.image(image2, caption='shop2world.com 뇌종양 MRI 판독 서비스',use_column_width=True)

 

2.이미지 분류 모델 만들기

https://teachablemachine.withgoogle.com/train

구글 Teachable Machine을 사용해 여러분은 이미지뿐 아니라 , 오디오 또는 포즈 프로젝트를 만들 수 있습니다. 이 경우 이미지 분류 프로젝트로서 Image Project를 선택합니다.

데이터셋

훈련을 위해서는 데이터가 필요합니다. 여기서는 Kaggle의 뇌종양 검출 데이터 셋을 다운로드 받아 압축을 푸세요.

https://www.kaggle.com/navoneel/brain-mri-images-for-brain-tumor-detection

(캐글에서 다운로드 안될 경우 여기서도 다운로드 가능합니다.)

이미지 분류 페이지에서 종양이 있는 뇌와 없는 뇌를 구분하는 클래스를 만들어 라벨링 작업을 하고, 해당 클래스에 이미지를 업로드하고 학습을 시킵니다.
그리고 완료되면 훈련된 파일(확장자가 .h5 인 가중치 파일)을 다운로드 해, 이것을 이용해 서비스를 제공합니다.

동영상의 설명을 보면서 함께 해 봅니다.

 

3그리고 Export에 보면 다음과 같이 적용 예 소스가 있습니다.
우리는 이것을 기반으로 streamlit에서 아래 소스의 model 부분과 image 부분을 분리해 처리하도록 만들겠습니다.

model = tensorflow.keras.models.load_model('keras_model.h5')

image = Image.open('test_photo.jpg')

import tensorflow.keras
from PIL import Image, ImageOps
import numpy as np

# Disable scientific notation for clarity
np.set_printoptions(suppress=True)

# Load the model
model = tensorflow.keras.models.load_model('keras_model.h5')

# Create the array of the right shape to feed into the keras model
# The 'length' or number of images you can put into the array is
# determined by the first position in the shape tuple, in this case 1.
data = np.ndarray(shape=(1, 224, 224, 3), dtype=np.float32)

# Replace this with the path to your image
image = Image.open('test_photo.jpg')

#resize the image to a 224x224 with the same strategy as in TM2:
#resizing the image to be at least 224x224 and then cropping from the center
size = (224, 224)
image = ImageOps.fit(image, size, Image.ANTIALIAS)

#turn the image into a numpy array
image_array = np.asarray(image)

# display the resized image
image.show()

# Normalize the image
normalized_image_array = (image_array.astype(np.float32) / 127.0) - 1

# Load the image into the array
data[0] = normalized_image_array

# run the inference
prediction = model.predict(data)
print(prediction)

나머지 부분은 기본적으로 동일하게 사용하고 app.py가있는 동일한 폴더에서 img_classification.py라는 파일을 만들고 다음과 같이 해 줍니다.

 

 

import keras
from PIL import Image, ImageOps
import numpy as np


def mri_machine_classification(img, weights_file):
    # 모델로드
    model = keras.models.load_model(weights_file)

    # keras 모델에 공급할 올바른 모양의 배열을 만듭니다.
    data = np.ndarray(shape=(1, 224, 224, 3), dtype=np.float32)
    image = img
    #이미지 크기 조정
    #resize the image to a 224x224 with the same strategy as in TM2:
    #resizing the image to be at least 224x224 and then cropping from the center
    size = (224, 224)
    image = ImageOps.fit(image, size, Image.ANTIALIAS)

    #이미지를 numpy 배열로 바꿈.
    image_array = np.asarray(image)
    # 이미지 정규화
    normalized_image_array = (image_array.astype(np.float32) / 127.0) - 1

    # 이미지를 배열에로드
    data[0] = normalized_image_array

    # 예측 시작 
    prediction = model.predict(data)
    return np.argmax(prediction) # 가장 높은 확률의 반환 위치

그리고 app.py 에서는 이미지를 업로드 하고, .h5 모델을 불러와 주는 부분을 추가합니다.



st.text("***이미지 분류를 위해 뇌 MRI 이미지를 업로드 해 주세요***")
#Streamlit 파일 처리 및 결과
#https://stackoverflow.com/questions/50906123/nameerror-name-image-is-not-defined/50906222
from PIL import Image, ImageOps

from img_classification import mri_machine_classification
uploaded_file = st.file_uploader("뇌 MRI 사진을 업로드 해 주세요.", type=['jpeg', 'png', 'jpg', 'webp'])
if uploaded_file is not None:
        image = Image.open(uploaded_file)
        st.image(image, caption='Uploaded MRI.', use_column_width=True)
        st.write("")
        st.write("처리중입니다...")
        label = mri_machine_classification(image, 'keras_model.h5')
        if label == 0:
            st.write("***결과 : MRI 스캔에는 뇌종양이 있습니다***")
        else:
            st.write("***결과 : MRI 스캔은 건강합니다***")


app.py의 전체 소스코드는 다음과 같습니다.

import streamlit as st
from PIL import Image

st.set_option('deprecation.showfileUploaderEncoding', False) # deprecation 표시 안함 
st.title("머신러닝 이용 뇌종양 MRI 사진 판독 서비스")
st.markdown("""
뇌종양 MRI 사진을 분류합니다. 
이 서비스는 의사들의 뇌 MRI 사진 판독의 도우미일 뿐입니다. 
정확한 최종 진단 결과는 반드시 전문 담당 의사의 확인과 승인을 거치십시요.""")

image2 = Image.open('brain.jpg')
st.image(image2, caption='shop2world.com 뇌종양 MRI 판독 서비스',use_column_width=True)


st.text("***이미지 분류를 위해 뇌 MRI 이미지를 업로드 해 주세요***")
#Streamlit 파일 처리 및 결과
from PIL import Image, ImageOps

from img_classification import mri_machine_classification
uploaded_file = st.file_uploader("뇌 MRI 사진을 업로드 해 주세요.", type=['jpeg', 'png', 'jpg', 'webp'])
if uploaded_file is not None:
        image = Image.open(uploaded_file)
        st.image(image, caption='Uploaded MRI.', use_column_width=True)
        st.write("")
        st.write("처리중입니다...")
        label = mri_machine_classification(image, 'keras_model.h5')
        if label == 0:
            st.write("***결과 : MRI 스캔에는 뇌종양이 있습니다***")
        else:
            st.write("***결과 : MRI 스캔은 건강합니다***")

그리고 이제 heroku 서버에 업로드 해서 적용 합니다.

다음의 세가지 파일을 만듭니다.

setup.sh

mkdir -p ~/.streamlit/

echo “\
[server]\n\
headless = true\n\
enableCORS=false\n\
port = $PORT\n\
” > ~/.streamlit/config.toml

 

Procfile

web: sh setup.sh && streamlit run app.py

requirements.txt

numpy
streamlit
pillow
keras
tensorflow

이제 모든 파일이 준비되어 하드디스크에서 업로드 할때 먼저 깃 리파지토리 초기화를 합니다.

git init

 

그리고 다음의 절차를 거쳐서 업로드 합니다.

heroku login
heroku create
git add .
git commit -m “Some message”
git push heroku master

 

만약 업데이트만 해줄 때는 다음과 같이 합니다. (// 뒤는 주석 설명이므로 타이핑 할 필요 없습니다.)

git add . // 변경사항 add
git commit -m “sopt 최고” // 스테이징
git push heroku master // 업데이트

최종 결과

https://shop2titanic.herokuapp.com/

전체 소스 코드
https://ai.shop2world.net/data/mri_brain.zip

결론

머신러닝을 의료 서비스 분야에 적용하거나 우리 삶에 필요한 도움이 되도록 할때
일반인이 쉽게 적근할 수 있는 웹 앱 서비스로 구현하는 것은 필수 입니다.

관련 해당 서비스를 만들어 보았습니다.

머신러닝 프로젝트 개발 문의
– 세계최고의 머신러닝 두뇌가 포진한 몬트리올에서
여러분 상상을 초월한  미래형 프로젝트 진행이 가능합니다.
문의 이메일
info@shop2world.com

 

 

2 -2 순한맛! 파이썬 머신러닝 강좌 – 부동산 가격(월세) 예측 (Featured 사이킷런(Scikit-learn))

이번 강좌에서는 다중선형회귀(Multiple Linear Regression) 모델을 이용해서 월세(렌트비)를 예측합니다. 지난 시간에 배운 단순 선형회귀 모델 (y = m*X + b)와 달리 월세에 영향을 주는 것은 방의 갯수, 평수, 지하철 역과 거리 등의 여러 요인이 있습니다. 이런 다양한 주어진 데이터 x 를 통해 월세 y를 예측하려면 여러 개의 변수 x를 포함해야 하기 때문에 다중 선형회귀라(Multiple Linear Regression)고 하는 것입니다. 여기서는 pandas를 통해 주어진 데이터를 불러와서 사이킷런(Scikit-learn)에서 train_test_split을 통해 데이터 세트를 분리, 훈련, 테스트를 하고 선형 회귀 모델을 생성해서 테스트데이터를 넣어 예측 값(월세)을 생성합니다. 그리고 나서 그래프를 통해 상관 관계를 살펴봅니다. (예. 평수와 월세의 관계, 건물 년식과 월세와의 관계 등) 또 마지막으로 모델의 정확도를 score 함수로 평가합니다. 이 형태를 통해 데이터를 구하여 여러분이 예측하고 싶은 것들에 다양하게 활용 할 수 있습니다.

재생목록
소스코드
Data Set

Cost 함수 크로스 앤트로피 (Cross -Entropy)

크로스 엔트로피(Cross-Entropy)는 머신러닝에서 분류 문제를 해결하기 위해 주로 사용되는 손실 함수입니다. 이를 예를 들어 남녀 관계로 설명해보겠습니다.

예를 들어, 남녀 구분 문제에서는 머신러닝 모델이 주어진 입력 데이터(성별, 나이, 키 등)를 바탕으로 해당 데이터가 남자일 확률과 여자일 확률을 예측합니다. 이 때, 크로스 엔트로피는 모델이 예측한 확률 분포와 실제 레이블 분포 간의 차이를 계산하는 손실 함수입니다.

만약, 모델이 특정 입력 데이터를 바탕으로 해당 데이터가 남자일 확률을 0.7, 여자일 확률을 0.3으로 예측했다고 가정해봅시다. 그리고 실제로 해당 데이터가 남자인 경우를 1로, 여자인 경우를 0으로 나타낸다면, 실제 레이블 분포는 1과 0이 됩니다.

이 경우, 크로스 엔트로피 손실 함수는 다음과 같이 계산됩니다.

import numpy as np

# 모델이 예측한 확률 분포
y_pred = np.array([0.7, 0.3])

# 실제 레이블 분포
y_true = np.array([1, 0])

# 크로스 엔트로피 손실 함수 계산
loss = -np.sum(y_true * np.log(y_pred))
print(loss) # 0.35667494393873245

실행하기

따라서, 위의 경우 모델이 예측한 확률 분포와 실제 레이블 분포 간의 차이를 나타내는 크로스 엔트로피 손실 함수의 값은 약 0.357이 됩니다. 이 값은 모델의 예측이 실제와 얼마나 차이가 나는지를 나타내며, 이 값을 최소화하는 것이 모델을 학습시키는 목표가 됩니다.

 

 

Back Propagation(역전파)

Back Propagation(역전파)은 인공신경망에서 학습 알고리즘 중 하나로, 출력값과 지도 데이터(정답) 사이의 오차를 이용하여 역방향으로 각 층의 가중치를 조정하여 최적의 가중치를 찾는 알고리즘입니다.

Back Propagation은 다음과 같은 과정으로 이루어집니다.

1 순전파 (Forward Propagation)

입력 데이터를 입력층으로 받아서 순차적으로 은닉층을 거쳐 출력층까지 연산하여 출력값을 계산합니다.
2 오차 계산 (Error Calculation)

출력값과 지도 데이터(정답) 사이의 오차를 계산합니다.
3 역전파 (Back Propagation)

출력층에서부터 시작해서, 각 층의 가중치가 오차에 미치는 영향을 계산합니다.
이를 이용하여, 가중치를 조정합니다. 즉, 기울기(gradient)를 구하여, 경사 하강법(Gradient Descent)을 이용하여 가중치를 업데이트합니다.
4.2~3 과정을 반복 (Iteration)

이 과정을 여러번 반복하여 최적의 가중치를 찾습니다.
Back Propagation 알고리즘을 이용하여 인공신경망을 학습시키면, 입력 데이터와 지도 데이터를 이용하여 최적의 가중치를 찾아내어, 새로운 입력 데이터에 대해 정확한 출력 값을 예측할 수 있습니다.

이처럼

역전파(Back Propagation)는 신경망(Neural Network)의 가중치(Weight)를 효과적으로 조정하기 위한 알고리즘입니다. 이 알고리즘은 주어진 입력값에 대한 출력값과 실제값 간의 차이(오차)를 최소화하기 위해 사용됩니다.

이를 예시로 설명하자면, 남녀의 눈 색깔, 키, 머리 색깔 등을 입력값으로 사용하여 그 사람이 남성인지 여성인지를 분류하는 신경망 모델을 학습한다고 가정해봅시다. 이 모델은 입력값을 받아 출력값으로 남성인지 여성인지를 분류합니다.

역전파는 이 모델이 분류한 결과와 실제 결과 간의 차이(오차)를 계산하고, 이 오차가 가중치를 조정하는 데 어떤 영향을 미치는지를 파악합니다. 가중치를 조정하는 과정에서는 출력층에서 입력층으로 거꾸로 이동하며, 각 층의 노드에 해당하는 가중치를 업데이트합니다. 이렇게 업데이트된 가중치를 사용하여 다시 입력값에 대한 출력값을 계산하고, 오차를 줄이는 방향으로 학습을 진행합니다.

이렇게 반복적으로 학습을 진행하면, 모델은 입력값에 대해 정확한 분류 결과를 출력할 수 있게 됩니다. 이러한 방식으로 역전파 알고리즘을 이용하여 신경망 모델을 학습시킬 수 있습니다.