mnist = tf.keras.datasets.fashion_mnist
(training_images, training_labels), (test_images, test_labels) = mnist.load_data()
training_images /= 255.0
test_images /= 255.0
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(128, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer="adam", loss="sparse_categorical_crossentropy", metrics=["accuracy"])
model.fit(training_images, training_labels, epochs=5)
test_loss = model.evaluate(test_images, test_labels)
코드 출처: C1_W3_Lab_1_improving_accuracy_using_convolutions.ipynb
텐서플로우 자격증을 준비하기 위해 코세라 강의를 듣고 실습하던 중 다음과 같은 오류가 떴다.
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-5-a45d78a6ac67> in <module>()
1 mnist = tf.keras.datasets.fashion_mnist
2 (training_images, training_labels), (test_images, test_labels) = mnist.load_data()
----> 3 training_images /= 255.0
4 test_images /= 255.0
5 model = tf.keras.models.Sequential([
ValueError: output array is read-only
training_images = training_images / 255.0랑 training_images /= 255.0는 분명 같은 거라고 배웠는데 왜 오류가 날까? 에러 내용을 구글링하니 나와 같은 고민을 하는 사람을 바로 찾을 수 있었다.
읽기 귀찮은 사람들을 위해 간단히 말하자면 numpy array는 read-only다. 그 말은 즉슨 immutable한, 변경할 수 없는 객체라는 소리다. 그런데 /= 연산은 in-place연산이기 때문에 무조건 mutable한 객체에 대해서만 동작한다. 따라서 immutable한 객체는 아예 새로 할당을 해줘야 한다. x /= y가 아닌 x = x / y로 말이다.
결론: numpy array는 할당 연산자 사용 시 풀어서 써줘야 한다!
엥 그런데 에러가 뜨지 않고 정상적으로 잘 작동하는 경우도 있다.
import numpy as np
import random
from tensorflow.keras.preprocessing.image import img_to_array, load_img
# Let's define a new Model that will take an image as input, and will output
# intermediate representations for all layers in the previous model after
# the first.
successive_outputs = [layer.output for layer in model.layers[1:]]
#visualization_model = Model(img_input, successive_outputs)
visualization_model = tf.keras.models.Model(inputs = model.input, outputs = successive_outputs)
# Let's prepare a random input image from the training set.
horse_img_files = [os.path.join(train_horse_dir, f) for f in train_horse_names]
human_img_files = [os.path.join(train_human_dir, f) for f in train_human_names]
img_path = random.choice(horse_img_files + human_img_files)
img = load_img(img_path, target_size=(300, 300)) # this is a PIL image
x = img_to_array(img) # Numpy array with shape (150, 150, 3)
x = x.reshape((1,) + x.shape) # Numpy array with shape (1, 150, 150, 3)
# Rescale by 1/255
x /= 255
# Let's run our image through our network, thus obtaining all
# intermediate representations for this image.
successive_feature_maps = visualization_model.predict(x)
# These are the names of the layers, so can have them as part of our plot
layer_names = [layer.name for layer in model.layers[1:]]
# Now let's display our representations
for layer_name, feature_map in zip(layer_names, successive_feature_maps):
if len(feature_map.shape) == 4:
# Just do this for the conv / maxpool layers, not the fully-connected layers
n_features = feature_map.shape[-1] # number of features in feature map
# The feature map has shape (1, size, size, n_features)
size = feature_map.shape[1]
# We will tile our images in this matrix
display_grid = np.zeros((size, size * n_features))
for i in range(n_features):
# Postprocess the feature to make it visually palatable
x = feature_map[0, :, :, i]
x -= x.mean()
x /= x.std()
x *= 64
x += 128
x = np.clip(x, 0, 255).astype('uint8')
# We'll tile each filter into this big horizontal grid
display_grid[:, i * size : (i + 1) * size] = x
# Display the grid
scale = 20. / n_features
plt.figure(figsize=(scale * n_features, scale))
plt.title(layer_name)
plt.grid(False)
plt.imshow(display_grid, aspect='auto', cmap='viridis')
코드 출처: C1_W4_Lab_1_image_generator_no_validation.ipynb
코드 다 볼 필요 없고 21번째 줄을 보면 x가 numpy array인데 코드 실행 시 전혀 문제가 생기지 않았다. 뭐지.....? 42, 43, 44, 45번째 줄도 마찬가지다.
결론: numpy array에서 할당 연산자 사용이 안되면 풀어서 써주자!
'TIL' 카테고리의 다른 글
HDFS 휴지통 복구, HDFS 파일 복구, HDFS 폴더 복구 (0) | 2022.07.21 |
---|---|
Conv1D, Conv2D, Conv3D 차이 (0) | 2021.11.22 |
include_top의 의미 (0) | 2021.11.17 |
입력 이미지(input image)를 정규화(normalize)하는 이유 (0) | 2021.11.11 |
sigmoid보다 tanh를 쓰는 이유 (0) | 2021.08.19 |