简体   繁体   English

为什么我的keras模型总是预测相同的结果?

[英]Why is my keras model always predicting the same result?

I realize this question has been asked before, but none of those solutions seem to be relevant to my problem. 我知道以前曾问过这个问题,但是这些解决方案似乎都与我的问题无关。

I am trying to implement a basic binary classification algorithm using logistic regression to identify whether an image is a cat or a dog. 我正在尝试使用逻辑回归来实现基本的二进制分类算法,以识别图像是猫还是狗。

I believe I am structuring the data properly, I am adding a flatten layer before the initial dense layer which I believe is accepting the proper shape, then I run it through two more dense layers with the final one having only 2 outputs (which as I understand it, is the way it should be for a binary classification such as this). 我相信我正在正确地构造数据,我在初始密集层之前添加了一个平坦的层,我认为该层接受了正确的形状,然后我将它遍历了另外两个密集层,最后一层只有2个输出(我理解它,这就是二进制分类之类的方式。

Please take a look at my code and advise what I can do better to: 请查看我的代码,并提出我可以做的更好的事情:

1.) Make the prediction output vary (not always choose one or the other) 1.)使预测输出变化(并非总是选择其中一个)
2.) Make my accuracy and loss vary after the second epoch. 2.)在第二个时期之后,使我的准确性和损失有所不同。

I have tried: - varying the number of dense layers and their parameters 我尝试过:-更改密集层的数量及其参数
- changing the size of my dataset (hence the count variable when processing files) -更改数据集的大小(因此在处理文件时使用count变量)
- changing the number of epochs -更改时代数
- changing the kind model from sgd to adam -将种类模型从sgd更改为adam

dataset initialization 数据集初始化

import numpy as np
import cv2
import os
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
import random
import keras

dataDir = '/content/gdrive/My Drive/AI'
categories = ['dog', 'cat']

x, y = [], []

imgSize = 100

for cat in categories:
  folderPath = os.path.join(dataDir, cat) # path to the respective folders
  classNum = categories.index(cat)        # sets classification number (0 = dog, 1 = cat)
  count = 0                               # used for limiting the number of images to test
  for file in os.listdir(folderPath):
    count = count + 1                     
    try:
      # open image and convert to grayscale
      img = cv2.imread(os.path.join(folderPath, file), cv2.IMREAD_GRAYSCALE)

      # resize to a square of predefined dimensions
      newImg = cv2.resize(img, (imgSize, imgSize))

      # add images to x and labels to y
      x.append(newImg)
      y.append(classNum)
      if count >= 100:
        break;

    # some images may be broken
    except Exception as e:
      pass

# y array to categorical
y = keras.utils.to_categorical(y, num_classes=2)

# shuffle data to increase training
random.shuffle(x)
random.shuffle(y)

x = np.array(x).reshape(-1, imgSize, imgSize, 1)
y = np.array(y)

# split data into default sized groups (75% train, 25% test)
xTrain, xTest, yTrain, yTest = train_test_split(x, y, test_size=0.25)

# display bar chart
objects = ('xTrain', 'xTest', 'yTrain', 'yTest')
y_pos = np.arange(len(objects))
maxItems = int((len(x) / 2 ) + 1)
arrays = [len(xTrain), len(xTest), len(yTrain), len(yTest)]

plt.bar(y_pos, arrays, align='center')
plt.xticks(y_pos, objects)
plt.ylabel('# of items')
plt.title('Items in Arrays')

plt.show()

model setup 模型设定

from keras.layers import Dense, Flatten
from keras.models import Sequential

shape = xTest.shape
model = Sequential([Flatten(),
                   Dense(100, activation = 'relu', input_shape = shape),
                   Dense(50, activation = 'relu'),
                   Dense(2, activation = 'softmax')])

model.compile(loss = keras.losses.binary_crossentropy,
             optimizer = keras.optimizers.sgd(),
             metrics = ['accuracy'])

model.fit(xTrain, yTrain,
         epochs=3,
         verbose=1,
         validation_data=(xTest, yTest))

model.summary()

which outputs: 输出:

Train on 150 samples, validate on 50 samples
Epoch 1/3
150/150 [==============================] - 1s 6ms/step - loss: 7.3177 - acc: 0.5400 - val_loss: 1.9236 - val_acc: 0.8800
Epoch 2/3
150/150 [==============================] - 0s 424us/step - loss: 3.4198 - acc: 0.7867 - val_loss: 1.9236 - val_acc: 0.8800
Epoch 3/3
150/150 [==============================] - 0s 430us/step - loss: 3.4198 - acc: 0.7867 - val_loss: 1.9236 - val_acc: 0.8800
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
flatten_13 (Flatten)         (None, 10000)             0         
_________________________________________________________________
dense_45 (Dense)             (None, 100)               1000100   
_________________________________________________________________
dense_46 (Dense)             (None, 50)                5050      
_________________________________________________________________
dense_47 (Dense)             (None, 2)                 102       
=================================================================
Total params: 1,005,252
Trainable params: 1,005,252
Non-trainable params: 0

prediction 预测

y_pred = model.predict(xTest)

for y in y_pred:
  print(y)

which outputs: 输出:

[1. 0.]
[1. 0.]
[1. 0.]
.
.
.
[1. 0.]

There are few ways to skin this cat...ha puns. 剥皮这只猫的方法很少...双关语。 I don't know if yours is working though. 我不知道您的工作是否正常。 So assuming your data and labelings are correct then it's your data collection and model construction that I think are the problems. 因此,假设您的数据和标签正确,那么我认为是您的数据收集和模型构建是问题所在。

First, I don't think you have enough data. 首先,我认为您没有足够的数据。 Most of these binary classification models are built on >1000 pictures. 这些二进制分类模型中的大多数都是基于> 1000张图片构建的。 You're working with a lot less. 您的工作量大大减少了。 Second, you're only doing 3 epochs, that's not enough at all. 其次,您只需要执行3个纪元,那还远远不够。 For the amount of pictures you'd need, I'd suggest at least 50 epochs. 对于您需要的图片数量,我建议至少50个纪元。 But that's trial and error to determine the right number and if you're overfitting. 但这是反复试验,以确定合适的数字以及您是否过拟合。

This is what I'd use to construct a model for binary classification. 这就是我用来构建二进制分类模型的方法。

from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import train_test_split
from keras.models import Sequential
from keras.layers import Activation
from keras.optimizers import SGD
from keras.layers import Dense
from keras.utils import np_utils
import numpy as np
import cv2


data = []
labels = []
imageSize = 32
# Do whatever you gotta do to create a folder of flatten/resized images
# and another labels list with indexes that match the index of pitcure
for image in folder:
    imagePath = 'path/to/image/'
    imageLabel = 'whatever_label'
    image = cv2.imread(imagePath)
    features = cv2.resize(image, imageSize).flatten(image)
    data.append(features)
    labels.append(imageLabel)

# Encode the labels
labelEncoder = LabelEncoder()
labels = labelEncoder.fit_transforma(labels)

# Scale the image to [0, 1]
data = np.array(data) / 255.0
# Generate labels as [0, 1] instead of ['dog', 'cat']
labels = np_utils.to_categorical(labels, 2)

# Split data
(trainData, testData, trainLabels, testLabels) = train_test_split(data, labels, test_size = 0.25, random_state = 42)

# Construct Model
model = Sequential()
model.add(Dense(768, input_dim = imageSize * imageSize * 3, init = 'uniform', activation = 'relu'))
model.add(Dense(384, activation = 'relu', kernel_initializer = 'uniform'))
model.add(Dense(2))
model.add(Activation('softmax'))

# Compile
sgd = SGD(lr=0.01)
model.compile(loss = 'binary_crossentropy', optimizer = sgd, metrics = ['accuracy'])
model.fit(trainData, trainLabels, epochs = 50, batch_size = 128, verbose = 1)

# Determine Accuracy and loss
(loss, accuracy) = model.evaluate(testData, testLabels, batch_size = 128, verbose = 1)
print('[INFO] loss={:.4f}, accuracy: {:.4f}%'.format(loss, accuracy * 100))

Hope that helps! 希望有帮助!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM