У меня есть набор данных:
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 предсказывает только один класс. Это из-за того, как я добавляю или храню данные или что-то еще?
Я проверил это решение , но, похоже, не сработало.
Для моего полного кода, вы можете просмотреть HTML-файл моего IPYNB здесь .
Я что-то упустил? Речь идет не только об устранении проблемы, но и о понимании концепции.