Keras CNN图像分类-从数据框中输入图像名称

时间:2018-09-04 16:41:19

标签: python numpy keras conv-neural-network

这是我拥有的数据集:

imageName         image_class
1466021829460.jpg   1
1466022672915.jpg   6
1466025877175.jpg   1
1466023217363.jpg   1
1466026546959.jpg   0

因此,我不得不从链接中抓取这些图像,并将其存储在文件夹中。我用于抓取的代码是这样的(使用urllib模块):

import urllib.request

for i in df['imageName']:
    urllib.request.urlretrieve('https://*********/*****/*****/****/' + str(i),i)
    print ("Image saved")

现在,我使用以下代码在像素数组后面附加类:

def proc_images():
    x = [] # images as arrays
    y = [] # labels
    WIDTH = 128
    HEIGHT = 128
    findings = df['image_class'].values
    for img,finding in zip(images,findings):
        base = os.path.basename(img)
        full_size_image = cv2.imread(img)
        # Read and resize image
        y.append(finding)
        x.append(cv2.resize(full_size_image, (WIDTH,HEIGHT), interpolation=cv2.INTER_CUBIC))
    return x,y
X,y = proc_images()
df1 = pd.DataFrame()
df1["images"]=X
df1["labels"]=y
print(len(df1), df1.images[0].shape)
print(type(X))

输出:

5000 (128, 128, 3)
<class 'list'>

现在的数据框:

images                                                labels
0   [[[18, 47, 74], [25, 55, 82], [28, 58, 87], [3...   1
1   [[[162, 158, 100], [164, 161, 103], [166, 159,...   6
2   [[[12, 5, 43], [15, 9, 30], [25, 18, 28], [14,...   1
3   [[[107, 159, 191], [116, 163, 197], [110, 153,...   1
5   [[[143, 147, 142], [145, 149, 144], [143, 147,...   4

下一步:

X=np.array(X)
X=X/255.0

X_train, X_test, Y_train, Y_test = train_test_split(X, y, test_size=0.2)
print("Training Data Shape:", X_train.shape)
print("Testing Data Shape:", X_test.shape)
print("Training Data Shape:", len(X_train), X_train[0].shape)
print("Testing Data Shape:", len(X_test), X_test[0].shape)

输出:

Training Data Shape: (2837, 128, 128, 3)
Testing Data Shape: (710, 128, 128, 3)
Training Data Shape: 2837 (128, 128, 3)
Testing Data Shape: 710 (128, 128, 3)

Y_trainHot = to_categorical(Y_train, num_classes = 7)
Y_testHot = to_categorical(Y_test, num_classes = 7)

主要型号:

from keras.applications.vgg16 import VGG16
from keras.models import Model
#weight_path = '../input/keras-pretrained-models/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5'
im_size = 128
map_characters=dict_characters
def vgg16network(a,b,c,d,e,f,g):
    num_class = f
    epochs = g
    base_model = VGG16(weights='imagenet', include_top=False, input_shape=(im_size, im_size, 3))
    # Add a new top layer
    x = base_model.output
    x = Flatten()(x)
    predictions = Dense(num_class, activation='softmax')(x)
    # This is the model we will train
    model = Model(inputs=base_model.input, outputs=predictions)
    # First: train only the top layers (which were randomly initialized)
    for layer in base_model.layers:
        layer.trainable = False
    model.compile(loss='categorical_crossentropy', 
                  optimizer=keras.optimizers.RMSprop(lr=0.0001), 
                  metrics=['accuracy'])
    callbacks_list = [keras.callbacks.EarlyStopping(monitor='val_acc', patience=3, verbose=1)]
    model.summary()
    model.fit(a,b, epochs=epochs, class_weight=e, validation_data=(c,d), verbose=1,callbacks = [MetricsCheckpoint('logs')])
    score = model.evaluate(c,d, verbose=0)
    print('\nKeras CNN #2 - accuracy:', score[1], '\n')
    y_pred = model.predict(c)
    print('\n', sklearn.metrics.classification_report(np.where(d > 0)[1], np.argmax(y_pred, axis=1), target_names=list(map_characters.values())), sep='') 
    Y_pred_classes = np.argmax(y_pred,axis = 1) 
    Y_true = np.argmax(d,axis = 1) 
    confusion_mtx = confusion_matrix(Y_true, Y_pred_classes) 
    plotKerasLearningCurve()
    plt.show()
    plot_confusion_matrix(confusion_mtx, classes = list(map_characters.values()))
    plt.show()
    return model

然后进行一些采样,因为数据集不平衡:

from imblearn.over_sampling import RandomOverSampler
ros = RandomOverSampler(ratio='auto')
X_trainRos, Y_trainRos = ros.fit_sample(X_trainFlat, Y_train)
X_testRos, Y_testRos = ros.fit_sample(X_testFlat, Y_test)

# Encode labels to hot vectors (ex : 2 -> [0,0,1,0,0,0,0,0,0,0])
Y_trainRosHot = to_categorical(Y_trainRos, num_classes = 7)
Y_testRosHot = to_categorical(Y_testRos, num_classes = 7)
print("X_train: ", X_train.shape)
print("X_trainFlat: ", X_trainFlat.shape)
print("X_trainRos Shape: ",X_trainRos.shape)
print("X_testRos Shape: ",X_testRos.shape)
print("Y_trainRosHot Shape: ",Y_trainRosHot.shape)
print("Y_testRosHot Shape: ",Y_testRosHot.shape)

然后我想看一下形状:

for i in range(len(X_trainRos)):
    height, width, channels = 128,128,3
    X_trainRosReshaped = X_trainRos.reshape(len(X_trainRos),height,width,channels)
print("X_trainRos Shape: ",X_trainRos.shape)
print("X_trainRosReshaped Shape: ",X_trainRosReshaped.shape)

for i in range(len(X_testRos)):
    height, width, channels = 128,128,3
    X_testRosReshaped = X_testRos.reshape(len(X_testRos),height,width,channels)
print("X_testRos Shape: ",X_testRos.shape)
print("X_testRosReshaped Shape: ",X_testRosReshaped.shape)

输出:

X_trainRos Shape:  (7806, 49152)
X_trainRosReshaped Shape:  (7806, 128, 128, 3)
X_testRos Shape:  (2028, 49152)
X_testRosReshaped Shape:  (2028, 128, 128, 3)

运行功能:

vgg16network(X_trainRosReshaped, Y_trainRosHot, X_testRosReshaped, Y_testRosHot,class_weight,7,25)

在3个或4个时期之后,我的acc增加了,但val_acc却被卡住了。

Epoch 1/25
7806/7806 [==============================] - 2089s 268ms/step - loss: 1.7347 - acc: 0.2848 - val_loss: 1.8463 - val_acc: 0.1583
Epoch 2/25
7806/7806 [==============================] - 1995s 256ms/step - loss: 1.4878 - acc: 0.4813 - val_loss: 1.8764 - val_acc: 0.1558

所有图像都被抓取并存储在一个文件夹中,我在像素上附加了类标签。我不知道为什么,但是我也早些时候面对过这个问题。每当我在图像像素上附加类别标签并形成数据框时,keras只会预测一个类别。是因为我添加或存储数据的方式,还是其他原因?

我检查了this solution,但似乎没有解决问题。

有关我的完整代码,您可以查看HTML file of my IPYNB here

我想念一些概念吗?这不仅是解决问题,还在于理解概念。

0 个答案:

没有答案