【问题标题】:Data too complicated for model to learn?数据太复杂,模型无法学习?
【发布时间】:2019-10-25 12:42:29
【问题描述】:

目前,我正在为 RTS 游戏(确切地说是魔兽争霸 III)开发一种 AI。我正在使用 TFlearn 来教模型如何自己玩游戏。我正在以这种方式收集数据:

[image array in grayscale] = [x-axis position of action, y-axis position of action, tokenized type of action]

所以,实际数据看起来像这样:

[[[36]
  [39]
  [38]
  ...
  [12]
  [48]
  [65]]

 [[30]
  [48]
  [ 0]
  ...
  [34]
  [49]
  [ 8]]

 [[28]
  [29]
  [23]
  ...
  [93]
  [38]
  [53]]

 ...

 [[ 0]
  [ 0]
  [ 0]
  ...
  [ 0]
  [ 0]
  [ 4]]

 [[ 0]
  [ 0]
  [ 0]
  ...
  [ 0]
  [ 0]
  [ 0]]

 [[ 0]
  [ 0]
  [ 0]
  ...
  [60]
  [19]
  [43]]]=[1, 1, 35]

这意味着,如果图像阵列上显示的情况(灰度),鼠标应该设置在 1-x 和 1-y 位置和正确的动作(鼠标动作或键盘按下动作,取决于未标记的值)应该被取走。

不过,我对正确的模型拟合有疑问。我有 30000 帧,模型学习正确似乎太少了,因为在拟合模型后进行预测的情况下,它总是给出相同的输出:

[1,1,0]

我几乎可以肯定,这是因为要学习的拍摄帧数很少。我正在尝试学习一个模型,大约 60 个动作和屏幕上的变化并不太显着,所以这组数据真的很难。尽管如此,我想问在这种情况下是否有其他方法可以改善模型的学习。我试过了:

  1. 降低学习率(至 1e^5)
  2. 模型配置上的不同激活方法/优化器/层数
  3. 更改要学习的动作数量(例如,我已经从学习池中剔除了移动动作)

这就是我获取数据的方式:

import os
import cv2
import mss
import pyWinhook as pyHook
import pythoncom
import numpy as np


def get_screen():
    with mss.mss() as sct:
        screen = np.array(sct.grab((0, 0, 1366, 768)))
    screen = cv2.cvtColor(screen, cv2.COLOR_BGR2GRAY)
    screen = cv2.resize(screen, (136, 76))
    return screen

def get_data():
    # file names for training data arrays
    file_name = 'training_data.npy'
    copy_file_name = 'training_data_copy.npy'

    # deciding if previous file with data is saved. If yes, it is opened. If not it's created
    if os.path.isfile(file_name):
        print('File exists, loading previous data!')
        print(os.path.realpath(file_name))
        training_data = list(np.load(file_name, allow_pickle=True))
        np.save(copy_file_name, training_data)
    else:
        print('File does not exist, starting fresh!')
        training_data = []
    # saving data after acquiring 2500 sets of inputs and screenshots
    def save_data(screen, output):
        training_data.append([screen, output])
        if len(training_data) % 2500 == 0:
            print(len(training_data))
            np.save(file_name, training_data)
        print("Frames taken: " + str(len(training_data)))
        index = len(training_data) - 1
        print(training_data[index])

    # getting inputs and screen on mouse event
    def OnMouseEvent(event):
        action = event.MessageName
        screen = get_screen()
        output = [event.Position, 0]
        if action == 'mouse move':
            output[1] = 'move'
        elif action == 'mouse left down':
            output[1] = 'left'
        elif action == 'mouse right down':
            output[1] = 'right'
        save_data(screen, output)
        return True

    # getting inputs and screen on keyboard event
    def OnKeyboardEvent(event):
        if event == 'Delete':
            np.save(file_name, training_data)
            print("Save and exit")
            exit()
        screen = get_screen()
        output = [(1,1), event.Key]
        ctrl_pressed = pyHook.GetKeyState(pyHook.HookConstants.VKeyToID('VK_CONTROL'))
        shift_pressed = pyHook.GetKeyState(pyHook.HookConstants.VKeyToID('VK_SHIFT'))
        try:
            if ctrl_pressed and int(pyHook.HookConstants.IDToName(event.KeyID)) in range(10):
                output[1] = 'bind' + event.Key
        except ValueError:
            pass
        try:
            if shift_pressed and int(pyHook.HookConstants.IDToName(event.KeyID)) in range(10):
                output[1] = 'add' + event.Key
        except ValueError:
            pass
        save_data(screen, output)
        return True

    # create a hook manager
    hm = pyHook.HookManager()
    # watch for all mouse events
    hm.MouseLeftDown = OnMouseEvent
    hm.MouseRightDown = OnMouseEvent
    #hm.MouseMove = OnMouseEvent
    hm.KeyUp = OnKeyboardEvent
    # set the hook
    hm.HookMouse()
    hm.HookKeyboard()
    # wait forever
    try:
        pythoncom.PumpMessages()
    except KeyboardInterrupt:
        pass

    # looping getting data
    while True:
        pass

这是我的模型配置:

import tflearn
from tflearn.layers.conv import conv_2d, max_pool_2d
from tflearn.layers.core import input_data, dropout, fully_connected
from tflearn.layers.estimator import regression
from tflearn.layers.normalization import local_response_normalization
import tensorflow as tf

def trainingmodel(width, height, lr):
    network = input_data(shape=[None, width, height, 1], name='input')
    network = conv_2d(network, 96, 11, strides=4, activation='relu')
    network = max_pool_2d(network, 3, strides=2)
    network = local_response_normalization(network)
    network = conv_2d(network, 256, 5, activation='relu')
    network = max_pool_2d(network, 3, strides=2)
    network = local_response_normalization(network)
    network = conv_2d(network, 384, 3, activation='relu')
    network = conv_2d(network, 256, 3, activation='relu')
    network = max_pool_2d(network, 3, strides=2)
    network = local_response_normalization(network)
    network = fully_connected(network, 4096, activation='tanh')
    network = dropout(network, 0.25)
    network = fully_connected(network, 3, activation='softmax')
    sgd = tflearn.optimizers.SGD(learning_rate=0.01, lr_decay=0.96, decay_step=100)
    network = regression(network, optimizer='adam',
                         loss='categorical_crossentropy',
                         learning_rate=lr, name='targets')
    model = tflearn.DNN(network, checkpoint_path='model_training_model',
                        max_checkpoints=1, tensorboard_verbose=2, tensorboard_dir='log')

    return model

【问题讨论】:

  • 作为一个非常小的注释,您应该规范化输入数据。使用 [-1.0, 1.0] 或 [0.0, 1.0] 将比使用 [0, 255] 容易得多。 (但可能还是太难了。)

标签: python tensorflow machine-learning tflearn


【解决方案1】:

我不确定您是否完全可以使用图片来尝试执行此操作。我已经看到这适用于超级马里奥兄弟,但 WC3 是一个更复杂的场景。您需要每个角色的每一个动作的图片,以便模型得出正确的结论。

您的模型可能无法处理未向其展示的情况(以类似方式)。您可以尝试使用模板匹配来提取字符的动作,并在 (x, y) 位置而不是使用 CNN 的图像上教模型。

【讨论】:

  • 假设我只想将其限制为一场比赛。我有点意识到这很复杂,但教模型还是太过分了?
  • 我会说这太复杂了。该模型必须了解游戏如何运作的基本概念。这对于国际象棋或跳棋来说要容易得多,但在 WC3 中,模型还需要学习很多其他的东西(许多不同的角色、他们的好处、背景景观)。而且你的模型必须知道图像的时间序列(循环神经网络)。
  • 您可以轻松开始,看看它会将您引向何方。取一个字符并在屏幕上移动它。然后使用这些框架过度拟合您的模型。一旦成功(应该),您可能会了解让模型播放它是多么困难。以及您需要的训练数据量。
  • 当您为网络设计层时,您对层的大小和顺序有何想法?
  • 老实说,这是一个反复试验的过程。我的出发点是取自 GTA 5 自驾教程的图层设置。然后,为了与过度拟合作斗争,我逐层删除,然后放弃配置它们,当它没有给出任何结果来尝试知道它是否可能时。
猜你喜欢
  • 2019-09-15
  • 1970-01-01
  • 1970-01-01
  • 2020-07-19
  • 2013-10-14
  • 1970-01-01
  • 1970-01-01
  • 2017-09-21
  • 2019-09-20
相关资源
最近更新 更多