Как установить некоторые веса в слое в Керасе - PullRequest
0 голосов
/ 28 апреля 2018

Есть ли способ установить определенные веса для определенного значения в слоях Keras?

Например, у меня есть набор массивов 3x3 в качестве входных данных. Они расположены в последовательности по 7. Каждый массив имеет значения 0, 1 или -1. Для позиций со значением -1 я не хочу вносить вклад в расчеты веса или функцию потерь. Я думал, что Masking предоставит то, что я искал, но это оказалось тупиком: насколько я могу судить, вы не можете маскировать отдельные значения во входном примере.

Есть ли способ использовать set_weights для этого?

Этот код - то, что у меня есть (пока нет set_weights).

from keras.layers import Input, LSTM, Dense
from keras.models import Model
import numpy as np
from keras.optimizers import adam

#Creating some sample data

#Matrix has size 3*3, values -1, 0, 1
X = np.random.rand(3, 3).flatten()
X[X < 0.2] = 0.
X[(X >= 0.2) & (X < 0.4)] = 1.
X[X >= 0.4] = -1

X2 = np.random.rand(7, 3*3)
for i in range(X2.shape[0]):
    X2[i,:][(X==-1.)] = -1.
    X2[i,:][(X !=-1.)] = 0.
    tobeone = int(len(np.where(X2[i,:] == 0.)[0])*0.5)
    selected_ones = np.random.choice(np.where(X2[i,:] == 0.)[0], tobeone)
    X2[i,selected_ones] = 1.

X = np.reshape(X, ((1, 3*3)))
X_new = np.concatenate((X, X2), axis=0)
y_true = X_new[7,:]
X = X_new[:7,:]

#Building the model

input_tensor = Input(shape=(7, 3*3))
lstm = LSTM(1, return_sequences=True)(input_tensor)
output = Dense(3*3, activation='sigmoid')(lstm)

model = Model(input_tensor, output)
model.compile(loss='categorical_crossentropy', optimizer='adam')

РЕДАКТИРОВАТЬ

Теперь, имея 500 обучающих примеров, немного изменил модель для целей измерения (теперь без return_sequence = True - мне это было нужно, когда я экспериментировал с Masking, но теперь это не нужно). Пожалуйста, имейте в виду, что эти данные являются случайными, поэтому мы не ожидаем, что они будут здесь подходящими.

from keras import backend as K
from keras.utils import to_categorical
from keras.optimizers import adam
import sys

#Creating some sample data

#Matrix has size 3*3, values -1, 0, 1
X = np.random.rand(7, 3, 3).flatten() #7*3*3 = 42
X[X < 0.2] = 0.
X[(X >= 0.2) & (X < 0.4)] = 1.
X[X >= 0.4] = -1

Xlist = list()
Xlist.append(X)
for j in range(499): #500 total input examples
    X2 = np.random.rand(7, 3, 3).flatten()
    X2[(X==-1.)] = -1.
    X2[(X !=-1.)] = 0.
    tobeone = int(len(np.where(X2 == 0.)[0])*0.5)
    selected_ones = np.random.choice(np.where(X2 == 0.)[0], tobeone)
    X2[selected_ones] = 1.
    X2 = np.reshape(X2, ((7, 3, 3)))
    Xlist.append(X2)

Xlist[0] = np.reshape(Xlist[0], ((7, 3, 3)))
X = np.asarray(Xlist)
X = np.reshape(X, ((500, 7, 3*3)))

Y = X[:, -1, :]
y_true = Y
X = X[:, :-1, :]

#print(y_true.shape, X.shape) #(500, 9) and (500, 6, 9)

#Building the model
input_tensor = Input(shape=(X.shape[1], X.shape[2]))
lstm = LSTM(1)(input_tensor) #return_sequences=True)(input_tensor)
output = Dense(X.shape[2], activation='sigmoid')(lstm)

model = Model(input_tensor, output)
model.compile(loss='categorical_crossentropy', optimizer='adam')
print(model.summary())

model.fit(X, y_true, batch_size = 10, epochs = 10, verbose=2) 

1 Ответ

0 голосов
/ 30 апреля 2018

Хорошо, проблема заключалась в использовании весов в качестве типа переменной вместо использования значений внутри. Это было исправлено настройкой weights = K.eval(weights) в custom_reg.

from keras.layers import Input, LSTM, Dense
from keras.models import Model
from keras import backend as K
from tensorflow.python.ops.variables import Variable
import numpy as np
import keras
from keras.optimizers import adam
from keras.callbacks import LambdaCallback


class SaveWeightsandRegularize(keras.callbacks.Callback):

    # Batch_num is defined so we can access the current X input into the model, as well as save layer params per batch.

    batch_num = 0
    X = None  # We'll set this to our X data

    def on_train_begin(self, logs={}):
        self.weights = {}

    def on_batch_end(self, batch, logs={}):
        self.batch_num += 1
        for layer in model.layers:
            self.weights[str(self.batch_num)] = layer.get_weights()

    def custom_reg(self, weights):
        # We set the already computed weights where the value of the input is -1 to a value of 0.
        weights = K.eval(weights)
        loss_contrib = np.where(X[self.batch_num] > -1, weights, 0)
        return Variable(loss_contrib)

# Creating some sample data


def gen_data():
    # Matrix has size 3*3, values -1, 0, 1
    X = np.random.rand(7, 3, 3).flatten()  # 7*3*3 = 42
    X[X < 0.2] = 0.
    X[(X >= 0.2) & (X < 0.4)] = 1.
    X[X >= 0.4] = -1

    Xlist = list()
    Xlist.append(X)
    for j in range(499):  # 500 total input examples
        X2 = np.random.rand(7, 3, 3).flatten()
        X2[(X==-1.)] = -1.
        X2[(X !=-1.)] = 0.
        tobeone = int(len(np.where(X2 == 0.)[0])*0.5)
        selected_ones = np.random.choice(np.where(X2 == 0.)[0], tobeone)
        X2[selected_ones] = 1.
        X2 = np.reshape(X2, ((7, 3, 3)))
        Xlist.append(X2)

    Xlist[0] = np.reshape(Xlist[0], ((7, 3, 3)))
    X = np.asarray(Xlist)
    X = np.reshape(X, ((500, 7, 3*3)))

    Y = X[:, -1, :]
    y_true = Y
    X = X[:, :-1, :]
    return X, y_true

X, y_true = gen_data()
save_weights_regularize = SaveWeightsandRegularize()
save_weights_regularize.X = X
print("input shape", X.shape)
# Building the model
input_tensor = Input(shape=(X.shape[1], X.shape[2]))
lstm = LSTM(1)(input_tensor)  # return_sequences=True)(input_tensor)
output = Dense(X.shape[2], activation='sigmoid',       kernel_regularizer=save_weights_regularize.custom_reg)(lstm)

model = Model(input_tensor, output)
model.compile(loss='categorical_crossentropy', optimizer='adam')
model.fit(X, y_true, batch_size=1, epochs=10, verbose=2, callbacks=[save_weights_regularize])
print(save_weights_regularize.weights)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...