2

我成功执行了 google cloud ml 在线教程的所有步骤。

但是由于本教程中使用的数据集已经是 TFRecord,我不太了解如何将我的 numpy 数据集转换为 TFRecord 数据集。

然后,我尝试使用与官方 convert_to_records.py 相比稍加修改的代码来创建我的 TFRecord 。我的理解是,我们只能将原始变量转换为 TFRecord,这就是使用将浮点列表转换为字节的技巧的原因。然后我必须在某个地方将我的字符串转换回浮点列表。因此,我尝试使用修改后的脚本 model.py 中的第 97 行或第 98 行来执行此任务。

不幸的是,这些尝试都没有奏效。我总是收到以下错误消息:

ValueError: rank of shape must be at least 2 not: 1

这是因为我的变量特征的形状是 (batch_size,) 而不是 (batch_size, IMAGE_PIXELS)。但我不明白为什么。

我是在尝试以错误的方式启动 google-cloud-ml 还是有更多参数需要调整?

4

2 回答 2

3

在你的 model.py 中分析 read_data_sets.py 的输出和 parse_example 操作的输出可能会有所帮助

read_data_sets 产生什么

正如您所指出的,read_data_sets为每个图像创建 numpy 数组。它们具有高度 x 宽度 x 通道的形状 [28, 28, 1](图像是单色的),并且在您对 read_data_sets 的原始调用中,您指定要将图像数据作为 uint8 数组。当您在 uint8 numpy 数组上调用tostring时,形状信息将被丢弃,并且由于每个 uint8 都是一个字节,因此您最终会得到一个长度为 784 的字节字符串,其中原始 28x28x1 numpy 数组中的每个像素都有一个条目(行主要)命令。然后将其作为 a 存储bytes_list在结果中tf.train.Example

回顾一下,该features键下的特征图中的每个条目都有一个字节列表,其中只有一个条目。该条目是一个长度为 784 的字符串,其中字符串中的每个“字符”都是一个介于 0-255 之间的值,表示原始 28x28 图像中某个点的单色像素值。以下是tf.train.ExamplePython 打印的示例实例:

features {
  feature {
    key: "features"
    value {
      bytes_list {
        value: "\000\000\257..."
      }
    }
  }
  feature {
    key: "labels"
    value {
      int64_list {
        value: 10
      }
    }
  }
}

parse_example 期望和返回什么

tf.parse_example接受一个tf.string对象向量作为输入。这些对象是序列化的tf.train.Example对象。在您的代码中,util.read_examples正是如此。

另一个论点tf.parse_example是示例的模式。如前所述,features您的示例中的条目是tf.string如上定义的。作为参考,您的代码具有:

def parse_examples(examples):
  feature_map = {
      'labels': tf.FixedLenFeature(
          shape=[], dtype=tf.int64, default_value=[-1]),
      'features': tf.FixedLenFeature(
          shape=[], dtype=tf.string),
  }
  return tf.parse_example(examples, features=feature_map)

与您收到的错误消息相关的有趣的事情是形状参数。该形状参数指定单个实例的形状,在这种情况下,通过指定shape=[]您说每个图像是一个等级为 0 的字符串,也就是说,一个普通的旧字符串(即,不是向量,不是矩阵等)。这要求bytes_list只有一个元素。这正是您存储featurestf.train.Example.

尽管该shape属性是指单个实例的形状,但字段的输出tf.parse_examplefeatures是整批示例。这可能有点令人困惑。因此,虽然每个单独的示例都有一个字符串 ( shape=[]),但批处理是字符串 ( shape=[batch_size]) 的向量。

使用图像

将图像数据放在字符串中并不是很有用;我们需要将其转换回数字数据。执行此操作的 TensorFlow 操作是tf.decode_raw(Jeremy Lewi解释了为什么tf.string_to_number在这里不起作用):

image_bytes = tf.decode_raw(parsed['features'], out_type=tf.uint8)
image_data = tf.cast(image_bytes, tf.float32)

(请务必设置out_type=tf.uint8,因为那是在 中输出的数据类型read_data_sets)。通常,您会希望将结果转换为tf.float32. 有时,重塑张量以恢复原始形状甚至很有用,例如,

# New shape is [batch_size, height, width, channels]. We use
# -1 as the first dimension in case batches are variable size.
image_data = tf.reshape(image_data, [-1, 28, 28, 1])

(注意:您的代码中可能不需要它)。

read_data_sets或者,您可以通过调用with dtype=tf.float32(默认值)将数据存储为 tf.float32 。然后您可以tf.train.Example按照 Jeremy Lewi 的解释构建您的,他还提供了解析此类示例的代码。但是,在这种情况下,形状会有所不同。现在每个实例的形状(如 FixedLenFeature 中的形状所示)为,输出中条目IMAGE_PIXELS的形状为。featurestf.parsed_example[batch_size, IMAGE_PIXELS]

uint8和之间的折衷float32当然是磁盘上的数据大约是后者的四倍,但是您避免了前者所需的额外转换。对于没有太多数据的 MNIST,直接处理浮点数据的额外清晰度可能值得额外的空间。

于 2016-10-24T13:46:23.823 回答
3

该错误表明预期为 2 级(矩阵),但该值实际上是 1 级(向量)。我怀疑这是因为 np.tostring() 返回单个字符串而不是字符串列表。

我认为这有点切题,因为我认为您的浮点到字符串和字符串到浮点的转换不一致。您可以使用 numpy 的内置 tostring() 方法将浮点数转换为字符串。返回数据的字节表示:即

import numpy as np
x = np.array([1.0, 2.0])
print x.tostring()

退货

�?@

并不是

['1.0', '2.0']

后者是 tf.string_to_number 所期望的。

您可以使浮点到字符串和字符串到浮点的转换保持一致,但我认为更好的解决方案是将数据表示为浮点数。例如:

def _int64_feature(value):
  return tf.train.Feature(int64_list=tf.train.Int64List(value=value))

def _float_feature(value):
  return tf.train.Feature(float_list=tf.train.FloatList(value=value))

e = tf.train.Example(features=tf.train.Features(feature={
          'labels': _int64_feature([10]),
          'features': _float_feature([100.0, 200, ....])}))

feature_map = {
      'labels': tf.FixedLenFeature(
          shape=[1], dtype=tf.int64, default_value=[-1]),
      'features': tf.FixedLenFeature(
          shape=[NUM_PIXELS], dtype=tf.float32),
}
result = tf.parse_example([e.SerializeToString()], features=feature_map)

Feature proto允许将 float32 存储在 float_list 中。如果您使用的是 float64,则只需将浮点数转换为字节。您的数据是 float32 ,因此没有必要。

于 2016-10-24T13:46:50.103 回答