如何在 Tensorflow 中使用 CNN 提高我的测试准确性

数据挖掘 机器学习 Python 神经网络 深度学习 张量流
2021-10-06 01:06:00

我正在从事 Kaggle 的 Dogs vs. Cats Redux: Kernels Edition 项目,我是这个领域的新手。到目前为止,我无法将我的测试率提高到 %50 以上。我想知道我能做些什么来提高我的测试准确性,或者我的代码有什么问题吗?顺便说一句,下面的代码是使用 tflearn 库,但我也直接尝试使用 Tensorflow,但我仍然无法超过 %50。

from __future__ import division, print_function, absolute_import

import csv

from skimage import color, io
from scipy.misc import imresize
import numpy as np
from sklearn.model_selection import train_test_split
import os
from glob import glob
import tflearn
from tflearn.data_utils import shuffle, to_categorical
from tflearn.layers.core import input_data, dropout, fully_connected
from tflearn.layers.conv import conv_2d, max_pool_2d
from tflearn.layers.estimator import regression
from tflearn.data_preprocessing import ImagePreprocessing
from tflearn.data_augmentation import ImageAugmentation
from tflearn.metrics import Accuracy
###################################
### Import picture files
###################################

files_path = 'dataset/train'
cat_files_path = os.path.join(files_path, 'cat*.jpg')
dog_files_path = os.path.join(files_path, 'dog*.jpg')
test_files_path = os.path.join('dataset/test1', '*.jpg')

cat_files = sorted(glob(cat_files_path))
dog_files = sorted(glob(dog_files_path))
test_files = sorted(glob(test_files_path))

n_files = len(cat_files) + len(dog_files)
test_n = len(test_files)
print(test_n)
size_image = 64
allX = np.zeros((n_files, size_image, size_image,3), dtype='float64')
ally = np.zeros(n_files)
testX = np.zeros((test_n, size_image, size_image, 3), dtype='float64')
count = 0
for f in test_files:
    try:
        img = io.imread(f)
        new_img = imresize(img, (size_image,size_image,3))
        testX[count] = np.array(new_img)
        count += 1
    except:
        continue
count = 0
for f in cat_files:
    try:
        img = io.imread(f)
        new_img = imresize(img, (size_image,size_image,3))
        allX[count] = np.array(new_img)
        ally[count] = 0
        count += 1
    except:
        continue
for f in dog_files:
    try:
        img = io.imread(f)
        new_img = imresize(img, (size_image,size_image,3))
        allX[count] = np.array(new_img)
        ally[count] = 1
        count += 1
    except:
        continue

###################################
# Prepare train & test samples
###################################

# test-train split
X, X_test, Y, Y_test = train_test_split(allX,ally,test_size=0.1, random_state=42)

#encode the Ys
Y = to_categorical(Y,2)
Y_test = to_categorical(Y_test, 2)

###################################
# Image transformations
###################################

# normalisation of images
img_prep = ImagePreprocessing()
img_prep.add_featurewise_zero_center()
img_prep.add_featurewise_stdnorm()

# Create extra synthetic training data by flipping & rotating images
img_aug = ImageAugmentation()
img_aug.add_random_flip_leftright()
img_aug.add_random_rotation(max_angle=25.)

###################################
# Define network architecture
###################################

# Input is a 32x32 image with 3 color channels (red, green and blue)
network = input_data(shape=[None, 64, 64, 3],
                     data_preprocessing=img_prep,
                     data_augmentation=img_aug)

# 1: Convolution layer with 32 filters, each 3x3x3
conv_1 = conv_2d(network, 32, [3,3], activation='relu', name='conv_1')

# 2: Max pooling layer
network = max_pool_2d(conv_1, [3,3])

# 3: Convolution layer with 64 filters
conv_2 = conv_2d(network, 64, [3,3], activation='relu', name='conv_2')

# 2: Max pooling layer
network = max_pool_2d(conv_2, [3,3])

# 4: Convolution layer with 64 filters
conv_3 = conv_2d(network, 32, [3,3], activation='relu', name='conv_3')

# 5: Max pooling layer
network = max_pool_2d(conv_3, [3,3])

# 5: Convolution layer with 64 filters
conv_4 = conv_2d(network, 64, [3,3], activation='relu', name='conv_4')

# 6: Max pooling layer
network = max_pool_2d(conv_4, [3,3])

# 7: Convolution layer with 64 filters
conv_5 = conv_2d(network, 32, [3,3], activation='relu', name='conv_5')

# 8: Max pooling layer
network = max_pool_2d(conv_5, [3,3])

# 9: Convolution layer with 64 filters
conv_6 = conv_2d(network, 64, [3,3], activation='relu', name='conv_6')

# 10: Max pooling layer
network = max_pool_2d(conv_6, [3,3])

# 11: Fully-connected 512 node layer
network = fully_connected(network, 1024, activation='relu')

# 12: Dropout layer to combat overfitting
network = dropout(network, 0.8)

# 13: Fully-connected layer with two outputs
network = fully_connected(network, 2, activation='softmax')

# Configure how the network will be trained
acc = Accuracy(name="Accuracy")
network = regression(network, optimizer='adam',
                     loss='categorical_crossentropy',
                     learning_rate=0.0005, metric=acc)

# Wrap the network in a model object
model = tflearn.DNN(network, checkpoint_path='model_cat_dog_6.tflearn', max_checkpoints = 3,
                    tensorboard_verbose = 3, tensorboard_dir='tmp/tflearn_logs/')

model.fit(X, Y, validation_set=(X_test, Y_test), batch_size=500,
      n_epoch=10, run_id='cat_dog_model', show_metric=True)
model.save('cat_dog_model_final.tflearn')
# choose images & plot the first one
result = []
logloss = 0

with open('deneme.csv','wb') as cs:
    writer = csv.writer(cs, delimiter=',',quoting=csv.QUOTE_NONE)
    for i in range(0, len(testX)):
        im = [testX[i]]
        a = model.predict(im)
        if a[0][0]<a[0][1]:
            writer.writerow([str(i+1), 1])
        else:
            writer.writerow([str(i + 1), 0])
2个回答

50% 并不比随机的好。你的训练成绩是多少?

对于 64 x 64 图像,您有 6 个大小为 3x3 的最大池化层:

  • 第 1 次之后:尺寸为 21 x 21 x 32
  • 第二次之后:尺寸为 7 x 7 x 64
  • 第三次之后:尺寸为 2 x 2 x 32
  • 第 4 次之后:大小为 1 x 1 x 64(?)

之后还有两个 conv/pool 层。池化太多了。

取而代之的是,尝试 3 个 5x5 卷积层,2x2 块中的最大池,然后在全连接层之前退出。每次有 [2,2] max pool 时,conv 层的深度就会加倍。

# Input is a 64x64 image with 3 color channels (red, green and blue)
network = input_data(shape=[None, 64, 64, 3],
                     data_preprocessing=img_prep,
                     data_augmentation=img_aug)

# 1: Convolution layer with 32 filters, each 5x5
conv_1 = conv_2d(network, 32, [5,5], activation='relu', name='conv_1')
# 2: Max pooling layer, out size is 32x32x32
network = max_pool_2d(conv_1, [2,2])
# 3: Convolution layer with 64 filters
conv_2 = conv_2d(network, 64, [5,5], activation='relu', name='conv_2')
# 2: Max pooling layer, out size is 16x16x64
network = max_pool_2d(conv_2, [2,2])
# 4: Convolution layer with 128 filters
conv_3 = conv_2d(network, 128, [5,5], activation='relu', name='conv_3')
# 5: Max pooling layer, out size is 8x8x128
network = max_pool_2d(conv_3, [2,2])
# 12: Dropout layer to combat overfitting
network = dropout(network, 0.5)
# 11: Fully-connected 1024 node layer
network = fully_connected(network, 1024, activation='relu')
# 13: Fully-connected layer with two outputs
network = fully_connected(network, 2, activation='softmax')

最后,如果 tflearn 不自动执行此操作,您可能必须在测试之前关闭dropout。在 vanilla Tensorflow 中,这是通过使用占位符来表示丢失保持概率并在测试时为其提供 1.0 来完成的。

我不熟悉 tensorflow,但我可以告诉你我从你的问题中所知道的。首先,问题很可能是你的训练方式,而不是你的模型本身。

您可能有两个可能的问题:

1 - 您对训练数据过度拟合

2 - 你没有足够的训练你的模型

我建议您要么使用预训练模型并对其进行微调以获得更好的结果,要么在返回猫狗之前使用更多数据训练现有模型。此外,它有助于增强您的数据,以便您的网络有更多的图像可以训练。还有一些有用的方法是使用 dropout、batchnorm 和正则化(如果您过度拟合,则更有帮助)。如果这些都不起作用,那么您可能有一个有问题的模型并且可能需要更改它。

我真的希望这对您将来有所帮助。

(如果您是 ML 的初学者,我建议您从 Fast.AI 的机器学习 MOOC 开始,并使用他们使用的库 keras 和 theano 进行学习。虽然它们看起来简单得多,但它们绝对足以实现在许多事情上取得了令人难以置信的结果。)