Ожидал увидеть 3 массива, но вместо этого получил следующий список из 1 массива
I am trying to train a triple loss model using a fit_generator. it requires three input and no output. so i have a function that generates hard triplets. the output from the triplets generator has a shape of (3,5,279) which is 3 inputs(anchor,positive and negative) for 5 batches and a total of 279 features. When i run the fit_generator it throws this error that "the list of Numpy arrays that you are passing to your model is not the size the model expected. Expected to see 3 array(s), but instead got the following list of 1 arrays" meanwhile i have passed a list of three arrays. the code is below. it works when i use the fit, however, i want to always call the generator function to generate my triplets as my batches. thanks in advance..this has taken me three days
<pre lang="Python"> def load_data(): path = "arrhythmia_data.txt" f = open( path, "r") data = [] #remove line breaker, comma separate and store in array for line in f: line = line.replace('\n','').replace('?','0') line = line.split(",") data.append(line) f.close() data = np.array(data).astype(np.float64) #print(data.shape) #create the class labels for input data Y_train = data[:,-1:] train = data[:,:-1] normaliser = preprocessing.MinMaxScaler() train = normaliser.fit_transform(train) val = train[320:,:] train = train[:320,:] #create one hot encoding of the class labels of the data and separate them into train and test data lb = LabelBinarizer() encode = lb.fit_transform(Y_train) nb_classes = int(len(encode[0])) #one_hot_labels = keras.utils.to_categorical(labels, num_classes=10) this could also be used for one hot encoding Y_val_e = encode[320:,:] Y_train_e = encode[:320,:] print(Y_train_e[0]) print(np.argmax(Y_train_e[0])) val_in = [] train_in = [] #grouping and sorting the input data based on label id or name for n in range(nb_classes): images_class_n = np.asarray([row for idx,row in enumerate(train) if np.argmax(Y_train_e[idx])==n]) train_in.append(images_class_n) images_class_n = np.asarray([row for idx,row in enumerate(val) if np.argmax(Y_val_e[idx])==n]) val_in.append(images_class_n) #print(train_in[0].shape) return train_in,val_in,Y_train_e,Y_val_e,nb_classes train_in,val,Y_train,Y_val,nb_classes = load_data() input_shape = (train_in[0].shape[1],) def build_network(input_shape , embeddingsize): ''' Define the neural network to learn image similarity Input : input_shape : shape of input images embeddingsize : vectorsize used to encode our picture ''' #in_ = Input(train.shape) net = Sequential() net.add(Dense(128, activation='relu', input_shape=input_shape)) net.add(Dense(128, activation='relu')) net.add(Dense(256, activation='relu')) net.add(Dense(4096, activation='sigmoid')) net.add(Dense(embeddingsize, activation= None)) #Force the encoding to live on the d-dimentional hypershpere net.add(Lambda(lambda x: K.l2_normalize(x,axis=-1))) return net class TripletLossLayer(Layer): def __init__(self, alpha, **kwargs): self.alpha = alpha super(TripletLossLayer, self).__init__(**kwargs) def triplet_loss(self, inputs): anchor, positive, negative = inputs p_dist = K.sum(K.square(anchor-positive), axis=-1) n_dist = K.sum(K.square(anchor-negative), axis=-1) return K.sum(K.maximum(p_dist - n_dist + self.alpha, 0), axis=0) def call(self, inputs): loss = self.triplet_loss(inputs) self.add_loss(loss) return loss def build_model(input_shape, network, margin=0.2): ''' Define the Keras Model for training Input : input_shape : shape of input images network : Neural network to train outputing embeddings margin : minimal distance between Anchor-Positive and Anchor-Negative for the lossfunction (alpha) ''' # Define the tensors for the three input images anchor_input = Input(input_shape, name="anchor_input") positive_input = Input(input_shape, name="positive_input") negative_input = Input(input_shape, name="negative_input") # Generate the encodings (feature vectors) for the three images encoded_a = network(anchor_input) encoded_p = network(positive_input) encoded_n = network(negative_input) #TripletLoss Layer loss_layer = TripletLossLayer(alpha=margin,name='triplet_loss_layer')([encoded_a,encoded_p,encoded_n]) # Connect the inputs with the outputs network_train = Model(inputs=[anchor_input,positive_input,negative_input],outputs=loss_layer) # return the model return network_train def get_batch_random(batch_size,s="train"): # initialize result triplets=[np.zeros((batch_size,m)) for i in range(3)] for i in range(batch_size): #Pick one random class for anchor anchor_class = np.random.randint(0, nb_classes) nb_sample_available_for_class_AP = X[anchor_class].shape[0] #Pick two different random pics for this class => A and P. You can use same anchor as P if there is one one element for anchor if nb_sample_available_for_class_AP<=1: continue [idx_A,idx_P] = np.random.choice(nb_sample_available_for_class_AP,size=2 ,replace=False) #Pick another class for N, different from anchor_class negative_class = (anchor_class + np.random.randint(1,nb_classes)) % nb_classes nb_sample_available_for_class_N = X[negative_class].shape[0] #Pick a random pic for this negative class => N idx_N = np.random.randint(0, nb_sample_available_for_class_N) triplets[0][i,:] = X[anchor_class][idx_A,:] triplets[1][i,:] = X[anchor_class][idx_P,:] triplets[2][i,:] = X[negative_class][idx_N,:] return np.array(triplets) def get_batch_hard(draw_batch_size,hard_batchs_size,norm_batchs_size,network,s="train"): if s == 'train': X = train_in else: X = val #m, features = X[0].shape #while True: #Step 1 : pick a random batch to study studybatch = get_batch_random(draw_batch_size,X) #Step 2 : compute the loss with current network : d(A,P)-d(A,N). The alpha parameter here is omited here since we want only to order them studybatchloss = np.zeros((draw_batch_size)) #Compute embeddings for anchors, positive and negatives A = network.predict(studybatch[0]) P = network.predict(studybatch[1]) N = network.predict(studybatch[2]) #Compute d(A,P)-d(A,N) studybatchloss = np.sum(np.square(A-P),axis=1) - np.sum(np.square(A-N),axis=1) #Sort by distance (high distance first) and take the selection = np.argsort(studybatchloss)[::-1][:hard_batchs_size] #Draw other random samples from the batch selection2 = np.random.choice(np.delete(np.arange(draw_batch_size),selection),norm_batchs_size,replace=False) selection = np.append(selection,selection2) triplets = [studybatch[0][selection,:], studybatch[1][selection,:],studybatch[2][selection,:]] triplets = triplets.reshape(triplets.shape[0],triplets.shape[1],triplets.shape[2]) yield triplets network = build_network(input_shape,embeddingsize=10) hard = get_batch_hard(5,4,1,network,s="train") network_train = build_model(input_shape,network) optimizer = Adam(lr = 0.00006) network_train.compile(loss=None,optimizer=optimizer) #this works #history = network_train.fit(hard,epochs=100,steps_per_epoch=1, verbose=2) history = network_train.fit_generator(hard,epochs=10,steps_per_epoch=16, verbose=2) # error:: the list of Numpy arrays that you are passing to your model is not the size the model expected. Expected to see 3 array(s), but instead got the following list of 1 arrays: tensorflow keras conv-neural-network numpy-ndarray loss-function
Что я уже пробовал:
я попробовал поддаваться отдельно в разные вариабли, но это все равно не сработало.