Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使Keras网络不输出所有1_Python_Tensorflow_Machine Learning_Neural Network_Keras - Fatal编程技术网

Python 如何使Keras网络不输出所有1

Python 如何使Keras网络不输出所有1,python,tensorflow,machine-learning,neural-network,keras,Python,Tensorflow,Machine Learning,Neural Network,Keras,我有一堆像这样的图片,有人在玩电子游戏(我在Tkinter中创建的一个简单游戏): 这个游戏的想法是,用户控制屏幕底部的盒子以躲避落下的球(他们只能躲避左右) 我的目标是让神经网络输出播放器在屏幕底部的位置。如果它们完全在左边,则神经网络应该输出一个 0代码/代码>,如果它们在中间,一个 5 ,并且始终是正确的,一个 1 ,以及所有的值之间。 我的图像是300x400像素。我存储数据非常简单。在一个50帧的游戏中,我将每一帧的图像和玩家的位置记录为一个元组。因此,我的结果是一个包含50个元素的

我有一堆像这样的图片,有人在玩电子游戏(我在Tkinter中创建的一个简单游戏):

这个游戏的想法是,用户控制屏幕底部的盒子以躲避落下的球(他们只能躲避左右)

我的目标是让神经网络输出播放器在屏幕底部的位置。如果它们完全在左边,则神经网络应该输出一个<代码> 0代码/代码>,如果它们在中间,一个<代码> 5 ,并且始终是正确的,一个<代码> 1 <代码>,以及所有的值之间。

我的图像是300x400像素。我存储数据非常简单。在一个50帧的游戏中,我将每一帧的图像和玩家的位置记录为一个元组。因此,我的结果是一个包含50个元素的列表,格式为
[(图像,玩家位置),…]
。然后我整理了那张单子

因此,在我的代码中,我尝试创建一个非常基本的前馈网络,它接收图像并输出一个介于0和1之间的值,表示图像底部框的位置。但我的神经网络只输出1s

我应该改变什么,以使其训练并输出接近我想要的值

当然,这是我的代码:

# machine learning code mostly from https://machinelearningmastery.com/tutorial-first-neural-network-python-keras/

from keras.models import Sequential
from keras.layers import Dense
import numpy as np
import pickle

def pil_image_to_np_array(image):
    '''Takes an image and converts it to a numpy array'''
    # from https://stackoverflow.com/a/45208895
    # all my images are black and white, so I only need one channel
    return np.array(image)[:, :, 0:1]

def data_to_training_set(data):
    # split the list in the form [(frame 1 image, frame 1 player position), ...] into [[all images], [all player positions]]
    inputs, outputs = [list(val) for val in zip(*data)]
    for index, image in enumerate(inputs):
        # convert the PIL images into numpy arrays so Keras can process them
        inputs[index] = pil_image_to_np_array(image)
    return (inputs, outputs)

if __name__ == "__main__":
    # fix random seed for reproducibility
    np.random.seed(7)

    # load data
    # data will be in the form [(frame 1 image, frame 1 player position), (frame 2 image, frame 2 player position), ...]
    with open("position_data1.pkl", "rb") as pickled_data:
        data = pickle.load(pickled_data)
    X, Y = data_to_training_set(data)

    # get the width of the images
    width = X[0].shape[1] # == 400
    # convert the player position (a value between 0 and the width of the image) to values between 0 and 1
    for index, output in enumerate(Y):
        Y[index] = output / width

    # flatten the image inputs so they can be passed to a neural network
    for index, inpt in enumerate(X):
        X[index] = np.ndarray.flatten(inpt)

    # keras expects an array (not a list) of image-arrays for input to the neural network
    X = np.array(X)
    Y = np.array(Y)

    # create model
    model = Sequential()
    # my images are 300 x 400 pixels, so each input will be a flattened array of 120000 gray-scale pixel values
    # keep it super simple by not having any deep learning
    model.add(Dense(1, input_dim=120000, activation='sigmoid'))

    # Compile model
    model.compile(loss='mean_squared_error', optimizer='adam')

    # Fit the model
    model.fit(X, Y, epochs=15, batch_size=10)

    # see what the model is doing
    predictions = model.predict(X, batch_size=10)
    print(predictions) # this prints all 1s! # TODO fix
编辑:打印(Y)给了我:


所以它肯定不是全零。

当然,更深层次的模型可能会提供更好的精度,但考虑到图像简单的事实,只有一个隐藏层的非常简单(浅)的模型应该提供中到高的精度。因此,以下是实现这一目标所需的修改:

  • 确保
    X
    Y
    类型为
    float32
    (当前,
    X
    类型为
    uint8
    ):

  • 在训练神经网络时,最好将训练数据标准化。规范化有助于优化过程顺利进行,并加快收敛到解决方案的速度。它还可以进一步防止较大的值导致较大的渐变更新,从而导致破坏。通常,输入数据中每个特征的值应在一个小范围内,其中两个常见范围是
    [-1,1]
    [0,1]
    。因此,为了确保所有值都在
    [-1,1]
    范围内,我们从每个特征中减去其平均值并除以其标准偏差:

    X_mean = X.mean(axis=0)
    X -= X_mean
    X_std = X.std(axis=0)
    X /= X_std + 1e-8  # add a very small constant to prevent division by zero
    
    请注意,我们在这里规范化每个特征(即本例中的每个像素),而不是每个图像。当您想要预测新数据时,即在推理或测试模式下,您需要从测试数据中减去
    X_mean
    ,然后除以
    X_std
    (您应该永远不要从测试数据中减去自己的平均值或除以自己的标准偏差;而是使用训练数据的平均值和标准差):

  • 如果在点1和点2应用更改,您可能会注意到网络不再只预测1或0。相反,它显示出一些微弱的学习迹象,并预测零和一的混合。这不是坏事,但远不是好事,我们有很高的期望!这些预测应该比只混合0和1要好得多。在这里,你应该考虑到(被遗忘的!)学习率。由于考虑到一个相对简单的问题,网络具有相对较多的参数(并且有少量训练数据样本),因此应选择较小的学习速率来平滑梯度更新和学习过程:

    from keras import optimizers
    model.compile(loss='mean_squared_error', optimizer=optimizers.Adam(lr=0.0001))
    
    您会注意到差异:损失值在10个纪元后达到约
    0.01
    。网络不再预测零和一的混合;相反,预测更准确,更接近它们应该达到的水平(即
    Y

  • 别忘了!我们有很高的(合乎逻辑的!)期望。那么,我们如何在不向网络添加任何新层的情况下做得更好呢(显然,我们认为这可能会有所帮助!!)

    4.1。收集更多的培训数据

    4.2。添加权重正则化。常见的是L1和L2正则化(我强烈推荐Keras的创建者弗朗索瓦·乔利特(François Chollet)所写的书中的Jupyter,特别是讨论正则化的那个一本。)

  • 您应该始终以正确、公正的方式评估您的模型。根据训练数据(您用来训练它)对其进行评估,并不能告诉您模型在看不见的(即新的或真实的)数据点上的表现如何(例如,考虑存储或记忆所有训练数据的模型,它将对训练数据进行完美的训练,但它将是一个无用的模型,在新数据上表现不佳)。因此,我们应该有测试和训练数据集:我们在训练数据上训练模型,并在测试中评估模型(即新的)。数据。然而,在提出一个好的模型的过程中,你要做很多实验:例如,你首先改变模型的类型和层数,训练模型,然后在测试数据上评估它,以确保它是好的。然后你改变另一件事,比如学习率,再次训练,然后在测试数据上再次评估它…简而言之,这些调整和评估周期不知何故会导致测试数据的过度拟合。因此,我们需要第三个数据集,称为验证数据(请阅读更多:):

    (实际上,当我们可用的训练数据很少时,将验证和测试数据从整个可用数据中分离出来是浪费的。在这种情况下,如果模型在计算上不昂贵,而不是分离一个称为交叉验证的验证集,则可以在只有很少数据的情况下进行或迭代K倍交叉验证数据样本。)


  • 在写这个答案的时候大约是凌晨4点,我感到很困,但我想再提一件与你的问题没有直接关系的事情:通过使用Numpy库
    X_test -= X_mean
    X_test /= X_std + 1e-8
    
    from keras import optimizers
    model.compile(loss='mean_squared_error', optimizer=optimizers.Adam(lr=0.0001))
    
    # first shuffle the data to make sure it isn't in any particular order
    indices = np.arange(X.shape[0])
    np.random.shuffle(indices)
    X = X[indices]
    Y = Y[indices]
    
    # you have 200 images
    # we select 100 images for training,
    # 50 images for validation and 50 images for test data
    X_train = X[:100]
    X_val = X[100:150]
    X_test = X[150:]
    Y_train = Y[:100]
    Y_val = Y[100:150]
    Y_test = Y[150:]
    
    # train and tune the model 
    # you can attempt train and tune the model multiple times,
    # each time with different architecture, hyper-parameters, etc.
    model.fit(X_train, Y_train, epochs=15, batch_size=10, validation_data=(X_val, Y_val))
    
    # only and only after completing the tuning of your model
    # you should evaluate it on the test data for just one time
    model.evaluate(X_test, Y_test)
    
    # after you are satisfied with the model performance
    # and want to deploy your model for production use (i.e. real world)
    # you can train your model once more on the whole data available
    # with the best configurations you have found out in your tunings
    model.fit(X, Y, epochs=15, batch_size=10)
    
    # machine learning code mostly from https://machinelearningmastery.com/tutorial-first-neural-network-python-keras/
    
    from keras.models import Sequential
    from keras.layers import Dense
    import numpy as np
    import pickle
    
    def pil_image_to_np_array(image):
        '''Takes an image and converts it to a numpy array'''
        # from https://stackoverflow.com/a/45208895
        # all my images are black and white, so I only need one channel
        return np.array(image)[:, :, 0]
    
    def data_to_training_set(data):
        # split the list in the form [(frame 1 image, frame 1 player position), ...] into [[all images], [all player positions]]
        inputs, outputs = zip(*data)
        inputs = [pil_image_to_np_array(image) for image in inputs]
        inputs = np.array(inputs, dtype=np.float32)
        outputs = np.array(outputs, dtype=np.float32)
        return (inputs, outputs)
    
    if __name__ == "__main__":
        # fix random seed for reproducibility
        np.random.seed(7)
    
        # load data
        # data will be in the form [(frame 1 image, frame 1 player position), (frame 2 image, frame 2 player position), ...]
        with open("position_data1.pkl", "rb") as pickled_data:
            data = pickle.load(pickled_data)
        X, Y = data_to_training_set(data)
    
        # get the width of the images
        width = X.shape[2] # == 400
        # convert the player position (a value between 0 and the width of the image) to values between 0 and 1
        Y /= width
    
        # flatten the image inputs so they can be passed to a neural network
        X = np.reshape(X, (X.shape[0], -1))
    
        # create model
        model = Sequential()
        # my images are 300 x 400 pixels, so each input will be a flattened array of 120000 gray-scale pixel values
        # keep it super simple by not having any deep learning
        model.add(Dense(1, input_dim=120000, activation='sigmoid'))
    
        # Compile model
        model.compile(loss='mean_squared_error', optimizer='adam')
    
        # Fit the model
        model.fit(X, Y, epochs=15, batch_size=10)
    
        # see what the model is doing
        predictions = model.predict(X, batch_size=10)
        print(predictions) # this prints all 1s! # TODO fix