我想用遗传算法和Keras来做蛇这个游戏。
我的问题,现在是这样的。
我创建了一个蛇的初始种群,每个种群有X个基因,其中X是NUMBER_WEIGHTS。
INPUT = 24
NEURONS_HIDDEN_1 = 16
NEURONS_HIDDEN_2 = 16
OUTPUT = 3
NUMBER_WEIGHTS = INPUT * NEURONS_HIDDEN_1 + NEURONS_HIDDEN_1 * NEURONS_HIDDEN_2 + NEURONS_HIDDEN_2 * OUTPUT
我创建的初始种群是这样的
population = numpy.random.choice(numpy.arange(-1, 1, step=0.01), size=(config.NUMBER_OF_POPULATION, config.NUMBER_WEIGHTS))
我有一个for循环,我的种群中的每条蛇都会启动pygame脚本,在pygame脚本中我有Keras NN,但我想把我生成的权重传递给NN。
我的NN目前是这样的。
from keras.layers import Dense, Activation
from keras.models import Sequential
from keras.optimizers import SGD
from utils import config
def neural_net(weights):
model = Sequential()
model.add(Dense(config.INPUT, input_shape=(config.INPUT,)))
model.add(Activation('relu'))
# create the dense input layer
# model.add(Dense(config.INPUT, activation=keras.activations.relu(4,), input_dim=4))
# model.add(Activation('sigmoid'))
# create first hidden layer
model.add(Dense(config.NEURONS_HIDDEN_1, input_shape=(config.INPUT,)))
model.add(Activation('relu'))
# create second hidden layer
model.add(Dense(config.NEURONS_HIDDEN_2, input_shape=(config.NEURONS_HIDDEN_1,)))
model.add(Activation('relu'))
# create output layer
model.add(Dense(config.OUTPUT, input_shape=(config.NEURONS_HIDDEN_2,)))
model.add(Activation('softmax'))
print(weights.shape[0])
model.set_weights(weights)
# create the optimizer (Stochastic Gradient Descent)
sgd = SGD(lr=0.01, decay=0.0, momentum=0.0, nesterov=False)
# Use mean squared error loss and SGD as optimizer
model.compile(loss='mse', optimizer=sgd)
return model
但是model.set_weights(weights)会返回这个异常。
File "neural_network.py", line 28, in neural_net
model.set_weights(weights)
File "C:\Users\Davide\AppData\Local\Programs\Python\Python37\lib\site-packages\keras\engine\network.py", line 527, in set_weights
K.batch_set_value(tuples)
File "C:\Users\Davide\AppData\Local\Programs\Python\Python37\lib\site-packages\keras\backend\tensorflow_backend.py", line 2960, in batch_set_value
tf_keras_backend.batch_set_value(tuples)
File "C:\Users\Davide\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow_core\python\keras\backend.py", line 3323, in batch_set_value
x.assign(np.asarray(value, dtype=dtype(x)))
File "C:\Users\Davide\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow_core\python\ops\resource_variable_ops.py", line 819, in assign
self._shape.assert_is_compatible_with(value_tensor.shape)
File "C:\Users\Davide\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow_core\python\framework\tensor_shape.py", line 1110, in assert_is_compatible_with
raise ValueError("Shapes %s and %s are incompatible" % (self, other))
ValueError: Shapes (24, 24) and () are incompatible
Process finished with exit code 1
我们有24个输入*16个神经元在隐藏层一,然后16个神经元*16个神经元在隐藏层二,最后16个神经元隐藏层二*3输入=24*16+16*16+16*3=688。
还有
print(weights.shape[0])
是688。那么为什么我不能设置正确的权重呢?
第一次使用AI做项目,所以我可能完全误解了它的工作原理。
我确定模型的权重和你提供的权重存在形状不匹配。你需要提供各层对应的权重,如下图所示。
import tensorflow as tf
mnist = tf.keras.datasets.mnist
(x_train, y_train),(x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
def create_model():
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28),name='flatten'),
tf.keras.layers.Dense(128, activation='relu',name='dense1'),
tf.keras.layers.Dropout(0.2,name = 'dropout'),
tf.keras.layers.Dense(10, name='dense2')
])
model.compile(optimizer='adam',
loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), #'sparse_categorical_crossentropy',
metrics=['accuracy'])
return model
# create model architecture and compile
model = create_model()
model.fit(x_train, y_train, epochs=5)
model.evaluate(x_test, y_test)
#saving weights
model.save_weights('./model_weights', save_format='tf')
#layer weights from the model
layer_dict = dict([(layer.name, layer) for layer in model.layers])
print(layer_dict)
# creating the same model architecture and compile
loaded_model = create_model()
# This initializes the variables used by the optimizers,
# as well as any stateful metric variables
loaded_model.train_on_batch(x_train[:1], y_train[:1])
# loading the weights from base_model
for layer in loaded_model.layers:
layer_name = layer.name
print(layer.name)
layer.set_weights(layer_dict[layer_name].get_weights())
# accessing weights of a layer by its name
layer_dict[layer_name].get_weights()
# check the evaluation before and after are same
loaded_model.evaluate(x_test, y_test)
print(loaded_model.weights)
print(model.weights)
希望这个例子能给你解决问题的一些启示。完整的代码是 此处 供大家参考。