CNN 与 Keras 的简单二进制分类,但只有 50% 的准确率
Simple binary classification by CNN with Keras, But got only 50% acc
今天我尝试使用 fit_generator 函数对普通黑白图像进行二进制分类,但它只给我 50% 的准确率
这只是我的编码练习,但我认为准确率应该达到 100%。所以我很好奇我的错误是什么。
我在 Google-colaboratory 中完成所有代码。
这是我的代码。
设置
import numpy as np
import random
from matplotlib import pyplot as plt
img_height = 150
img_width = 150
batch_size = 8
class MyDataset(object):
def __init__(self):
placeholder = 0
def generator(self):
is_black = True
X, y = [], []
while True:
if is_black:
img = np.full((img_height, img_width, 3), 255)
else:
img = np.zeros((img_height, img_width, 3))
img = img / 255.
X.append(img)
y.append(is_black)
is_black = not is_black
if len(X) >= batch_size:
c = list(zip(X, y))
random.shuffle(c)
X, y = zip(*c)
yield np.asarray(X, dtype=np.float32), np.asarray(y, dtype=np.float32)
X, y = [], []
dataset = MyDataset()
sample_gen = dataset.generator()
可视化数据
Example of inputs for model
X, y = next(sample_gen)
label_dict = {0:'black', 1:'white'}
sample_size = len(X)
fig = plt.figure(figsize=(16, 8))
for sample in range(sample_size):
img = X[sample]
lbl = label_dict[y[sample]]
fig.add_subplot(2, sample_size//2, sample + 1)
f = plt.imshow(img)
f.axes.get_xaxis().set_visible(False)
f.axes.get_yaxis().set_visible(False)
plt.title(lbl)
plt.show()
创建模型
我创建了一个小尺寸模型。它只有9个参数。
import tensorflow as tf
model = tf.keras.Sequential()
model.add(tf.keras.layers.Conv2D(filters=1, kernel_size=(1,1), padding='same',
activation='relu', input_shape=(img_height, img_width, 3)))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(img_height//2,img_height//2)))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(1, activation='softmax'))
model.summary()
训练模型
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
model.fit_generator(
sample_gen,
steps_per_epoch = 100//batch_size ,
epochs=300)
结果
经过 200 多个 epoch 后,准确率仍然是 0.5。
Epoch 218/300
12/12 [==============================] - 0s 8ms/step - loss: 7.9712 - acc: 0.5000
Epoch 219/300
12/12 [==============================] - 0s 8ms/step - loss: 7.9712 - acc: 0.5000
Epoch 220/300
12/12 [==============================] - 0s 8ms/step - loss: 7.9712 - acc: 0.5000
Epoch 221/300
12/12 [==============================] - 0s 9ms/step - loss: 7.9712 - acc: 0.5000
Epoch 222/300
12/12 [==============================] - 0s 8ms/step - loss: 7.9712 - acc: 0.5000
我已经学习了一些关于 CNN 的知识,我是 Keras 的初学者。
问题出在模型定义的末尾,具体如下:
model.add(tf.keras.layers.Dense(1, activation='softmax'))
根据定义,通过应用 softmax,您可以强制其输出总和为 1。单个值如何符合的唯一方法是成为 1 本身。因此,不会传播任何信息。
要修复它,请将 softmax 转换为 logistic sigmoid,例如:
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))
这样,您还可以将模型的输出解释为数据来自 class 1
.
的后验概率
今天我尝试使用 fit_generator 函数对普通黑白图像进行二进制分类,但它只给我 50% 的准确率
这只是我的编码练习,但我认为准确率应该达到 100%。所以我很好奇我的错误是什么。
我在 Google-colaboratory 中完成所有代码。
这是我的代码。
设置
import numpy as np
import random
from matplotlib import pyplot as plt
img_height = 150
img_width = 150
batch_size = 8
class MyDataset(object):
def __init__(self):
placeholder = 0
def generator(self):
is_black = True
X, y = [], []
while True:
if is_black:
img = np.full((img_height, img_width, 3), 255)
else:
img = np.zeros((img_height, img_width, 3))
img = img / 255.
X.append(img)
y.append(is_black)
is_black = not is_black
if len(X) >= batch_size:
c = list(zip(X, y))
random.shuffle(c)
X, y = zip(*c)
yield np.asarray(X, dtype=np.float32), np.asarray(y, dtype=np.float32)
X, y = [], []
dataset = MyDataset()
sample_gen = dataset.generator()
可视化数据
Example of inputs for model
X, y = next(sample_gen)
label_dict = {0:'black', 1:'white'}
sample_size = len(X)
fig = plt.figure(figsize=(16, 8))
for sample in range(sample_size):
img = X[sample]
lbl = label_dict[y[sample]]
fig.add_subplot(2, sample_size//2, sample + 1)
f = plt.imshow(img)
f.axes.get_xaxis().set_visible(False)
f.axes.get_yaxis().set_visible(False)
plt.title(lbl)
plt.show()
创建模型
我创建了一个小尺寸模型。它只有9个参数。
import tensorflow as tf
model = tf.keras.Sequential()
model.add(tf.keras.layers.Conv2D(filters=1, kernel_size=(1,1), padding='same',
activation='relu', input_shape=(img_height, img_width, 3)))
model.add(tf.keras.layers.MaxPooling2D(pool_size=(img_height//2,img_height//2)))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(1, activation='softmax'))
model.summary()
训练模型
model.compile(optimizer='rmsprop',
loss='binary_crossentropy',
metrics=['accuracy'])
model.fit_generator(
sample_gen,
steps_per_epoch = 100//batch_size ,
epochs=300)
结果
经过 200 多个 epoch 后,准确率仍然是 0.5。
Epoch 218/300
12/12 [==============================] - 0s 8ms/step - loss: 7.9712 - acc: 0.5000
Epoch 219/300
12/12 [==============================] - 0s 8ms/step - loss: 7.9712 - acc: 0.5000
Epoch 220/300
12/12 [==============================] - 0s 8ms/step - loss: 7.9712 - acc: 0.5000
Epoch 221/300
12/12 [==============================] - 0s 9ms/step - loss: 7.9712 - acc: 0.5000
Epoch 222/300
12/12 [==============================] - 0s 8ms/step - loss: 7.9712 - acc: 0.5000
我已经学习了一些关于 CNN 的知识,我是 Keras 的初学者。
问题出在模型定义的末尾,具体如下:
model.add(tf.keras.layers.Dense(1, activation='softmax'))
根据定义,通过应用 softmax,您可以强制其输出总和为 1。单个值如何符合的唯一方法是成为 1 本身。因此,不会传播任何信息。
要修复它,请将 softmax 转换为 logistic sigmoid,例如:
model.add(tf.keras.layers.Dense(1, activation='sigmoid'))
这样,您还可以将模型的输出解释为数据来自 class 1
.