CNTK从入门到深入研究(5) - Data Reader & Writer

前言

Data Reader是CNTK进行机器学习的最基础部分,一切算法都已以数据为根本的。所以对于数据的解析以及预处理则显得更加重要,数据的来源不同,则解析方式也不同。本文将针对CNTK官方提供出来的一些Data Reader的使用方式进行讲解。

而CNTK中本来是没有Writer的,但是与Reader相对应也需要一个结果的输出。所以在本文中也会针对于输出结果的方式进行讲解。

Data Reader

reader = [
    readerType = "UCIFastReader"
    file = "$DataDir$/mnist_train.txt"
    features = [
        dim = 784
        start = 1
    ]
    labels = [
        dim = 1
        start = 0
        labelDim = 10
        labelMappingFile = "$DataDir$/mnistlabels.txt"
    ]
]

Data Reader其实就是针对某种特殊数据的读取器,但是数据不同则解析的方式也不同。CNTK里面提供了4种常用的Data Reader。

- UCI Fast Reader
- HTKMLF Reader
- LM sequence reader
- LU sequence reader

4种Reader中,虽然都是针对于某种特殊的数据格式,但是其中的UCIFastReader也可以用于csv文件格式的加载。DataReader其本质功能只是解析数据(也许包括数据的预处理),CNTK所提供的Reader并不一定满足实际生产过程的需要,但如果目前所提供的Reader不满足需要则可以考虑自己实现一个继承自IDataReader接口的Reader即可。

UCI Fast Reader

UCIFastReader用于读取基于text的UCI机器学习库中的数据格式,针对于数据可以去UCI Machine Learning Repository进行下载(http://archive.ics.uci.edu/ml/)。

这种数据一般每个观测包含参数和标签两种,其中标签(label)一般不是出现在观测的前面要不然就是后面。通过设置readerType为UCIFastReader来指定使用UCI Fast Reader。

reader = [
    readerType = "UCIFastReader"
    file = "c:\cntk\data\mnist\mnist_train.txt"
    features = [
        dim = 784
        start = 1
    ]
    labels = [
        dim = 1
        start = 0
        labelDim = 10
        labelMappingFile = "c:\cntk\data\mnist\mnistlabels.txt"
    ]
]

在UCIFastReader中,首先应指定UCI数据格式中,哪些列是观测值(features),哪些列是标签值(labels)。这些可以通过features和labels块来指定。使用UCIFastReader除了设定readerType、features、以及labels以外,还是需要指定一些指定Reader的特有参数。

  • file:file参数用于指定数据文件的位置(就是数据文件)。
  • dim:该参数用于指定输入的值的维度。UCI提供的数据文件中,每一列都是一个维度。这里的维度不仅是用于观测值的维度,还用于指定标签值的维度。应将其写入相应的features或者是labels的数据块中。
  • start:UCI中观测值都是以列的形式组织的,列中不仅包括观测值还包括了标签值,所以在指定相应的维度的时候,还应指定从哪个列开始是指定的观测或者标签。该参数应同dim参数一同出现在指定的块中。
  • labelDim:该参数用于指定可能的标签值的数量。
  • labelMappingFile:参数用于指定一个文件路径,该文件用于加载一个标签值到标签符号的映射。labelMappingFile其实是一本字典用于作为标签值和标签符号之间的映射。该参数不仅用于训练和测试,它也用于测试,并且这三种操作一般公用一个文件。所以应该将该参数设定的位置适当的放在块的外面以使其能被共享。
  • customDelimiter:默认情况下每个观测使用空格作为数据的分割,但是当文件中的分隔符不同时,可以通过设定该参数来制定。UCIFastReader虽然特定的用于读取UCI所提供的数据。但是该格式通csv很相近。所以可以指定customDelimiter为“,”来读取csv格式文件。
  • customDecimalPoint:默认情况下,很多语言文化总使用“.”作为小数点的符号,但是一些欧洲的文化中小数点是“,”。该参数提供一个接口去设定解析数据时遇到小数情况下,识别小数点所使用的符号。
  • labelType:用于指定标签的类型,默认是“Category”,标示是分类,其需要设定labelMappingFile共同使用,可以做数值通标签符号的映射。也可已设定为“Regression”来直接显示标签的值而不做任何映射。也可指定为“None”来指明不适用任何标签。

UCI Fast Reader也提供了一些其他参数如下:

  • traceLevel:用于指定输出调试信息的详细程度。可设定为0或者为1,默认是0(不输出调试信息)。
  • prefetch:是否开启预先读取功能(可设定为true或者是false)。预取功能是使用一个异步线程去预先读取数据。默认为false。
  • randomize:该参数用于设定数据的读取顺序,可设定为none或者为auto。none代表使用线性的顺序一条一条的去读取观测。auto代表使用随机顺序去读取观测。默认为none。
  • minibatchMode:该参数可以设定为partial或者是一个整数,设定为parial的mini-Batch可以被接受。当设定为一个整数的时候,则训练的数据必须是mini-Batch大小的整数倍。

Data Writer

CNTK中其实没有DataWriter,所谓的Writer只是将eval或者test的结果输出至文件。更加严谨地说应该是将相关Node的结果值输出至文件或者stdout流。

之前我们介绍过每个任务块中的action可以赋值为train、test、eval等,其还可以被复制为write。
当需要将数据输出时,则需要设置action为write。下面是出现在Simple2d中的例子,

Simple_Demo_Output=[
    action = "write"

    # Parameter values for the reader
    reader = [
        readerType = "UCIFastReader"
        file = "$DataDir$/SimpleDataTest.txt"
        randomize = "none"

        features = [
            dim = 2
            start = 0 ] labels = [ start = 2 dim = 1 labelDim = 2 labelMappingFile = "$DataDir$/SimpleMapping.txt" ] ] outputNodeNames = PosteriorProb : labels # Select the nodes to print. If this is not given, the nodes tagged as "output" are printed instead. outputPath = "$OutputDir$/SimpleOutput" # Path to write to. ".NODENAME" will be appended. #outputPath = "-" # As an alternative, this prints to stdout. # extra formatting options # This is configured to print the classified and ground-truth labels. # To write out the actual posterior probabilities, comment out this section. format = [ type = "category" # This finds the highest-scoring entry and prints its index. labelMappingFile = "$DataDir$/SimpleMapping.txt" # Specifying this as well will translate the index into a string. sequenceEpilogue = "\t// %s\n" # Append this on every line, %s = node name. Useful when printing to stdout. # How to implement simple error counting with this (cd into $OutputDir$ first): # grep PosteriorProb SimpleOutput.PosteriorProb | awk '{print $1}' > P # grep labels SimpleOutput.labels | awk '{print $1}' > L # diff L P | grep "<" | wc -l # wc -l P # The ratio of the two numbers gives the same error rate as ErrorPrediction/Sample in the log. ] ] 

在设置action=write后,其执行过程类似于eval或者是test。也是一个测试过程,只是输出不同而已。仍需要指定一个Reader块。
除Reader块外,其他笔者所知道的参数如下:

  • outputNodeNames 参数用于指定都需要输出哪些节点值的名字。该参数未指定的时候,则使用最后的output的节点。这里可以用冒号来指定多个节点的名字。
  • outputPath 参数用于指定输出的路径及文件的名称,这里的文件名只是名称,文件将会自动被CNTK添加节点名称作为拓展名,例如output.label其中前面的output是名称,而.label是被自动添加进去的。该节点还有另外一种用法是赋值为”-“,这种方式可以控制其输出至stdout,通过对标准输出输出流的重定向,可以被其他进程所捕获进而与其他系统连用。
  • format 数据块主要针对于输出内容的格式进行控制。
    • type 参数用于控制输出的内容是枚举值的形式还是数值形式。可选的值目前可以为real(直接将节点的值输出),或者为category(需要map文件,将值map到唯一的一个枚举)。
    • labelMappingFile 参数用于指定map文件的位置,该参数可以设置在块的外面,这样就可以被更多块所公用。(当type为category的时候,需要配置该参数)
    • sequenceEpilogue 参数用于设置每行输出后添加内容的格式,所设置的内容将会被添加到每个样本的输出上。可以通过此功能添加一些标签,例如\t// %s\n,其中的\t是添加一个tab符号,然后添加一个节点的名称然后\n是换行。

在Simple2d的这个例子中,就是通过设定write来输出内容至文件的,其将最后的label节点以类型的方式进行输出。

总结

UCI Fast Reader只是其中的一种Reader,特定的Reader在不同领域的使用中不尽相同,笔者虽尝试过研究其他的Reader但是总是没有研究透彻,索性也先不写了。

最后,Reader是可以自定义实现的,所以真的涉及到自己具体的项目或者任务的时候,并不一定非要局限于CNTK所提供的已知Reader,完全可以自己实现,Reader其实是一个继承自IReader的接口的类,将其抽象或者是虚函数实现了即可。

CNTK的入门可能到此为止,最近时间忙,回家基本倒头睡觉,研究的较少。未来我可能会对CNTK开始深入研究,如果研究出来了一些结果,我将会继续更新本系列文章,当然,更加欢迎朋友们给我提各种问题让我有一个具体的研究方向,进行深入的交流。

下一章节为常见问题答疑,我会收集大家的问题,并更新。

你可能感兴趣的:(人工智能,reader,DNN,深度学习,CNTK)