2017-06-02 109 views
0

我已经训练了CNN神经网络python与800个样本,并在60测试。 预测它给我的相同的结果keras CNN相同的输出

#main file - run this to train the network 

import numpy as np 
from keras.datasets import cifar10 
from datasetFetch import DataFetch 
from keras.models import Sequential 
from keras.layers import Dense 
from keras.layers import Dropout 
from keras.layers import Flatten 
from keras.constraints import maxnorm 
from keras.optimizers import SGD 
from keras.layers.convolutional import Conv2D 
from keras.layers.convolutional import MaxPooling2D 
from keras.utils import np_utils 
from keras import backend as K 
K.set_image_dim_ordering('th') 
import simplejson 
from matplotlib import pyplot 
from scipy.misc import toimage 
# load data 
#(X_train, y_train), (X_test, y_test) = cifar10.load_data() 
# create a grid of 3x3 images 
#for i in range(0, 9): 
# pyplot.subplot(3,3,1 + i) 
# pyplot.imshow(toimage(X_train[i])) 
# show the plot 
#pyplot.show() 

#init data 
CONST_PHOTOS = 400 # number of photos of each type 
y_train = [] 

#train data 
data = DataFetch('orange',CONST_PHOTOS) 
data1 = data.openPictures() 
data = DataFetch('apple', CONST_PHOTOS) 
data.removeErrorImages() 
data2 = data.openPictures() 

#test data 
tdata = DataFetch('test-orange',30) 
tdata1 = tdata.openPictures() 
tdata = DataFetch('test-apple',30) 
tdata2 = tdata.openPictures() 

#add togheter data 
X_train = data.connectData(data1,data2,'train') 
y_train = data.getYtrain('train') 
X_test = tdata.connectData(tdata1,tdata2,'test') 
y_test = tdata.getYtrain('test') 

# fix random seed for reproducibility 
seed = 7 
np.random.seed(seed) 

# normalize inputs from 0-255 to 0.0-1.0 
X_train = X_train.astype('float32') 
X_test = X_test.astype('float32') 
X_train = X_train/255.0 
X_test = X_test/255.0 

#one hot encode outputs 
y_train = np_utils.to_categorical(y_train) 
y_test = np_utils.to_categorical(y_test) 
num_classes = y_train.shape[1] #number of categories 


# Create the model 
model = Sequential() 
model.add(Conv2D(224, (11, 11), input_shape=(224, 224, 3), activation='relu', padding='same')) 
model.add(Dropout(0.2)) 
model.add(Conv2D(55, (5, 5), activation='relu', padding='same')) 
model.add(MaxPooling2D(pool_size=(2, 2), data_format="channels_last")) 
model.add(Conv2D(13, (3, 3), activation='relu', padding='same')) 
model.add(Dropout(0.5)) 
model.add(Conv2D(13, (3, 3), activation='relu', padding='same')) 
model.add(MaxPooling2D(pool_size=(2, 2), data_format="channels_last")) 
model.add(Flatten()) 
model.add(Dropout(0.2)) 
model.add(Dense(512, activation='relu', kernel_constraint=maxnorm(3))) 
model.add(Dropout(0.2)) 
model.add(Dense(num_classes, activation='softmax')) 

# Compile model 
epochs = 100 
lrate = 0.01 
decay = lrate/epochs 
sgd = SGD(lr=lrate, momentum=0.9, decay=decay, nesterov=False) 
model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['accuracy']) 
#print(model.summary()) 
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=epochs, batch_size=10) 

# Final evaluation of the model 
scores = model.evaluate(X_test, y_test, verbose=0) 
print("Accuracy: %.2f%%" % (scores[1]*100)) 

#and then we save 
# serialize model to JSON 
model_json = model.to_json() 
with open("Data/model.json", "w") as json_file: 
    json_file.write(simplejson.dumps(simplejson.loads(model_json), indent=4)) 
# serialize weights to HDF5 
model.save_weights("Data/model.h5") 
print("Saved model to disk") 

我用kerastensorflow。图像是224x224像素每个分成2个类别。我对神经网络了解不多,这是我第一次尝试做这项大型工作。我听说它可能过于合适,或者我需要一个更重要的图层,或者我的批量/时代/学习率是错误的。

任何帮助表示赞赏!

编辑1:种子如何影响网络的训练? 训练结束后,精确度正好是50%,并且使用一个单独的.py文件,它只加载模型并在其上使用预测函数返回所用图像的确切输出百分比。我尝试了用于训练和外部的图像。 我添加了dataFetch代码。

#preparing the photos to be 224x224 and getting them from urls saved in txt files 

from PIL import Image 
import requests 
from io import BytesIO 
import numpy as np 
import socket 
import random 
from scipy import misc 
from PIL import ImageChops 
import math, operator 
from functools import reduce 
import glob 
import os 
import signal 

compare = Image.open('/home/mihai/PycharmProjects/neuralnet/compare.jpg') 
compare1 = Image.open('/home/mihai/PycharmProjects/neuralnet/compare1.jpg') 
compare2 = Image.open('/home/mihai/PycharmProjects/neuralnet/compare2.jpg') 
compare3 = Image.open('/home/mihai/PycharmProjects/neuralnet/compare3.jpg') 
compare4 = Image.open('/home/mihai/PycharmProjects/neuralnet/compare4.jpg') 

def rmsdiff(im1, im2): 
    "Calculate the root-mean-square difference between two images" 

    h = ImageChops.difference(im1, im2).histogram() 

    # calculate rms 
    return math.sqrt(reduce(operator.add, map(lambda h, i: h*(i**2), h, range(256)))/(float(im1.size[0]) * im1.size[1])) 

class DataFetch: 

    chosenFile = '' 
    maxNumber = 0 
    y_train = [] 
    y_test = [] 

    def __init__(self, choice, number): 
     print('Images with '+choice+'s are being prepared') 
     self.chosenFile = choice 
     self.maxNumber = number 

    def getPictures(self): 
     imgArr = np.zeros((self.maxNumber, 224, 224, 3), dtype='uint8') 
     count = 0 
     class timeoutError(Exception): 
      signal.alarm(0) 
     def handler(signum, frame): 
      raise timeoutError 
     with open(self.chosenFile, "r") as ins: 
      for line in ins: 
       if count < self.maxNumber: 
        signal.signal(signal.SIGALRM, handler) 
        signal.alarm(3) 
        try: 
         try: 
          r = requests.get(line) 
          try: 
           img = Image.open(BytesIO(r.content)) 
           ok = 0 
           try: 
            if rmsdiff(compare, img) > 1.3 and rmsdiff(compare1, img) > 1.3 and rmsdiff(compare2, img) > 1.3 and rmsdiff(compare3, img) > 1.3 and rmsdiff(compare4, img) > 1.3: 
             ok = 1 
            else: 
             print('Image removed from website') 
           except ValueError: 
            ok = 1 
           if ok == 1: 
            img = img.resize((224, 224)) 
            img = img.convert('RGB') 
            img.save('/home/mihai/PycharmProjects/neuralnet/images/'+self.chosenFile+'/'+str(count)+".jpg", 'JPEG') 
            imgArr[count, :, :, :] = img 
            count = count + 1 
            print(count) 
          except OSError: 
           print('Image not Available') 
         except socket.error: 
          print('URL not available') 
        except timeoutError: 
         print("URL not available") 
     return imgArr 

    def openPictures(self): 
     cdir = os.getcwd() 
     imgArr = np.zeros((self.maxNumber, 224, 224, 3), dtype='uint8') 
     count = 0 
     for filename in glob.glob(cdir+'/images/'+self.chosenFile+'/*.jpg'): 
      if count < self.maxNumber: 
       img = Image.open(filename) 
       imgArr[count, :, :, :] = img 
       count = count + 1 
     return imgArr 

    def removeErrorImages(self): 
     cdir = os.getcwd() 
     for filename in glob.glob(cdir+'/images/'+self.chosenFile+'/*.jpg'): 
      img = Image.open(filename) 
      try: 
       if rmsdiff(compare, img) < 1.3 or rmsdiff(compare1, img) < 1.3 or rmsdiff(compare2, img) < 1.3 or rmsdiff(compare3, img) < 1.3 or rmsdiff(compare4, img) < 1.3: 
        os.remove(cdir+'/images/'+self.chosenFile+'/'+filename+'.jpg') 
      except ValueError: 
       pass 

    def getYtrain(self,outParam): 
     if outParam == 'train': 
      self.y_train = np.reshape(self.y_train, (len(self.y_train), 1)) 
      return self.y_train 
     else: 
      self.y_test = np.reshape(self.y_test, (len(self.y_test), 1)) 
      return self.y_test 

    def connectData(self, data1, data2, outParam): 
     d1c = 0 
     d2c = 0 
     outList = [] 
     X_train = np.zeros((2 * self.maxNumber, 224, 224, 3), dtype='uint8') 
     for i in range(2 * self.maxNumber): 
      if d1c < self.maxNumber and d2c <self.maxNumber: 
       if random.random() <= 0.5: 
        X_train[d1c + d2c, :, :, :] = data1[d1c, :, :, :] 
        d1c = d1c + 1 
        outList.append(0) 
       else: 
        X_train[d1c + d2c, :, :, :] = data2[d2c, :, :, :] 
        d2c = d2c + 1 
        outList.append(1) 
      else: 
       if d1c < self.maxNumber: 
        X_train[d1c + d2c, :, :, :] = data1[d1c, :, :, :] 
        d1c = d1c + 1 
        outList.append(0) 
       else: 
        if d2c < self.maxNumber: 
         X_train[d1c + d2c, :, :, :] = data2[d2c, :, :, :] 
         d2c = d2c + 1 
         outList.append(1) 
     if outParam == 'train': 
      self.y_train = outList 
     else: 
      if outParam == 'test': 
       self.y_test = outList 
     return X_train 

代码预测:

#run this to test a sample 

from keras.utils import np_utils 
from keras.models import model_from_json 
from keras.optimizers import SGD 
from datasetFetch import DataFetch 

# load json and create model 
json_file = open('Data/model2.json', 'r') 
loaded_model_json = json_file.read() 
json_file.close() 
loaded_model = model_from_json(loaded_model_json) 

# load weights into new model 
loaded_model.load_weights("Data/model2.h5") 
print("Loaded model from disk") 

epochs = 100 
lrate = 0.01 
decay = lrate/epochs 
sgd = SGD(lr=lrate, momentum=0.9, decay=decay, nesterov=False) 
loaded_model.compile(loss='categorical_crossentropy', optimizer=sgd, metrics=['accuracy']) 

#prepare X_test 
tdata = DataFetch('test-orange',int(3)) 
tdata1 = tdata.openPictures() 
tdata = DataFetch('test-apple',int(3)) 
tdata2 = tdata.openPictures() 
X_test = tdata.connectData(tdata1,tdata2,'test') 
y_test = tdata.getYtrain('test') 
X_test = X_test.astype('float32') 
X_test = X_test/255.0 
y_test = np_utils.to_categorical(y_test) 
print('Number of samples to be tested: '+str(X_test.shape[0])) 

scores = loaded_model.evaluate(X_test, y_test, verbose=0) 
print(scores[1]*100) 

score = loaded_model.predict(X_test,batch_size=6, verbose=1) 
print(score) #prints percentages 
+0

准确性是相同的,因为你设置了一个固定的随机种子 –

+0

你是什么意思的“它给出了相同的结果”?无论您传递给它什么样的输入,它都会做出相同的预测,或者您将相同的输入传递给它并始终获得50%的准确性? – gionni

+0

啊对不起,我以为你在同一个脚本中使用了model.predict。训练阶段模型的准确性/损失是什么?以及在使用模型预测之前如何重新加载数据和模型? –

回答

0

图像准备是正确的。问题出在神经网络的结构加上使用的优化方法。

由于用于分类只有2个类的神经元数量巨大,结构过度拟合,导致精度保持在50%。

第二个问题是使用sgd优化器。我使用:

opt=keras.optimizers.rmsprop(lr=0.0001, decay=1e-6) 
model.compile(loss='binary_crossentropy', optimizer=opt, metrics=['accuracy'] 

希望这可以帮助别人!