为什么keras中的reshape函数不能改变维数
Why can the reshape function in keras not change the number of dimensions
我正在尝试使用 Keras 中的神经网络制作国际象棋引擎。我想输出基于训练游戏的可能策略的预测,我正在使用 73x8x8 输出来做到这一点(棋盘上的每个位置乘以 73 种不同的可能移动,8 个方向 * "queen moves" 的 7 个正方形, 8 个骑士移动,3 个提升(任何其他提升都是女王提升)乘以 3 个方向)。
然而,我网络中的最后一层是密集层,它输出一维 4672 长的输出。我正在尝试通过重塑层将其重塑为更易于使用的东西。
但是,它给了我这个错误:ValueError:检查目标时出错:预期 reshape_1 有 4 个维度,但得到形状为 (2, 1)
的数组
我看过这个问题: 但答案似乎不适用于密集层,因为它们没有 "return sequences" 输入。
这是我的代码:
from keras.models import Model, Input
from keras.layers import Conv2D, Dense, Flatten, Reshape
from keras.optimizers import SGD
import numpy
from copy import deepcopy
class NeuralNetwork:
def __init__(self):
self.network = Model()
self.create_network()
def create_network(self):
input = Input((13, 8, 8))
output = Conv2D(256, (3, 3), padding='same')(input)
policy_head_output = Conv2D(2, (1, 1))(output)
policy_head_output = Flatten()(policy_head_output)
policy_head_output = Dense(4672, name='policy_output')(policy_head_output)
policy_head_output = Reshape((73, 8, 8), input_shape=(4672,))(policy_head_output)
value_head_output = Conv2D(1, (1, 1))(output)
value_head_output = Dense(256)(value_head_output)
value_head_output = Flatten()(value_head_output)
value_head_output = Dense(1, name="value_output")(value_head_output)
self.network = Model(outputs=[value_head_output, policy_head_output], inputs=input)
def train_network(self, input_training_data, labels):
sgd = SGD(0.2, 0.9)
self.network.compile(sgd, 'categorical_crossentropy', metrics=['accuracy'])
self.network.fit(input_training_data, [labels[0], labels[1]])
self.network.save("Neural Net 1")
def make_training_data():
training_data = []
labels = []
for i in range(6):
training_data.append(make_image())
labels.append(make_label_image())
return training_data, labels
def make_image():
data = []
for i in range(13):
blank_board = []
for j in range(8):
a = []
for k in range(8):
a.append(0)
blank_board.append(a)
data.append(blank_board)
return data
def make_label_image():
policy_logits = []
blank_board = []
for i in range(8):
a = []
for j in range(8):
a.append(0)
blank_board.append(a)
for i in range(73):
policy_logits.append(deepcopy(blank_board))
return [policy_logits, [0]]
def main():
input_training_data, output_training_data = make_training_data()
neural_net = NeuralNetwork()
input_training_data = numpy.array(input_training_data)
output_training_data = numpy.array(output_training_data)
neural_net.train_network(input_training_data, output_training_data)
main()
有人可以解释一下吗:
发生了什么事
我能做些什么来解决它
您的方法有些问题。
1。您的 output/target 数据
所以您正在创建一个包含两个元素(board、label)的列表对象。板是 73x8x8
,其中标签是 0/1
。这会产生不一致的尺寸。当您将这个参差不齐的结构转换为 numpy 数组时,就会发生这种情况。
a = [[0,1,2,3],[0]]
arr = np.array(a)
print(arr)
# => [list([0, 1, 2, 3]) list([0])]
然后data slicing indexing 转得很奇怪,我就不去了。因此,首先要分离您的数据,以便 make_training_data
中返回的每个元素都具有一致的尺寸。所以这里我们分别返回了 input_image、output_board_image 和 output_labels。
def make_training_data():
training_data = []
labels = []
board_output = []
for i in range(6):
training_data.append(make_image())
board, lbl = make_label_image()
labels.append(lbl)
board_output.append(board)
return training_data, board_output, labels
并且在 main()
中,它变为
input_training_data, output_training_board, output_training_labels = make_training_data()
input_training_data = np.array(input_training_data)
output_training_board = np.array(output_training_board)
output_training_labels = np.array(output_training_labels)
错误
所以你得到了错误
ValueError: Error when checking target: expected reshape_1 to have 4 dimensions, but got array with shape (2, 1)
嗯,很简单,您在执行 model.fit()
时以错误的顺序给出了输出。换句话说,你的模型说,
outputs=[value_head_output, policy_head_output]
你的 make_labels()
说,
[policy_logits, [0]]
恰恰相反。你可怜的模型正试图将标签重塑为 4 维结构。这就是它抱怨的原因。应该是,
neural_net.train_network(input_training_data, [output_training_labels, output_training_board])
即使您只纠正这个(没有 make_training_data()),您也可能无法正常工作,因为您的 numpy 结构(第一部分)中存在所有这些不一致之处。
损失函数
这是关于你的损失函数。您有一个具有单个输出的 Dense
层,并且您正在使用 categorical_crossentropy
用于 "categorical" 输出。你应该在这里使用 binary_crossentropy
,因为你只有一个索引。
此外,如果您希望多个输出有多个损失,请执行以下操作。
self.network.compile(sgd, ['binary_crossentropy', 'mean_squared_error'], metrics=['accuracy'])
这只是一个例子。如果你愿意,你也可以对两个输入有相同的损失。
我正在尝试使用 Keras 中的神经网络制作国际象棋引擎。我想输出基于训练游戏的可能策略的预测,我正在使用 73x8x8 输出来做到这一点(棋盘上的每个位置乘以 73 种不同的可能移动,8 个方向 * "queen moves" 的 7 个正方形, 8 个骑士移动,3 个提升(任何其他提升都是女王提升)乘以 3 个方向)。 然而,我网络中的最后一层是密集层,它输出一维 4672 长的输出。我正在尝试通过重塑层将其重塑为更易于使用的东西。
但是,它给了我这个错误:ValueError:检查目标时出错:预期 reshape_1 有 4 个维度,但得到形状为 (2, 1)
的数组我看过这个问题:
这是我的代码:
from keras.models import Model, Input
from keras.layers import Conv2D, Dense, Flatten, Reshape
from keras.optimizers import SGD
import numpy
from copy import deepcopy
class NeuralNetwork:
def __init__(self):
self.network = Model()
self.create_network()
def create_network(self):
input = Input((13, 8, 8))
output = Conv2D(256, (3, 3), padding='same')(input)
policy_head_output = Conv2D(2, (1, 1))(output)
policy_head_output = Flatten()(policy_head_output)
policy_head_output = Dense(4672, name='policy_output')(policy_head_output)
policy_head_output = Reshape((73, 8, 8), input_shape=(4672,))(policy_head_output)
value_head_output = Conv2D(1, (1, 1))(output)
value_head_output = Dense(256)(value_head_output)
value_head_output = Flatten()(value_head_output)
value_head_output = Dense(1, name="value_output")(value_head_output)
self.network = Model(outputs=[value_head_output, policy_head_output], inputs=input)
def train_network(self, input_training_data, labels):
sgd = SGD(0.2, 0.9)
self.network.compile(sgd, 'categorical_crossentropy', metrics=['accuracy'])
self.network.fit(input_training_data, [labels[0], labels[1]])
self.network.save("Neural Net 1")
def make_training_data():
training_data = []
labels = []
for i in range(6):
training_data.append(make_image())
labels.append(make_label_image())
return training_data, labels
def make_image():
data = []
for i in range(13):
blank_board = []
for j in range(8):
a = []
for k in range(8):
a.append(0)
blank_board.append(a)
data.append(blank_board)
return data
def make_label_image():
policy_logits = []
blank_board = []
for i in range(8):
a = []
for j in range(8):
a.append(0)
blank_board.append(a)
for i in range(73):
policy_logits.append(deepcopy(blank_board))
return [policy_logits, [0]]
def main():
input_training_data, output_training_data = make_training_data()
neural_net = NeuralNetwork()
input_training_data = numpy.array(input_training_data)
output_training_data = numpy.array(output_training_data)
neural_net.train_network(input_training_data, output_training_data)
main()
有人可以解释一下吗:
发生了什么事
我能做些什么来解决它
您的方法有些问题。
1。您的 output/target 数据
所以您正在创建一个包含两个元素(board、label)的列表对象。板是 73x8x8
,其中标签是 0/1
。这会产生不一致的尺寸。当您将这个参差不齐的结构转换为 numpy 数组时,就会发生这种情况。
a = [[0,1,2,3],[0]]
arr = np.array(a)
print(arr)
# => [list([0, 1, 2, 3]) list([0])]
然后data slicing indexing 转得很奇怪,我就不去了。因此,首先要分离您的数据,以便 make_training_data
中返回的每个元素都具有一致的尺寸。所以这里我们分别返回了 input_image、output_board_image 和 output_labels。
def make_training_data():
training_data = []
labels = []
board_output = []
for i in range(6):
training_data.append(make_image())
board, lbl = make_label_image()
labels.append(lbl)
board_output.append(board)
return training_data, board_output, labels
并且在 main()
中,它变为
input_training_data, output_training_board, output_training_labels = make_training_data()
input_training_data = np.array(input_training_data)
output_training_board = np.array(output_training_board)
output_training_labels = np.array(output_training_labels)
错误
所以你得到了错误
ValueError: Error when checking target: expected reshape_1 to have 4 dimensions, but got array with shape (2, 1)
嗯,很简单,您在执行 model.fit()
时以错误的顺序给出了输出。换句话说,你的模型说,
outputs=[value_head_output, policy_head_output]
你的 make_labels()
说,
[policy_logits, [0]]
恰恰相反。你可怜的模型正试图将标签重塑为 4 维结构。这就是它抱怨的原因。应该是,
neural_net.train_network(input_training_data, [output_training_labels, output_training_board])
即使您只纠正这个(没有 make_training_data()),您也可能无法正常工作,因为您的 numpy 结构(第一部分)中存在所有这些不一致之处。
损失函数
这是关于你的损失函数。您有一个具有单个输出的 Dense
层,并且您正在使用 categorical_crossentropy
用于 "categorical" 输出。你应该在这里使用 binary_crossentropy
,因为你只有一个索引。
此外,如果您希望多个输出有多个损失,请执行以下操作。
self.network.compile(sgd, ['binary_crossentropy', 'mean_squared_error'], metrics=['accuracy'])
这只是一个例子。如果你愿意,你也可以对两个输入有相同的损失。