for (int row_index = 0; row_index < rows; row_index++)
{
for (int col_index = 0; col_index < cols; col_index++)
{
// print the pixels of image
printf("%3d", values[image_index*image_size+row_index*cols+col_index]);
}
printf("\n");
}
printf("\n");
}
free(values);
fclose(fp);
return 0;
}
int main(int argc, char *argv[])
{
if (-1 == read_lables())
{
return -1;
}
if (-1 == read_images())
{
return -1;
}
return 0;
}
下载并解压出数据集文件train-images-idx3-ubyte和train-labels-idx1-ubyte放到源代码所在目录后,编译并执行:
gcc -o read_images read_images.c
./read_images
展示出来的效果如下:
一共有60000个图片,从代码可以看出数据集里存储的实际就是图片的像素
请尊重原创,转载请注明来源网站www.shareditor.com以及原始链接地址
softmax模型
我们在《 机器学习教程 十三-用scikit-learn做逻辑回归 》中介绍了逻辑回归模型。逻辑回归是用于解决二类分类问题(使用sigmoid函数),而softmax模型是逻辑回归模型的扩展,用来解决多类分类问题。
softmax意为柔和的最大值,也就是如果某个zj大于其他z,那么这个映射的分量就逼近于1,其他的分量就逼近于0,从而将其归为此分类,多个分量对应的就是多分类,数学形式和sigmoid不同,如下:
它的特点是,所有的softmax加和为1,其实它表示的是一种概率,即x属于某个分类的概率。
在做样本训练时,这里的xi计算方法是:
其中W是样本特征的权重,xj是样本的特征值,bi是偏置量。
详细来说就是:假设某个模型训练中我们设计两个特征,他们的值分别是f1和f2,他们对于第i类的权重分别是0.2和0.8,偏置量是1,那么
xi=f1*0.2+f2*0.8+1
如果所有的类别都计算出x的值,如果是一个训练好的模型,那么应该是所属的那个类别对应的softmax值最大
softmax回归算法也正是基于这个原理,通过大量样本来训练这里的W和b,从而用于分类的
tensorflow的优点
tensorflow会使用外部语言计算复杂运算来提高效率,但是不同语言之间的切换和不同计算资源之间的数据传输耗费很多资源,因此它使用图来描述一系列计算操作,然后一起传给外部计算,最后结果只传回一次,这样传输代价最低,计算效率最高
举个例子:
import tensorflow as tf
x = tf.placeholder(tf.float32, [None, 784])
这里的x不是一个实际的x,而是一个占位符,也就是一个描述,描述成了二维浮点型,后面需要用实际的值来填充,这就类似于printf("%d", 10)中的占位符%d,其中第一维是None表示可无限扩张,第二维是784个浮点型变量
如果想定义可修改的张量,可以这样定义:
W = tf.Variable(tf.zeros([784,10]))
b = tf.Variable(tf.zeros([10]))
其中W的维度是[784, 10],b的形状是[10]
有了这三个变量,我们可以定义我们的softmax模型:
y = tf.nn.softmax(tf.matmul(x,W) + b)
这虽然定义,但是没有真正的进行计算,因为这只是先用图来描述计算操作
其中matmul是矩阵乘法,因为x的维度是[None, 784],W的维度是[784, 10],所以矩阵乘法得出的是[None, 10],这样可以和向量b相加
softmax函数会计算出10维分量的概率值,也就是y的形状是[10]
数字识别模型实现
基于上面定义的x、W、b,和我们定义的模型:
y = tf.nn.softmax(tf.matmul(x,W) + b)
我们需要定义我们的目标函数,我们以交叉熵(衡量预测用于描述真相的低效性)为目标函数,让它达到最小: