
신경망 시작하기: 분류와 회귀
from tensorflow.keras.datasets import imdb
(train_data, train_labels), (test_data, test_labels) = imdb.load_data(
num_words=10000)
imdb.load_data() : 함수는 IMDB 데이터셋을 로드하는 함수로, 이 함수는 훈련 데이터셋과 테스트 데이터셋을 각각 튜플로 반환합니다. 튜플의 첫 번째 원소는 데이터(data)이고, 두 번째 원소는 레이블(label)입니다.
num_words=10000 : 인자는 데이터셋에서 가장 자주 사용되는 단어 1만 개만 선택하겠다는 것을 의미
train_data.shape
train_data : shape을 알려주는것
max([max(sequence) for sequence in test_data[40:70]])
: 테스트 데이터셋에서 40번째부터 69번째까지의 샘플에 대해, 시퀀스(sequence) 중 가장 큰 정수값을 구하는 코드
word_index = imdb.get_word_index()
reverse_word_index = dict(
[(value, key) for (key, value) in word_index.items()])
decoded_review = " ".join(
[reverse_word_index.get(i - 3, "?") for i in train_data[0]])
word_index = imdb.get_word_index(): IMDB 데이터셋으로부터 단어와 해당 단어의 정수 인덱스를 가져옵니다. word_index는 딕셔너리 형태이며, key는 단어, value는 해당 단어의 정수 인덱스입니다.
reverse_word_index = dict([(value, key) for (key, value) in word_index.items()]): word_index의 key와 value를 뒤집은 딕셔너리 reverse_word_index를 생성합니다. 이를 통해, 정수 인덱스를 이용해 단어를 찾을 수 있게 됩니다.
decoded_review = " ".join([reverse_word_index.get(i - 3, "?") for i in train_data[0]]): 텍스트 데이터를 디코딩합니다. 이 코드에서는 첫 번째 훈련 데이터의 정수 시퀀스를 디코딩하는 것을 예시로 들고 있습니다. 정수 시퀀스는 train_data[0]에 저장되어 있습니다. reverse_word_index를 이용하여, 각 정수 인덱스를 해당하는 단어로 바꾸고, 이를 공백 문자열을 기준으로 이어붙입니다. 이 결과, decoded_review는 정수 시퀀스에 해당하는 텍스트 데이터가 됩니다. 여기서 get() 함수의 두 번째 인자인 ?는 만약 정수 인덱스가 reverse_word_index에 없을 경우 대신 사용할 값입니다. i - 3은 인덱스를 3씩 감소시켜주는 것으로, IMDB 데이터셋에서 정의한 규칙에 따라 특수 문자를 나타내는 0, 1, 2를 제외하기 위한 조치
import numpy as np
def vectorize_sequences(sequences, dimension=10000):
results = np.zeros((len(sequences), dimension))
for i, sequence in enumerate(sequences):
for j in sequence:
results[i, j] = 1.
return results
x_train = vectorize_sequences(train_data)
x_test = vectorize_sequences(test_data)
def vectorize_sequences(sequences, dimension=10000):: 정수 시퀀스를 입력으로 받아, 이를 고정된 크기의 벡터로 변환하는 함수입니다. dimension은 결과 벡터의 차원 수를 의미합니다. 기본값은 10000입니다.
results = np.zeros((len(sequences), dimension)): 결과를 저장할 2차원 배열 results를 생성합니다. len(sequences)는 입력 시퀀스의 개수를 나타내며, dimension은 결과 벡터의 차원 수입니다. 이 배열은 모든 값이 0인 배열로 초기화됩니다.
for i, sequence in enumerate(sequences):: 입력 시퀀스의 개수만큼 반복합니다. enumerate() 함수는 리스트나 배열의 값과 인덱스를 동시에 반환하는 함수입니다.
for j in sequence: results[i, j] = 1.: 시퀀스의 각 정수 인덱스 j에 대해, results 배열에서 i번째 행과 j번째 열에 해당하는 값에 1을 할당합니다. 이는 해당하는 단어가 시퀀스에 포함되었음을 의미합니다.
x_train = vectorize_sequences(train_data): 훈련 데이터를 벡터화합니다. train_data는 정수 시퀀스의 리스트이며, vectorize_sequences() 함수를 이용하여 벡터화된 훈련 데이터를 x_train에 할당합니다.
y_train = np.asarray(train_labels).astype("float32") # y: label 깂
y_test = np.asarray(test_labels).astype("float32")
np.asarray : p.asarray() 함수는 입력 데이터를 NumPy 배열로 변환하는 함수입니다. 이 함수는 파이썬 리스트, 튜플, 배열 등 다양한 객체를 입력으로 받아 해당 객체를 NumPy 배열로 변환합니다
model = keras.Sequential([
layers.Dense(16, activation="relu"),
layers.Dense(16, activation="relu"),
layers.Dense(1, activation="sigmoid")
첫 번째 층(layers.Dense(16, activation="relu"))은 16개의 뉴런을 가지며, 활성화 함수로 ReLU(Rectified Linear Unit) 함수를 사용합니다. 입력 데이터의 차원은 모델에 따라 자동으로 결정되므로, 이 층에서는 입력 데이터의 차원을 명시적으로 지정하지 않습니다.
두 번째 층(layers.Dense(16, activation="relu"))은 첫 번째 층과 동일한 구조를 가집니다. 이전 층에서 출력된 16개의 특성(feature)을 입력으로 받아 다시 16개의 특성을 출력합니다. 활성화 함수로는 여전히 ReLU 함수가 사용됩니다.
세 번째 층(layers.Dense(1, activation="sigmoid"))은 하나의 출력 뉴런을 가지며, 활성화 함수로 Sigmoid 함수를 사용합니다. Sigmoid 함수는 이진 분류 문제(binary classification)에서 사용하는 일반적인 활성화 함수입니다. 출력값이 0.5보다 크면 1, 작으면 0으로 분류합니다.
반면, 출력층에서는 활성화 함수를 목적에 맞게 선택하여 사용합니다. 예를 들어, 이진 분류 문제에서는 Sigmoid 함수를, 다중 분류 문제에서는 Softmax 함수를 사용합니다. Sigmoid 함수는 출력값을 [0, 1] 범위로 변환하며, 이진 분류 문제에서 출력값이 0.5보다 크면 1, 작으면 0으로 분류합니다. Softmax 함수는 출력값을 확률로 해석할 수 있도록 변환합니다.
model.compile(optimizer="rmsprop",
loss="binary_crossentropy",
metrics=["accuracy"])
optimizer: 최적화 알고리즘을 선택합니다. 여기에서는 RMSprop 알고리즘을 사용합니다.
loss: 손실 함수를 선택합니다. 이진 분류 문제에서는 binary_crossentropy를 사용합니다. 이 손실 함수는 실제값과 예측값 간의 차이를 계산하여 모델을 학습하는 데 사용됩니다.
metrics: 모델의 성능을 평가하는 지표를 선택합니다. 이진 분류 문제에서는 accuracy(정확도)를 사용합니다. 정확도는 전체 샘플 중 맞게 분류한 샘플의 비율을 의미합니다.
다중 분류 문제에서는 categorical_crossentropy 손실 함수를 사용하는 것이 일반적입니다.
x_val = x_train[:10000]
partial_x_train = x_train[10000:]
y_val = y_train[:10000]
partial_y_train = y_train[10000:]
history = model.fit(partial_x_train,
partial_y_train,
epochs=20,
batch_size=512,
validation_data=(x_val, y_val))
model.fit() 메서드는 다음과 같은 파라미터를 받습니다.
partial_x_train: 훈련 데이터셋의 입력값 중 검증 데이터를 제외한 부분입니다.
partial_y_train: 훈련 데이터셋의 출력값 중 검증 데이터를 제외한 부분입니다.
epochs: 훈련 과정에서 전체 데이터셋을 몇 번 반복할 것인지를 결정합니다.
batch_size: 한 번에 처리할 데이터의 개수를 결정합니다.
validation_data: 검증 데이터셋을 지정합니다.
- 'loss': 각 epoch마다 훈련 데이터셋에 대한 손실값을 저장한 리스트
- accuracy': 각 epoch마다 훈련 데이터셋에 대한 정확도를 저장한 리스트
- 'val_loss': 각 epoch마다 검증 데이터셋에 대한 손실값을 저장한 리스트
- 'val_accuracy': 각 epoch마다 검증 데이터셋에 대한 정확도를 저장한 리스트
history_dict.keys()
import matplotlib.pyplot as plt
history_dict = history.history
loss_values = history_dict["loss"]
val_loss_values = history_dict["val_loss"]
epochs = range(1, len(loss_values) + 1)
plt.plot(epochs, loss_values, "bo", label="Training loss")
plt.plot(epochs, val_loss_values, "b", label="Validation loss")
plt.title("Training and validation accuracy")
plt.xlabel("Epochs")
plt.ylabel("accuracy")
plt.legend()
plt.show()

plt.clf()
acc = history_dict["accuracy"]
val_acc = history_dict["val_accuracy"]
plt.plot(epochs, acc, "bo", label="Training acc")
plt.plot(epochs, val_acc, "b", label="Validation acc") #blue -> b
plt.title("Training and validation accuracy")
plt.xlabel("Epochs")
plt.ylabel("Accuracy")
plt.legend()
plt.show()
plt.clf(): 현재 figure에 그려진 모든 그래프를 지우고 새로운 그래프를 그리기 위해 초기화합니다.
acc = history_dict["accuracy"]: 모델이 학습한 학습 데이터에 대한 정확도 값을 acc 변수에 저장합니다.
plt.plot(epochs, acc, "bo", label="Training acc"): epochs와 acc 값을 이용해 학습 데이터에 대한 정확도 그래프를 그립니다. 'bo'는 파란색 동그라미를 의미합니다. label="Training acc"는 이 그래프가 학습 데이터에 대한 정확도 그래프임을 나타내는 레이블(label)입니다.

- result : 에폭이 커질수록 , train의 loss는 줄어들고 accuracy는 커지는 것을 볼 수 있다.
하지만 , val의 loss는 오히려 커지고 , val의 accuracy는 작아지는 것을 볼 수 있다. 이로써 최적값을 찾아야한다.
model = keras.Sequential([
layers.Dense(16, activation="relu"),
layers.Dense(16, activation="relu"),
layers.Dense(1, activation="sigmoid")
])
model.compile(optimizer="rmsprop",
loss="binary_crossentropy", #cross-emtropy -
metrics=["accuracy"])
model.fit(x_train, y_train, epochs=4, batch_size=512)
results = model.evaluate(x_test, y_test)
model = Sequential()
model.add(Dense(16, activation='relu', input_shape=(10000,)))
이렇게 해서 , layer를 추가할 수도 있다 -> add 메소드 사용
model.predict(x_test)
뉴스 기사 분류: 다중 분류 문제
#1
def to_one_hot(labels, dimension=46):
results = np.zeros((len(labels), dimension))
for i, label in enumerate(labels):
results[i, label] = 1.
return results
y_train = to_one_hot(train_labels)
y_test = to_one_hot(test_labels)
enumerate(labels)는 labels라는 iterable 객체를 받아 해당 객체의 각 원소를 순회하면서 해당 원소의 인덱스와 값을 동시에 반환하는 iterator를 생성
#2
from tensorflow.keras.utils import to_categorical
y_train = to_categorical(train_labels)
y_test = to_categorical(test_labels)
import copy
test_labels_copy = copy.copy(test_labels)
np.random.shuffle(test_labels_copy)
hits_array = np.array(test_labels) == np.array(test_labels_copy)
hits_array.mean()
test_labels와 동일한 shape을 가지는 test_labels_copy 배열을 생성하고, 이를 무작위로 섞은 뒤 test_labels와의 일치 여부를 판단하여 정확도를 계산하는 과정
copy 모듈에서 copy 함수를 import하고, test_labels를 복사하여 test_labels_copy를 생성합니다.
np.random.shuffle 함수를 사용하여 test_labels_copy 배열의 원소들을 무작위로 섞습니다
np.argmax(predictions[5])
mean = train_data.mean(axis=0)
train_data -= mean
std = train_data.std(axis=0)
train_data /= std
test_data -= mean
test_data /= std
train_data 배열에서 mean 값을 뺀 후, train_data.std(axis=0)를 통해 각 픽셀의 표준편차를 계산
train_data 배열에서 mean 값을 뺀 후, std 값으로 나누어주는 과정을 거쳐, 훈련 데이터와 테스트 데이터를 모두 정규화(normalize)합니다.
result : 정규화된 데이터를 모델의 입력값으로 사용하면, 모델이 더욱 빠르고 정확하게 학습할 수 있습니다.
k = 4
num_val_samples = len(train_data) // k
num_epochs = 100
all_scores = []
for i in range(k):
print(f"#{i}번째 폴드 처리중")
val_data = train_data[i * num_val_samples: (i + 1) * num_val_samples]
val_targets = train_targets[i * num_val_samples: (i + 1) * num_val_samples]
partial_train_data = np.concatenate(
[train_data[:i * num_val_samples],
train_data[(i + 1) * num_val_samples:]],
axis=0)
partial_train_targets = np.concatenate(
[train_targets[:i * num_val_samples],
train_targets[(i + 1) * num_val_samples:]],
axis=0)
model = build_model()
model.fit(partial_train_data, partial_train_targets,
epochs=num_epochs, batch_size=16, verbose=0)
val_mse, val_mae = model.evaluate(val_data, val_targets, verbose=0)
all_scores.append(val_mae)
k 값이 4로 설정되어 있으므로, 전체 학습 데이터셋인 train_data와 train_targets를 4개의 폴드(fold)로 나누어서 교차 검증을 수행
all_scores 리스트에는 모든 폴드에서 검증 세트의 평균 절대 오차(MAE)가 저장
plt.plot(range(1, len(average_mae_history) + 1), average_mae_history)
plt.xlabel("Epochs")
plt.ylabel("Validation MAE")
plt.show()