如何使Keras网络不输出全1

我有一组图像,显示有人在玩一个视频游戏(这是我在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) 显示为:

<code>print(Y)</code>“></a></p>
<p>所以绝对不是全零。</p>
<hr class='wp-block-separator has-alpha-channel-opacity is-style-wide'/>
<p><strong>回答:</strong></p>
<p>当然,更深层次的模型可能会给你更好的准确性,但考虑到你的图像很简单,一个只有一个隐藏层的相当简单的(浅层)模型应该能提供中等到高的准确性。所以,这里是你需要做的修改:</p>
<ol>
<li>
<p>确保<code>X</code>和<code>Y</code>的类型为<code>float32</code>(目前,<code>X</code>的类型为<code>uint8</code>):</p>
<pre><code>X = np.array(X, dtype=np.float32)Y = np.array(Y, dtype=np.float32)</code></pre>
</li>
<li>
<p>在训练神经网络时,最好对训练数据进行归一化。归一化有助于优化过程顺利进行,并加速收敛到解。它还可以防止大值导致大梯度更新,从而造成干扰。通常,输入数据中每个特征的值应落在较小的范围内,两个常见的范围是<code>[-1,1]</code>和<code>[0,1]</code>。因此,为了确保所有值落在<code>[-1,1]</code>的范围内,我们从每个特征中减去其均值,并将其除以其标准差:</p>
<pre><code>X_mean = X.mean(axis=0)X -= X_meanX_std = X.std(axis=0)X /= X_std + 1e-8  # 加上一个非常小的常数以防止除以零</code></pre>
<p>请注意,我们在这里对每个特征(即每个像素)进行归一化,而不是对每张图像。当你想对新数据进行预测时,即在推理或测试模式下,你需要从测试数据中减去<code>X_mean</code>并将其除以<code>X_std</code>(你绝对不应该从测试数据中减去其自身的均值或将其除以其自身的标准差;相反,应该使用训练数据的均值和标准差):</p>
<pre><code>X_test -= X_meanX_test /= X_std + 1e-8</code></pre>
</li>
</ol>
<p><!--422174--></p>
<div class='yarpp yarpp-related yarpp-related-website yarpp-template-list'>
<!-- YARPP List -->
<h3>相关文章:</h3><ol>
<li><a href=如何从model.predict()结果中获取单个值

  • 当训练集等于测试集时,训练损失与验证损失不匹配
  • Keras: 预期 activation_3 的形状为 (None, 3),但得到的数组形状为 (5708, 1)
  • 为什么平均绝对百分比误差(MAPE)极高?
  • 返回Keras中EarlyStopping回调的轮次数
  • 如何在Tensorflow中实现ReduceLROnPlateau?
  • 使用Keras创建神经网络来乘以两个输入整数
  • 使用Keras创建具有多个输入的NN架构
  • 无法编译用于多类预测的Keras模型
  • 使用Keras编程多输入神经网络架构
  • Related Posts

    Keras Dense层输入未被展平

    这是我的测试代码: from keras import…

    无法将分类变量输入随机森林

    我有10个分类变量和3个数值变量。我在分割后直接将它们…

    如何在Keras中对每个输出应用Sigmoid函数?

    这是我代码的一部分。 model = Sequenti…

    如何选择类概率的最佳阈值?

    我的神经网络输出是一个用于多标签分类的预测类概率表: …

    在Keras中使用深度学习得到不同的结果

    我按照一个教程使用Keras中的深度神经网络进行文本分…

    ‘MatMul’操作的输入’b’类型为float32,与参数’a’的类型float64不匹配

    我写了一个简单的TensorFlow代码,但不断遇到T…

    发表回复

    您的邮箱地址不会被公开。 必填项已用 * 标注