我有一组图像,显示有人在玩一个视频游戏(这是我在Tkinter中创建的一个简单游戏):
游戏的理念是用户控制屏幕底部的盒子,以躲避下落的球(他们只能向左或向右躲避)。
我的目标是让神经网络输出玩家在屏幕底部的位置。如果玩家完全在左侧,神经网络应输出0
,如果在中间,则输出.5
,如果完全在右侧,则输出1
,以及介于这些值之间的所有数值。
我的图像尺寸为300×400像素。我以非常简单的方式存储数据。我记录了每一帧的图像和玩家位置作为元组,在一个50帧的游戏中。因此,我的结果是一个列表,形式为[(图像, 玩家位置), ...]
,包含50个元素。我随后将这个列表进行了pickle处理。
所以在我的代码中,我尝试创建一个非常基本的前馈网络,它接收图像并输出一个介于0和1之间的值,表示图像底部盒子的位置。但我的神经网络只输出1s。
为了使其训练并输出接近我想要的值,我应该做哪些更改?
当然,这是我的代码:
# 机器学习代码主要来自 https://machinelearningmastery.com/tutorial-first-neural-network-python-keras/from keras.models import Sequentialfrom keras.layers import Denseimport numpy as npimport pickledef pil_image_to_np_array(image): '''将图像转换为numpy数组''' # 来自 https://stackoverflow.com/a/45208895 # 我的所有图像都是黑白的,所以我只需要一个通道 return np.array(image)[:, :, 0:1]def data_to_training_set(data): # 将形式为[(第1帧图像, 第1帧玩家位置), ...]的列表拆分为[[所有图像], [所有玩家位置]] inputs, outputs = [list(val) for val in zip(*data)] for index, image in enumerate(inputs): # 将PIL图像转换为numpy数组,以便Keras处理 inputs[index] = pil_image_to_np_array(image) return (inputs, outputs)if __name__ == "__main__": # 为了可重复性,固定随机种子 np.random.seed(7) # 加载数据 # 数据形式为[(第1帧图像, 第1帧玩家位置), (第2帧图像, 第2帧玩家位置), ...] with open("position_data1.pkl", "rb") as pickled_data: data = pickle.load(pickled_data) X, Y = data_to_training_set(data) # 获取图像的宽度 width = X[0].shape[1] # == 400 # 将玩家位置(介于0和图像宽度之间的值)转换为介于0和1之间的值 for index, output in enumerate(Y): Y[index] = output / width # 展平图像输入,以便传递给神经网络 for index, inpt in enumerate(X): X[index] = np.ndarray.flatten(inpt) # Keras期望输入神经网络的图像数组是一个数组(而不是列表) X = np.array(X) Y = np.array(Y) # 创建模型 model = Sequential() # 我的图像为300 x 400像素,因此每个输入将是一个包含120000个灰度像素值的展平数组 # 保持非常简单,不使用深度学习 model.add(Dense(1, input_dim=120000, activation='sigmoid')) # 编译模型 model.compile(loss='mean_squared_error', optimizer='adam') # 拟合模型 model.fit(X, Y, epochs=15, batch_size=10) # 查看模型的表现 predictions = model.predict(X, batch_size=10) print(predictions) # 这打印出全是1s! # TODO 修复
编辑: print(Y) 显示为: