机器学习是时下非常流行的话题,而Tensorflow是机器学习中最有名的工具包。TensorflowSharp是Tensorflow的C#语言表述。本文会对TensorflowSharp的使用进行一个简单的介绍。
本文会先介绍Tensorflow的一些基本概念,然后实现一些基本操作例如数字相加等运算。然后,实现求两个点(x1,y1)和(x2,y2)的距离。最后,通过这些前置基础和一些C#代码,实现使用KNN方法识别MNIST手写数字集合(前半部分)。阅读本文绝对不需要任何机器学习基础,因为我现在也才刚刚入门,行文不准确之处难免,敬请见谅。
本文的后半部分还在整理之中。
1. 什么是机器学习
用最最简单的话来说,机器学习就是不断改进一个模型的过程,使之可以更好的描述一组数据的内在规律。假设,我们拿到若干人的年龄(a1,a2,a3…)和他们的工资(b1,b2,b3…),此时,我们就可以将这些点画在一个二维直角坐标系中,包括(a1,b1),(a2,b2)等等。这些就称为输入或训练数据。
我们可以用数学的最小二乘法拟合一条直线,这样就可以得到最好的可以描述这些数据的规律y=ax+b了。当然,因为我们有很多个点,所以它们可能不在一条直线上,因此任何的直线都不会过它们所有的点,即一定会有误差。
但对于电脑来说,它可以使用一种截然不同的方式来得到y=ax+b中a,b的值。首先,它从一个随便指定的a和b出发(例如a=100,b=1),然后它算出y=100(a1)+1的值和b1的区别,y=100(a2)+1和b2的区别,等等。它发现误差非常大,此时,它就会调整a和b的值(通过某种算法),使得下一次的误差会变小。如果下次的误差反而变得更大了,那就说明,要么是初始值a,b给的不好,要么是y=ax+b可能不是一个好的模型,可能一个二次方程y=a^2+bx+c更好,等等。
经过N轮调整(这称为模型的训练),误差的总和可能已经到了一个稳定的,较小的值。误差小时,a和b的调整相对当然也会较小。此时的a和b就会十分接近我们使用最小二乘法做出来的值,这时,就可以认为模型训练完成了。
当然,这只是机器学习最简单的一个例子,使用的模型也只是线性的直线方程。如果使用更加复杂的模型,机器学习可以做出十分强大的事情。
2. 环境初始化
我使用VS2017创建一个新的控制台应用,然后,使用下面的命令安装TensorflowSharp:
nuget install TensorFlowSharp
TensorflowSharp的源码地址:https://github.com/migueldeicaza/TensorFlowSharp
如果在运行时发现问题“找不到libtensorflow.dll”,则需要访问
http://ci.tensorflow.org/view/Nightly/job/nightly-libtensorflow-windows/lastSuccessfulBuild/artifact/lib_package/libtensorflow-cpu-windows-x86_64.zip
下载这个压缩包。然后,在下载的压缩包中的\lib中找到tensorflow.dll,将它改名为libtensorflow.dll,并在你的工程中引用它。
这样一来,环境初始化就完成了。
3. TensorflowSharp中的概念
TensorflowSharp / Tensorflow中最重要的几个概念:
图(Graph):它包含了一个计算任务中的所有变量和计算方式。可以将它和C#中的表达式树进行类比。例如,一个1+2可以被看作为两个常量表达式,以一个二元运算表达式连接起来。在Tensorflow的世界中,则可以看成是两个tensor和一个op(operation的缩写,即操作)。简单来说,做一个机器学习的任务就是计算一张图。
在计算图之前,当然要把图建立好。例如,计算(1+2)*3再开根号,是一个包括了3个tensor和3个Op的图。
不过,Tensorflow的图和常规的表达式还有所不同,Tensorflow中的节点变量是可以被递归的更新的。我们所说的“训练”,也就是不停的计算一个图,获得图的计算结果,再根据结果的值调整节点变量的值,然后根据新的变量的值再重新计算图,如此重复,直到结果令人满意(小于某个阈值),或跑到了一个无穷大/小(这说明图的变量初始值设置的有问题),或者结果基本不变了为止。
会话(Session):为了获得图的计算结果,图必须在会话中被启动。图是会话类型的一个成员,会话类型还包括一个runner,负责执行这张图。会话的主要任务是在图运算时分配CPU或GPU。
张量(tensor): Tensorflow中所有的输入输出变量都是张量,而不是基本的int,double这样的类型,即使是一个整数1,也必须被包装成一个0维的,长度为1的张量【1】。