Ошибка входных данных Keras
Нашёл на просторах интернета код сиамской сети, решил попробовать, но даже оригинал имел ошибки, связанные в различиях версий библиотек и самого python. Все не совместимости заменил и всё застопорилось на вот этой ошибке
ValueError: Input 0 of layer sequential is incompatible with the layer: expected axis -1 of input shape to have value 1 but received input with shape [None, 1, 112, 92]
вот мой код
import re
import numpy as np
from PIL import Image
from sklearn.model_selection import train_test_split
from keras import backend as K
import tensorflow as tf
from keras.layers import Activation
from keras.layers import Input, Lambda, Dense, Dropout, Conv2D, MaxPooling2D, Flatten
from keras.models import Sequential, Model
from keras.optimizers import RMSprop
import cv2 as cv
def read_image(filename, byteorder='>'):
#first we read the image, as a raw file to the buffer
with open(filename, 'rb') as f:
buffer = f.read()
#using regex, we extract the header, width, height and maxval of the image
header, width, height, maxval = re.search(
b"(^P5\s(?:\s*#.*[\r\n])*"
b"(\d+)\s(?:\s*#.*[\r\n])*"
b"(\d+)\s(?:\s*#.*[\r\n])*"
b"(\d+)\s(?:\s*#.*[\r\n]\s)*)", buffer).groups()
#then we convert the image to numpy array using np.frombuffer which interprets buffer as one dimensional array
res=np.frombuffer(buffer)
if int(maxval): res=np.dtype(res,"u1")
return res
size = 2
total_sample_size = 10000
def get_data(size, total_sample_size):
#read the image
image = cv.imread('res/s' + str(1) + '/' + str(1) + '.pgm')
#reduce the size
# image = image[::size, ::size]
#get the new size
image=cv.cvtColor(image, cv.COLOR_BGR2GRAY)
image.reshape(112,92,1)
dim1 = image.shape[0]
dim2 = image.shape[1]
count = 0
#initialize the numpy array with the shape of [total_sample, no_of_pairs, dim1, dim2]
x_geuine_pair = np.zeros([total_sample_size, 2, 1, dim1, dim2]) # 2 is for pairs
y_genuine = np.zeros([total_sample_size, 1])
for i in range(40):
for j in range(int(total_sample_size/40)):
ind1 = 0
ind2 = 0
#read images from same directory (genuine pair)
while ind1 == ind2:
ind1 = np.random.randint(10)
ind2 = np.random.randint(10)
# read the two images
img1 = cv.imread('res/s' + str(i+1) + '/' + str(ind1 + 1) + '.pgm')
img2 = cv.imread('res/s' + str(i+1) + '/' + str(ind2 + 1) + '.pgm')
img1, img2= cv.cvtColor(img1, cv.COLOR_BGR2GRAY), cv.cvtColor(img2, cv.COLOR_BGR2GRAY)
img1.reshape(112,92,1)
img2.reshape(112,92,1)
#store the images to the initialized numpy array
x_geuine_pair[count, 0, 0, :, :] = img1
x_geuine_pair[count, 1, 0, :, :] = img2
#as we are drawing images from the same directory we assign label as 1. (genuine pair)
y_genuine[count] = 1
count += 1
count = 0
x_imposite_pair = np.zeros([total_sample_size, 2, 1, dim1, dim2])
y_imposite = np.zeros([total_sample_size, 1])
for i in range(int(total_sample_size/10)):
for j in range(10):
#read images from different directory (imposite pair)
while True:
ind1 = np.random.randint(40)
ind2 = np.random.randint(40)
if ind1 != ind2:
break
img1 = cv.imread('res/s' + str(ind1+1) + '/' + str(j + 1) + '.pgm')
img2 = cv.imread('res/s' + str(ind2+1) + '/' + str(j + 1) + '.pgm')
img1, img2= cv.cvtColor(img1, cv.COLOR_BGR2GRAY), cv.cvtColor(img2, cv.COLOR_BGR2GRAY)
img1.reshape(112,92,1)
img2.reshape(112,92,1)
x_imposite_pair[count, 0, 0, :, :] = img1
x_imposite_pair[count, 1, 0, :, :] = img2
#as we are drawing images from the different directory we assign label as 0. (imposite pair)
y_imposite[count] = 0
count += 1
#now, concatenate, genuine pairs and imposite pair to get the whole data
X = np.concatenate([x_geuine_pair, x_imposite_pair], axis=0)/255
Y = np.concatenate([y_genuine, y_imposite], axis=0)
return X, Y
X, Y = get_data(size, total_sample_size)
X.shape
(20000, 2, 112,92,1)
Y.shape
(20000, 1)
def build_base_network(input_shape):
seq = Sequential()
nb_filter = [6, 12]
kernel_size = 3
#convolutional layer 1
seq.add(Conv2D(nb_filter[0], kernel_size=kernel_size, input_shape=input_shape))
seq.add(Activation('relu'))
seq.add(MaxPooling2D(pool_size=(2, 2)))
seq.add(Dropout(.25))
#convolutional layer 2
seq.add(Conv2D(nb_filter[1], kernel_size= kernel_size))
seq.add(Activation('relu'))
seq.add(MaxPooling2D(pool_size=(2, 2), ))
seq.add(Dropout(.25))
#flatten
seq.add(Flatten())
seq.add(Dense(128, activation='relu'))
seq.add(Dropout(0.1))
seq.add(Dense(50, activation='relu'))
return seq
x_train, x_test, y_train, y_test = train_test_split(X, Y, test_size=.25)
input_dim = x_train.shape[2:]
print(input_dim)
print(x_train.shape)
img_a = Input(shape=(112,92,1))
img_b = Input(shape=(112,92,1))
base_network = build_base_network((112,92,1))
feat_vecs_a = base_network(img_a)
feat_vecs_b = base_network(img_b)
def euclidean_distance(vects):
x, y = vects
return K.sqrt(K.sum(K.square(x - y), axis=1, keepdims=True))
def eucl_dist_output_shape(shapes):
shape1, shape2 = shapes
return (shape1[0], 1)
distance = Lambda(euclidean_distance, output_shape=eucl_dist_output_shape)([feat_vecs_a, feat_vecs_b])
epochs = 13
rms = RMSprop()
model = Model(inputs=[img_a,img_b], outputs=distance)
def contrastive_loss(y_true, y_pred):
margin = 1
return K.mean(y_true * K.square(y_pred) + (1 - y_true) * K.square(K.maximum(margin - y_pred, 0)))
model.compile(loss=contrastive_loss, optimizer=rms)
img_1 = x_train[:, 0]
img_2 = x_train[:, 1]
img_1.reshape(15000,112,92,1)
img_2.reshape(15000,112,92,1)
# img_1=np.reshape(img_1,(1,-1))
# img_2=np.reshape(img_2,(1,-1))
model.fit([img_1, img_2], y_train, batch_size=128, verbose=2, epochs=epochs)
pred = model.predict([x_test[:, 0], x_test[:, 1]])
def compute_accuracy(predictions, labels):
return labels[predictions.ravel()]
print(compute_accuracy(pred, y_test))
Здесь оригинал статья на Хабре
Пробовал на последних версиях Tensorflow/Keras с python3.8.0/5 и на линуксе Tensorflow 1.14/Keras 2.2.4 c python3.6.9. Ошибка от версий не меняется