- 이전글
[작곡 인공지능 개발기] 3. 마르코프 체인을 이용한 작곡
본격적으로 신경망을 활용한 학습을 구현해보기 위해 다음 링크의 내용을 따라해보려고 한다.
https://tykimos.github.io/2018/09/14/How_to_Generate_Music_using_a_LSTM_Neural_Network_in_Keras/
케라스 LSTM 모델로 작곡하기
이 문서는 순환신경망(RNN)인 LSTM 과 Python 음악 툴킷인 music21 을 이용해서 작곡을 해보는 것에 대해 설명합니다. 2018년 8월을 기준으로, 동작하지 않는 코드는 동작하지 않는 부분을 동작하도록 변
tykimos.github.io
이 링크에 나오는 LSTM모델을 따라해보기 전에 우선 keras 라이브러리에 익숙해지고자 관련 예제를 찾아봤다.
keras는 tensorflow를 백엔드로 사용하는 신경망 라이브러리이다.
다행히도 TensorFlow 공식문서에 의류 데이터를 분류하는 관련 예제가 있었고, 먼저 이 예제를 살펴보려고 한다.
https://www.tensorflow.org/tutorials/keras/classification?hl=ko
기본 분류: 의류 이미지 분류 | TensorFlow Core
Google I/O는 끝입니다! TensorFlow 세션 확인하기 세션 보기 기본 분류: 의류 이미지 분류 이 튜토리얼에서는 운동화나 셔츠 같은 옷 이미지를 분류하는 신경망 모델을 훈련합니다. 상세 내용을 모두
www.tensorflow.org
의류 데이터 분류 예제 설명
이 예제는 10개의 범주(category)와 70,000개의 흑백 이미지로 구성된 패션 MNIST 데이터셋을 사용한다.
10개의 범주는 'T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat','Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot' 가 있다.
각 이미지는 28x28 픽셀로 표현되고, 각 픽셀 값의 범위는 0~255이다.
예제 코드는 데이터셋을 로드하고, 전처리하며, 신경망 모델을 구성하고, 훈련시키며 예측하는 일련의 과정을 모두 담고 있다.
예제 코드
예제에 나온 코드를 나름대로 주석을 달아가며 공부해본 내용을 첨부한다.
<classification.py>
# TensorFlow and tf.keras
import tensorflow as tf
# Helper libraries
import numpy as np
import matplotlib.pyplot as plt
print(tf.__version__)
#버전체크
fashion_mnist = tf.keras.datasets.fashion_mnist
(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
#학습용 패션 이미지와 테스트용 패션 이미지 다운로드
#이미지는 28x28 크기의 넘파이 배열이고 픽셀 값은 0과 255 사이입니다.
# 레이블(label)은 0에서 9까지의 정수 배열입니다.
# 이 값은 이미지에 있는 옷의 클래스(class)를 나타냅니다
# 레이블 클래스
# 0 T-shirt/top
# 1 Trouser
# 2 Pullover
# 3 Dress
# 4 Coat
# 5 Sandal
# 6 Shirt
# 7 Sneaker
# 8 Bag
# 9 Ankle boot
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
# train_images.shape -> (60000, 28, 28)
# len(train_labels) -> 60000
# train_labels -> array([9, 0, 0, ..., 3, 0, 5], dtype=uint8)
# test_images.shape -> (10000, 28, 28)
# len(test_labels) -> 10000
#데이터셋중 첫번쨰 데이터 시각화코드
# plt.figure()
# plt.imshow(train_images[0])
# plt.colorbar()
# plt.grid(False)
# plt.show()
#훈련,테스트이미지 값 전처리 (0 과 1 사이의 값으로 만들기)
train_images = train_images / 255.0
test_images = test_images / 255.0
#25개 데이터의 이미지-라벨 시각화 코드
# plt.figure(figsize=(10,10))
# for i in range(25):
# plt.subplot(5,5,i+1)
# plt.xticks([])
# plt.yticks([])
# plt.grid(False)
# plt.imshow(train_images[i], cmap=plt.cm.binary)
# plt.xlabel(class_names[train_labels[i]])
# plt.show()
#신경망 모델 구성
model = tf.keras.Sequential([
#2차원배열을 1차원 배열로 변환
tf.keras.layers.Flatten(input_shape=(28, 28)),
#128개 노드가진 dense 층, activation function 으로 relu사옹
tf.keras.layers.Dense(128, activation='relu'),
# 0~9라벨 대응 10개 확률 반환 층
tf.keras.layers.Dense(10)
])
# 이 네트워크의 첫 번째 층인 tf.keras.layers.Flatten은 2차원 배열(28 x 28 픽셀)의 이미지 포맷을
# 28 * 28 = 784 픽셀의 1차원 배열로 변환합니다. 이 층은 이미지에 있는 픽셀의 행을 펼쳐서 일렬로 늘립니다.
# 이 층에는 학습되는 가중치가 없고 데이터를 변환하기만 합니다.
# 픽셀을 펼친 후에는 두 개의 tf.keras.layers.Dense 층이 연속되어 연결됩니다.
# 이 층을 밀집 연결(densely-connected) 또는 완전 연결(fully-connected) 층이라고 부릅니다.
# 첫 번째 Dense 층은 128개의 노드(또는 뉴런)를 가집니다.
# 두 번째 (마지막) 층은 10개의 노드의 소프트맥스(softmax) 층입니다.
# 이 층은 10개의 확률을 반환하고 반환된 값의 전체 합은 1입니다.
# 각 노드는 현재 이미지가 10개 클래스 중 하나에 속할 확률을 출력합니다.
#손실함수로 크로스 엔트로피 손실함수 사용
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
metrics=['accuracy'])
#https://wandb.ai/wandb_fc/korean/reports/---VmlldzoxNDI4NDUx
#크로스 엔트로피 손실함수 설명 링크
# 모델 훈련
# 신경망 모델을 훈련하려면 다음 단계가 필요합니다.
# 훈련 데이터를 모델에 주입합니다- 이 예에서는 train_images와 train_labels 배열입니다.
# 모델이 이미지와 레이블을 매핑하는 방법을 배웁니다.
# 테스트 세트에 대한 모델의 예측을 만듭니다-이 예에서는 test_images 배열입니다.
# 이 예측이 test_labels 배열의 레이블과 맞는지 확인합니다.
# 예측이 test_labels 배열의 레이블과 일치하는지 확인합니다.
#훈련을 시작하려면 model.fit 메서드를 호출합니다. 모델을 훈련 데이터에 "맞추기(fit)" 때문에 이렇게 불립니다.
#backpropagation algorithm에서 forward pass한 번 + backward pass한 번이 한번의 epoch
#모델을 만들 때 적절한 epoch 값을 설정해야만 underfitting과 overfitting을 방지할 수 있음
#epoch 값이 너무 작다면 underfitting이 너무 크다면 overfitting이 발생할 확률이 높은 것
model.fit(train_images, train_labels, epochs=10)
# 정확도 평가
# 다음으로, 모델이 테스트 데이터세트에서 작동하는 방식을 비교
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print('\nTest accuracy:', test_acc)
#113 line 실행결과
# This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations: AVX2 FMA
# To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
# Epoch 1/10
# 1875/1875 [==============================] - 3s 2ms/step - loss: 0.4978 - accuracy: 0.8245
# Epoch 2/10
# 1875/1875 [==============================] - 3s 2ms/step - loss: 0.3776 - accuracy: 0.8645
# Epoch 3/10
# 1875/1875 [==============================] - 3s 2ms/step - loss: 0.3377 - accuracy: 0.8772
# Epoch 4/10
# 1875/1875 [==============================] - 3s 2ms/step - loss: 0.3115 - accuracy: 0.8849
# Epoch 5/10
# 1875/1875 [==============================] - 3s 2ms/step - loss: 0.2939 - accuracy: 0.8920
# Epoch 6/10
# 1875/1875 [==============================] - 3s 2ms/step - loss: 0.2795 - accuracy: 0.8965
# Epoch 7/10
# 1875/1875 [==============================] - 3s 2ms/step - loss: 0.2681 - accuracy: 0.9005
# Epoch 8/10
# 1875/1875 [==============================] - 3s 2ms/step - loss: 0.2562 - accuracy: 0.9052
# Epoch 9/10
# 1875/1875 [==============================] - 3s 2ms/step - loss: 0.2487 - accuracy: 0.9078
# Epoch 10/10
# 1875/1875 [==============================] - 3s 2ms/step - loss: 0.2385 - accuracy: 0.9110
# 313/313 - 0s - loss: 0.3473 - accuracy: 0.8806 - 397ms/epoch - 1ms/step
# 121 line 실행결과
# Test accuracy: 0.8805999755859375
#테스트 세트의 정확도가 훈련 세트의 정확도보다 조금 낮습니다. 0.9110> 0.0.8805999755859375
#훈련 세트의 정확도와 테스트 세트의 정확도 사이의 차이는 과대적합(overfitting) 때문입니다.
#과대적합은 머신러닝 모델이 훈련 데이터보다 새로운 데이터에서 성능이 낮아지는 현상을 말합니다.
# 예측하기
# 훈련된 모델을 사용하여 일부 이미지에 대한 예측을 수행할 수 있습니다.
# 모델의 선형 출력, 로짓. 소프트맥스 레이어를 연결하여 로짓을 해석하기 쉬운 확률로 변환합니다.
#
probability_model = tf.keras.Sequential([model, tf.keras.layers.Softmax()])
#probability_model에 test_images입력하여 라벨별 확률 배열 반환
predictions = probability_model.predict(test_images)
#첫 번째 데이터의 확률 배열
# print("predictions[0] : "+ str(predictions[0]))
# #확률배열에서 가장 높은 라벨 값 반환
# print("np.argmax(predictions[0]) : "+ str(np.argmax(predictions[0])))
# #실제 첫 번째 데이터의 라벨 값과 비교
# print("test_labels[0] : " + str(test_labels[0]))
#161 ~171 실행 결과
# predictions[0] : [3.2637752e-05 6.2541337e-09 9.4678709e-09 5.9356329e-09 2.7046305e-08
# 2.3374294e-03 8.9446411e-07 3.0109612e-02 1.0862083e-06 9.6751827e-01]
# np.argmax(predictions[0]) : 9
# test_labels[0] : 9
#전체 실행결과 시각화위한 함수 정의
def plot_image(i, predictions_array, true_label, img):
true_label, img = true_label[i], img[i]
plt.grid(False)
plt.xticks([])
plt.yticks([])
plt.imshow(img, cmap=plt.cm.binary)
predicted_label = np.argmax(predictions_array)
if predicted_label == true_label:
color = 'blue'
else:
color = 'red'
plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
100*np.max(predictions_array),
class_names[true_label]),
color=color)
def plot_value_array(i, predictions_array, true_label):
true_label = true_label[i]
plt.grid(False)
plt.xticks(range(10))
plt.yticks([])
thisplot = plt.bar(range(10), predictions_array, color="#777777")
plt.ylim([0, 1])
predicted_label = np.argmax(predictions_array)
thisplot[predicted_label].set_color('red')
thisplot[true_label].set_color('blue')
# 3*5 = 15개 데이터에 대한 0~9 라벨별 확률 시각화
# argmax의 라벨 값과 실제 데이터 값의 라벨 값이 같으면 파란색,아니면 빨간색으로 그래프 칠해놓음
# Plot the first X test images, their predicted labels, and the true labels.
# Color correct predictions in blue and incorrect predictions in red.
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)
plot_image(i, predictions[i], test_labels, test_images)
plt.subplot(num_rows, 2*num_cols, 2*i+2)
plot_value_array(i, predictions[i], test_labels)
plt.tight_layout()
plt.show()
# 훈련된 모델 사용하기
# 마지막으로 훈련된 모델을 사용하여 한 이미지에 대한 예측을 만듭니다.
# Grab an image from the test dataset.
#두번째 테스트 이미지 꺼내오기
img = test_images[1]
# print(img.shape)
# (28, 28)
# tf.keras 모델은 한 번에 샘플의 묶음 또는 배치(batch)로 예측을 만드는데 최적화되어 있습니다.
# 하나의 이미지를 사용할 때에도 2차원 배열로 만들어야 합니다:
# Add the image to a batch where it's the only member.
img = (np.expand_dims(img,0))
#expand_dims : (28, 28) -> (1, 28, 28) 예측 모델의 입력형식에 맞게 차원확장
print(img.shape)
# (1, 28, 28)
# 이제 이 이미지의 예측을 만듭니다:
predictions_single = probability_model.predict(img)
print(predictions_single)
# [[3.6173755e-05 3.2209617e-14 9.9866760e-01 1.6559891e-11 1.0769934e-03
# 1.6140698e-13 2.1918291e-04 3.4505306e-21 3.6745976e-10 1.0840150e-14]]
plot_value_array(1, predictions_single[0], test_labels)
_ = plt.xticks(range(10), class_names, rotation=45)
plt.show()
# tf.keras.Model.predict는 데이터 배치의 각 이미지에 대해 하나의 목록씩 목록의 목록을 반환합니다.
# 배치에서 (유일한) 이미지에 대한 예측을 가져옵니다.
np.argmax(predictions_single[0])
# 2
# 예상과 같이 모델이 레이블을 예측합니다.
학습 데이터셋을 통해 학습된 모델을 통해 테스트 데이터 셋을 분류해보았다.
실행결과, 각 데이터 별로 1~10번째 라벨에 부여된 확률을 담은 배열이 생성된다.
그 중에 가장 큰(argmax) 확률의 라벨이 실제 데이터에 대응하는 라벨과 같으면 파란색, 아니면 빨간색으로 그래프를 그려준다.
28*28 픽셀의 데이터인데도 epoch 10번 돌리는데 35초정도 걸렸다.
고화질 이미지를 사용하면 실행시간이 정말 한참 걸릴 것 같다.
이제 본격적으로 LSTM을 이용한 작곡 구현을 해보려고 한다.
- 다음 글