Почему моя модель keras всегда предсказывает один и тот же результат? - PullRequest
0 голосов
/ 13 апреля 2019

Я понимаю, что этот вопрос задавался ранее, но ни одно из этих решений, похоже, не относится к моей проблеме.

Я пытаюсь реализовать базовый алгоритм двоичной классификации, используя логистическую регрессию, чтобы определить, является ли изображение кошкой или собакой.

Я полагаю, что я правильно структурирую данные, я добавляю плоский слой перед начальным плотным слоем, который, как я полагаю, принимает правильную форму, затем я пропускаю его через два более плотных слоя, причем последний имеет только 2 выхода ( что, как я понимаю, так и должно быть для бинарной классификации, такой как эта).

Пожалуйста, посмотрите на мой код и посоветуйте, что я могу сделать лучше:

1.) Изменение выходных данных прогноза (не всегда выбирайте одно или другое)
2.) Меняйте мою точность и потери после второй эпохи.

Я пытался: - варьирование количества плотных слоев и их параметров
- изменение размера моего набора данных (отсюда и переменная count при обработке файлов)
- изменение количества эпох
- изменить тип модели с sgd на adam

инициализация набора данных

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()

настройка модели

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()

который выводит:

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

предсказание

y_pred = model.predict(xTest)

for y in y_pred:
  print(y)

который выводит:

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

1 Ответ

1 голос
/ 13 апреля 2019

Есть несколько способов снять шкуру с этой кошки ... ха.Я не знаю, работает ли ваш, хотя.Таким образом, если предположить, что ваши данные и метки верны, то, по-моему, проблемы - это сбор данных и построение модели.

Во-первых, я не думаю, что у вас достаточно данных.Большинство из этих моделей бинарной классификации построены на> 1000 картин.Ты работаешь намного меньше.Во-вторых, вы делаете только 3 эпохи, этого недостаточно.Для того количества фотографий, которое вам понадобится, я бы предложил как минимум 50 эпох.Но это метод проб и ошибок, чтобы определить правильное число, и если вы переоснащаете.

Это то, что я бы использовал для построения модели для двоичной классификации.

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))

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...