🕷️ Crawler Inspector

URL Lookup

Direct Parameter Lookup

Raw Queries and Responses

1. Shard Calculation

Query:
Response:
Calculated Shard: 173 (from laksa022)

2. Crawled Status Check

Query:
Response:

3. Robots.txt Check

Query:
Response:

4. Spam/Ban Check

Query:
Response:

5. Seen Status Check

ℹ️ Skipped - page is already crawled

📄
INDEXABLE
CRAWLED
1 day ago
🤖
ROBOTS ALLOWED

Page Info Filters

FilterStatusConditionDetails
HTTP statusPASSdownload_http_code = 200HTTP 200
Age cutoffPASSdownload_stamp > now() - 6 MONTH0 months ago
History dropPASSisNull(history_drop_reason)No drop reason
Spam/banPASSfh_dont_index != 1 AND ml_spam_score = 0ml_spam_score=0
CanonicalPASSmeta_canonical IS NULL OR = '' OR = src_unparsedNot set

Page Details

PropertyValue
URLhttps://geektutu.com/post/tensorflow-mnist-simplest.html
Last Crawled2026-04-17 05:59:54 (1 day ago)
First Indexed2018-03-28 12:52:54 (8 years ago)
HTTP Status Code200
Meta TitleTensorFlow入门(一) - mnist手写数字识别(网络搭建) | 极客兔兔
Meta DescriptionTensorFlow 入门系列文章,第一篇,mnist手写数字识别(网络搭建)。
Meta Canonicalnull
Boilerpipe Text
源代码/数据集已上传到 Github - tensorflow-tutorial-samples 这篇文章是 TensorFlow Tutorial 入门教程的第一篇文章。主要介绍了如何从0开始用tensorflow搭建最简单的网络进行训练。 mnist数据集 简介 MNIST是一个入门级的计算机视觉数据集,它包含各种手写数字图片。在机器学习中的地位相当于Python入门的打印 Hello World 。官网是 THE MNIST DATABASE of handwritten digits 该数据集包含以下四个部分 train-images-idx3-ubyte.gz: 训练集-图片,6w train-labels-idx1-ubyte.gz: 训练集-标签,6w t10k-images-idx3-ubyte.gz: 测试集-图片,1w t10k-labels-idx1-ubyte.gz: 测试集-标签,1w 图片和标签 mnist数据集里的每张图片大小为28 * 28像素,可以用28 * 28的大小的数组来表示一张图片。 标签用大小为10的数组来表示,这种编码我们称之为One hot(独热编码)。 One-hot编码(独热编码) 独热编码使用N位代表N种状态,任意时候只有其中一位有效。 采用独热编码的例子 1 2 3 4 5 性别: [0, 1]代表女,[1, 0]代表男 数字0-9: [0,0,0,0,0,0,0,0,0,1]代表9,[0,1,0,0,0,0,0,0,0,0]代表1 独热编码的优点在于 能够处理非连续型数值特征 在一定程度上也扩充了特征。比如性别本身是一个特征,经过编码以后,就变成了男或女两个特征。 在神经网络中,独热编码其实具有很强的容错性,比如神经网络的输出结果是 [0,0.1,0.2,0.7,0,0,0,0,0, 0]转成独热编码后,表示数字3。即值最大的地方变为1,其余均为0。[0,0.1,0.4,0.5,0,0,0,0,0, 0]也能表示数字3。 numpy中有一个函数,numpy.argmax()可以取得最大值的下标。 神经网络的重要概念 输入(x)输出(y)、标签(label) 输入是指传入给网络处理的向量,相当于数学函数中的变量。 输出是指网络处理后返回的结果,相当于数据函数中的函数值。 标签是指我们期望网络返回的结果。 对于识别mnist图片而言,输入是大小为784(28 * 28)的向量,输出是大小为10的概率向量(概率最大的位置,即预测的数字)。 损失函数(loss function) 损失函数评估网络模型的好坏,值越大,表示模型越差,值越小,表示模型越好。因为传入大量的训练集训练的目标,就是将损失函数的值降到最小。 常见的损失函数定义: 差的平方和 sum((y - label)^2) 1 2 3 [0, 0, 1] 与 [0.1, 0.3, 0.6]的差的平方和为 0.01 + 0.09 + 0.16 = 0.26 [0, 0, 1] 与 [0.2, 0.2, 0.6]的差的平方和为 0.04 + 0.04 + 0.16 = 0.24 [0, 0, 1] 与 [0.1, 0, 0.9]的差的平方和为 0.01 + 0.01 = 0.02 交叉熵 -sum(label * log(y)) 1 2 3 4 [0, 0, 1] 与 [0.1, 0.3, 0.6]的交叉熵为 -log(0.6) = 0.51 [0, 0, 1] 与 [0.2, 0.2, 0.6]的交叉熵为 -log(0.6) = 0.51 [0, 0, 1] 与 [0.1, 0, 0.9]的交叉熵为 -log(0.9) = 0.10 当label为0时,交叉熵为0,label为1时,交叉熵为-log(y),交叉熵只关注独热编码中有效位的损失。这样屏蔽了无效位值的变化(无效位的值的变化并不会影响最终结果),并且通过取对数放大了有效位的损失。当有效位的值趋近于0时,交叉熵趋近于正无穷大。 回归模型 我们可以将网络理解为一个函数,回归模型,其实是希望对这个函数进行拟合。 比如定义模型为 Y = X * w + b,对应的损失即 1 2 3 loss = (Y - labal)^2 = -(X * w - b - label)^2 这里损失函数用方差计算,这个函数是关于w和b的二次函数,所以神经网络训练的目的是找到w和b,使得loss最小。 可以通过不断地传入X和label的值,来修正w和b,使得最终得到的Y与label的loss最小。这个训练的过程,可以采用 梯度下降 的方法。通过梯度下降,找到最快的方向,调整w和b值,使得w * X + b的值越来越接近label。 梯度下降的具体过程,就不在这篇文章中展开了。 学习速率 简单说,梯度即一个函数的斜率,找到函数的斜率,其实就知道了w和b的值往哪个方向调整,能够让函数值(loss)降低得最快。那么方向知道了,往这个方向调整多少呢?这个数,神经网络中称之为学习速率。学习速率调得太低,训练速度会很慢,学习速率调得过高,每次迭代波动会很大。 softmax激活函数 本文不展开讲解softmax激活函数。事实上,再计算交叉熵前的Y值是经过softmax后的,经过softmax后的Y,并不影响Y向量的每个位置的值之间的大小关系。大致有2个作用,一是放大效果,二是梯度下降时需要一个可导的函数。 1 2 3 4 5 6 def softmax ( x ): import numpy as np return np.exp(x) / np. sum (np.exp(x), axis= 0 ) softmax([ 4 , 5 , 10 ]) Tensorflow识别手写数字 构造网络 model.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import tensorflow as tf class Network : def __init__ ( self ): self .learning_rate = 0.001 self .x = tf.placeholder(tf.float32, [ None , 784 ]) self .label = tf.placeholder(tf.float32, [ None , 10 ]) self .w = tf.Variable(tf.zeros([ 784 , 10 ])) self .b = tf.Variable(tf.zeros([ 10 ])) self .y = tf.nn.softmax(tf.matmul( self .x, self .w) + self .b) self .loss = -tf.reduce_sum( self .label * tf.log( self .y + 1e-10 )) self .train = tf.train.GradientDescentOptimizer( self .learning_rate).minimize( self .loss) predict = tf.equal(tf.argmax( self .label, 1 ), tf.argmax( self .y, 1 )) self .accuracy = tf.reduce_mean(tf.cast(predict, "float" )) 训练 train.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import tensorflow as tf from tensorflow.examples.tutorials.mnist import input_data from model import Network class Train : def __init__ ( self ): self .net = Network() self .sess = tf.Session() self .sess.run(tf.global_variables_initializer()) self .data = input_data.read_data_sets( '../data_set' , one_hot= True ) def train ( self ): batch_size = 64 train_step = 2000 for i in range (train_step): x, label = self .data.train.next_batch(batch_size) _, loss = self .sess.run([ self .net.train, self .net.loss], feed_dict={ self .net.x: x, self .net.label: label}) if (i + 1 ) % 10 == 0 : print ( '第%5d步,当前loss:%.2f' % (i + 1 , loss)) 验证准确率 train.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class Train : def __init__ ( self ): ... def train ( self ): ... def calculate_accuracy ( self ): test_x = self .data.test.images test_label = self .data.test.labels accuracy = self .sess.run( self .net.accuracy, feed_dict={ self .net.x: test_x, self .net.label: test_label}) print ( "准确率: %.2f,共测试了%d张图片 " % (accuracy, len (test_label))) 主函数 train.py 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 if __name__ == "__main__" : app = Train() app.train() app.calculate_accuracy() 项目已更新在 Github ,数据集由于国内网络等因素,有时候不能正确下载,所以数据集也一并同步了。 觉得还不错,不要吝惜你的 star ,支持是持续不断更新的动力。 附 推荐 一篇文章入门 Python 上一篇 « 留言板 下一篇 » TensorFlow入门(二) - mnist手写数字识别(模型保存加载) 推荐阅读 Rust 简明教程 发表于2019-11-24, 全文28544字, 阅读约96分钟
Markdown
[![](https://geektutu.com/img/icon.png) 极客兔兔](https://geektutu.com/) - [订阅](https://geektutu.com/feed.xml) - [专题](https://geektutu.com/series/) - [归档](https://geektutu.com/archives/) - [友链](https://geektutu.com/post/link.html) - [关于](https://geektutu.com/post/about.html) - [简明教程 ▾](https://geektutu.com/post/tensorflow-mnist-simplest.html) - [TensorFlow 教程](https://geektutu.com/post/tensorflow-mnist-simplest.html) - [Pandas 数据处理](https://geektutu.com/post/pandas-dataframe-series.html) - [TensorFlow2 文档](https://geektutu.com/post/tf2doc.html) - [Go 简明教程](https://geektutu.com/post/quick-golang.html) - [Rust 简明教程](https://geektutu.com/post/quick-rust.html) - [Python 简明教程](https://geektutu.com/post/quick-python.html) - [杂谈 ▾](https://geektutu.com/post/blog-experience-1.html) - [建站经历](https://geektutu.com/post/blog-experience-1.html) - [年终总结](https://geektutu.com/post/2020.html) - [面试 ▾](https://geektutu.com/post/qa-ml.html) - [机器学习面试题](https://geektutu.com/post/qa-ml.html) - [Go 语言面试题](https://geektutu.com/post/qa-golang.html) - [从零实现 ▾](https://geektutu.com/post/gee.html) - [Web框架 - Gee](https://geektutu.com/post/gee.html) - [分布式缓存 - GeeCache](https://geektutu.com/post/geecache.html) - [ORM框架 - GeeORM](https://geektutu.com/post/geeorm.html) - [RPC框架 - GeeRPC](https://geektutu.com/post/geerpc.html) - [7days-golang Q & A](https://geektutu.com/post/7days-golang-q1.html) - [百宝箱 ▾](https://geektutu.com/post/box-tools.html) - [工具](https://geektutu.com/post/box-tools.html) - [SQLite 速查表](https://geektutu.com/post/cheat-sheet-sqlite.html) - [高性能编程 ▾](https://geektutu.com/post/high-performance-go.html) - [序言](https://geektutu.com/post/high-performance-go.html) - [性能分析](https://geektutu.com/post/hpg-benchmark.html) - [常用数据结构](https://geektutu.com/post/hpg-string-concat.html) - [并发编程](https://geektutu.com/post/hpg-mutex.html) - [编译优化](https://geektutu.com/post/hpg-reduce-size.html) - [语言陷阱](https://geektutu.com/post/hpg-gotchas-array-slice.html) # TensorFlow入门(一) - mnist手写数字识别(网络搭建) **TensorFlow 教程系列文章链接:** - [TensorFlow入门(一) - mnist手写数字识别(网络搭建)](https://geektutu.com/post/tensorflow-mnist-simplest.html) (Dec 9, 2017) - [TensorFlow入门(二) - mnist手写数字识别(模型保存加载)](https://geektutu.com/post/tensorflow-mnist-save-ckpt.html) (Dec 17, 2017) - [TensorFlow入门(三) - mnist手写数字识别(可视化训练)](https://geektutu.com/post/tensorflow-mnist-tensorboard-training.html) (Mar 29, 2018) - [TensorFlow入门(四) - mnist手写数字识别(制作h5py训练集)](https://geektutu.com/post/tensorflow-make-npy-hdf5-data-set.html) (Apr 2, 2018) - [TensorFlow 2.0 (五) - mnist手写数字识别(CNN卷积神经网络)](https://geektutu.com/post/tensorflow2-mnist-cnn.html) (Jun 13, 2019) - [TensorFlow 2.0 (六) - 监督学习玩转 OpenAI gym game](https://geektutu.com/post/tensorflow2-gym-nn.html) (Jun 21, 2019) - [TensorFlow 2.0 (七) - 强化学习 Q-Learning 玩转 OpenAI gym](https://geektutu.com/post/tensorflow2-gym-q-learning.html) (Jun 25, 2019) - [TensorFlow 2.0 (八) - 强化学习 DQN 玩转 gym Mountain Car](https://geektutu.com/post/tensorflow2-gym-dqn.html) (Jun 28, 2019) - [TensorFlow 2.0 (九) - 强化学习 70行代码实战 Policy Gradient](https://geektutu.com/post/tensorflow2-gym-pg.html) (Jul 6, 2019) > 源代码/数据集已上传到 [Github - tensorflow-tutorial-samples](https://github.com/geektutu/tensorflow-tutorial-samples) 这篇文章是 **TensorFlow Tutorial** 入门教程的第一篇文章。主要介绍了如何从0开始用tensorflow搭建最简单的网络进行训练。 ## mnist数据集 ### 简介 MNIST是一个入门级的计算机视觉数据集,它包含各种手写数字图片。在机器学习中的地位相当于Python入门的打印`Hello World`。官网是[THE MNIST DATABASE of handwritten digits](http://yann.lecun.com/exdb/mnist/) 该数据集包含以下四个部分 - train-images-idx3-ubyte.gz: 训练集-图片,6w - train-labels-idx1-ubyte.gz: 训练集-标签,6w - t10k-images-idx3-ubyte.gz: 测试集-图片,1w - t10k-labels-idx1-ubyte.gz: 测试集-标签,1w ### 图片和标签 mnist数据集里的每张图片大小为28 \* 28像素,可以用28 \* 28的大小的数组来表示一张图片。 标签用大小为10的数组来表示,这种编码我们称之为One hot(独热编码)。 ### One-hot编码(独热编码) 独热编码使用N位代表N种状态,任意时候只有其中一位有效。 采用独热编码的例子 独热编码的优点在于 - 能够处理非连续型数值特征 - 在一定程度上也扩充了特征。比如性别本身是一个特征,经过编码以后,就变成了男或女两个特征。 > 在神经网络中,独热编码其实具有很强的容错性,比如神经网络的输出结果是 \[0,0.1,0.2,0.7,0,0,0,0,0, 0\]转成独热编码后,表示数字3。即值最大的地方变为1,其余均为0。\[0,0.1,0.4,0.5,0,0,0,0,0, 0\]也能表示数字3。 > numpy中有一个函数,numpy.argmax()可以取得最大值的下标。 ## 神经网络的重要概念 ### 输入(x)输出(y)、标签(label) - 输入是指传入给网络处理的向量,相当于数学函数中的变量。 - 输出是指网络处理后返回的结果,相当于数据函数中的函数值。 - 标签是指我们期望网络返回的结果。 对于识别mnist图片而言,输入是大小为784(28 \* 28)的向量,输出是大小为10的概率向量(概率最大的位置,即预测的数字)。 ### 损失函数(loss function) 损失函数评估网络模型的好坏,值越大,表示模型越差,值越小,表示模型越好。因为传入大量的训练集训练的目标,就是将损失函数的值降到最小。 常见的损失函数定义: - 差的平方和 sum((y - label)^2) - 交叉熵 -sum(label \* log(y)) 当label为0时,交叉熵为0,label为1时,交叉熵为-log(y),交叉熵只关注独热编码中有效位的损失。这样屏蔽了无效位值的变化(无效位的值的变化并不会影响最终结果),并且通过取对数放大了有效位的损失。当有效位的值趋近于0时,交叉熵趋近于正无穷大。 ![x\_y](https://geektutu.com/post/tensorflow-mnist-simplest/x_y.png) ### 回归模型 我们可以将网络理解为一个函数,回归模型,其实是希望对这个函数进行拟合。 比如定义模型为 Y = X \* w + b,对应的损失即 可以通过不断地传入X和label的值,来修正w和b,使得最终得到的Y与label的loss最小。这个训练的过程,可以采用**梯度下降**的方法。通过梯度下降,找到最快的方向,调整w和b值,使得w \* X + b的值越来越接近label。 梯度下降的具体过程,就不在这篇文章中展开了。 ![loss](https://geektutu.com/post/tensorflow-mnist-simplest/loss.png) ### 学习速率 简单说,梯度即一个函数的斜率,找到函数的斜率,其实就知道了w和b的值往哪个方向调整,能够让函数值(loss)降低得最快。那么方向知道了,往这个方向调整多少呢?这个数,神经网络中称之为学习速率。学习速率调得太低,训练速度会很慢,学习速率调得过高,每次迭代波动会很大。 ### softmax激活函数 本文不展开讲解softmax激活函数。事实上,再计算交叉熵前的Y值是经过softmax后的,经过softmax后的Y,并不影响Y向量的每个位置的值之间的大小关系。大致有2个作用,一是放大效果,二是梯度下降时需要一个可导的函数。 ## Tensorflow识别手写数字 ### 构造网络 `model.py` ### 训练 `train.py` ### 验证准确率 `train.py` ### 主函数 `train.py` > 项目已更新在[Github](https://github.com/geektutu/tensorflow-tutorial-samples),数据集由于国内网络等因素,有时候不能正确下载,所以数据集也一并同步了。 **觉得还不错,不要吝惜你的[star](https://github.com/geektutu/tensorflow-tutorial-samples),支持是持续不断更新的动力。** ## 附 推荐 - [一篇文章入门 Python](https://geektutu.com/post/quick-python.html) *** 专题: [`TensorFlow 教程`](https://geektutu.com/series/#TensorFlow%20%E6%95%99%E7%A8%8B) 本文发表于 2017-12-09,最后修改于 2026-02-23。 本站永久域名「 [geektutu.com](https://geektutu.com/post/tensorflow-mnist-simplest.html) 」,也可搜索「 极客兔兔 」找到我。 *** [上一篇 « 留言板](https://geektutu.com/post/about.html) [下一篇 » TensorFlow入门(二) - mnist手写数字识别(模型保存加载)](https://geektutu.com/post/tensorflow-mnist-save-ckpt.html) 赞赏支持 **请我吃胡萝卜 =^\_^=** ![i](https://geektutu.com/img/icon.png) ![ali](data:image/png;base64,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) 支付宝 ![i](https://geektutu.com/img/icon.png) ![wechat](data:image/png;base64,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) 微信 [![](https://geektutu.com/img/related_links/github.png)](https://github.com/geektutu "Github") [![](https://geektutu.com/img/related_links/rss.jpg)](https://geektutu.com/feed.xml "RSS") [![](https://geektutu.com/img/related_links/zhihu.png)](https://www.zhihu.com/people/gzdaijie "知乎") [![](https://geektutu.com/img/related_links/weibo.jpg)](https://weibo.com/geektutu "微博") ### 推荐阅读 / [Rust](https://geektutu.com/tags/#Rust "Rust") / [Rust 简明教程](https://geektutu.com/post/quick-rust.html) 发表于2019-11-24, 全文28544字, 阅读约96分钟 / [Pandas](https://geektutu.com/tags/#Pandas "Pandas") / [Pandas 数据处理(三) - Cheat Sheet 中文版](https://geektutu.com/post/pandas-cheat-sheet-zh-cn.html) 发表于2019-06-16, 全文1090字, 阅读约4分钟 / [Pandas](https://geektutu.com/tags/#Pandas "Pandas") / [Pandas 数据处理(一) - DataFrame 与 Series](https://geektutu.com/post/pandas-dataframe-series.html) 发表于2018-03-20, 全文7121字, 阅读约24分钟 [\#关于我 (9)](https://geektutu.com/tags/#%E5%85%B3%E4%BA%8E%E6%88%91 "关于我") [\#Go (48)](https://geektutu.com/tags/#Go "Go") [\#百宝箱 (2)](https://geektutu.com/tags/#%E7%99%BE%E5%AE%9D%E7%AE%B1 "百宝箱") [\#Cheat Sheet (1)](https://geektutu.com/tags/#Cheat%20Sheet "Cheat Sheet") [\#Go语言高性能编程 (20)](https://geektutu.com/tags/#Go%E8%AF%AD%E8%A8%80%E9%AB%98%E6%80%A7%E8%83%BD%E7%BC%96%E7%A8%8B "Go语言高性能编程") [\#友链 (1)](https://geektutu.com/tags/#%E5%8F%8B%E9%93%BE "友链") [\#Pandas (3)](https://geektutu.com/tags/#Pandas "Pandas") [\#机器学习 (9)](https://geektutu.com/tags/#%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0 "机器学习") [\#Python (10)](https://geektutu.com/tags/#Python "Python") [\#Rust (1)](https://geektutu.com/tags/#Rust "Rust") [\#TensorFlow (9)](https://geektutu.com/tags/#TensorFlow "TensorFlow") [\#mnist (5)](https://geektutu.com/tags/#mnist "mnist") [\#强化学习 (3)](https://geektutu.com/tags/#%E5%BC%BA%E5%8C%96%E5%AD%A6%E4%B9%A0 "强化学习") [\#OpenAI gym (4)](https://geektutu.com/tags/#OpenAI%20gym "OpenAI gym") [\#DQN (1)](https://geektutu.com/tags/#DQN "DQN") [\#Q-Learning (1)](https://geektutu.com/tags/#Q-Learning "Q-Learning") [\#CNN (1)](https://geektutu.com/tags/#CNN "CNN") [\#TensorFlow 2 (10)](https://geektutu.com/tags/#TensorFlow%202 "TensorFlow 2") [\#官方文档 (10)](https://geektutu.com/tags/#%E5%AE%98%E6%96%B9%E6%96%87%E6%A1%A3 "官方文档") [15](https://github.com/geektutu/geektutu.github.io/issues/4) comments Anonymous [Markdown is supported](https://guides.github.com/features/mastering-markdown/) Preview Login with GitHub ![@qiuChengleiy](https://cdn.jsdelivr.net/npm/gitalk@1/src/assets/icon/github.svg) [qiuChengleiy](https://github.com/qiuChengleiy)commentedover 6 years ago mark 一下 ![@sauryniu](https://cdn.jsdelivr.net/npm/gitalk@1/src/assets/icon/github.svg) [sauryniu](https://github.com/sauryniu)commentedover 6 years ago 计算交叉熵的时候,-log(0.6)如果是默认底数为10的话,不是应该等于0.22吗 ![@geektutu](https://cdn.jsdelivr.net/npm/gitalk@1/src/assets/icon/github.svg) [geektutu](https://github.com/geektutu)commentedover 6 years ago [@sauryniu](https://github.com/sauryniu) 编程语言里,一般默认以e为底数。 ![@sauryniu](https://cdn.jsdelivr.net/npm/gitalk@1/src/assets/icon/github.svg) [sauryniu](https://github.com/sauryniu)commentedover 6 years ago > [@geektutu](https://github.com/geektutu) > [@sauryniu](https://github.com/sauryniu) 编程语言里,一般默认以e为底数。 好的,谢谢 ![@ghost](https://cdn.jsdelivr.net/npm/gitalk@1/src/assets/icon/github.svg) [ghost](https://github.com/ghost)commentedover 6 years ago 请问激活函数主要有什么作用呀? ![@geektutu](https://cdn.jsdelivr.net/npm/gitalk@1/src/assets/icon/github.svg) [geektutu](https://github.com/geektutu)commentedover 6 years ago @jinge1001 空间映射,引入非线性因素,弥补线性模型不能解决的问题。映射后保证数据可求偏导,且保留了原始数据的特征。 ![@ghost](https://cdn.jsdelivr.net/npm/gitalk@1/src/assets/icon/github.svg) [ghost](https://github.com/ghost)commentedover 6 years ago > [@geektutu](https://github.com/geektutu) > @jinge1001 空间映射,引入非线性因素,弥补线性模型不能解决的问题。映射后保证数据可求偏导,且保留了原始数据的特征。 好的,那选哪种激活函数主要依据什么呀? ![@ZENOTME](https://cdn.jsdelivr.net/npm/gitalk@1/src/assets/icon/github.svg) [ZENOTME](https://github.com/ZENOTME)commentedover 6 years ago 你好 我使用的是2.0.0版本 为什么model里面tf.train.GradientDescentOptimizer显示不存在还有log也显示不存在 ![@ZENOTME](https://cdn.jsdelivr.net/npm/gitalk@1/src/assets/icon/github.svg) [ZENOTME](https://github.com/ZENOTME)commentedover 6 years ago 我将tf.train改为tf.keras.train好像就可以了 这是为什么 ![@King-Key](https://cdn.jsdelivr.net/npm/gitalk@1/src/assets/icon/github.svg) [King-Key](https://github.com/King-Key)commentedabout 6 years ago star Load more [Go RPC & TLS 鉴权简明教程5 评论 ● 2月前![icon](https://avatars.githubusercontent.com/u/35258223?v=4) **shigubin** —— @geektutu listener.Accept() 阻塞等待客户端与服务端建立连接,建立连接后交给 rpc.ServeConn 异步处理。因为可能有多个客户端建立连接,所以需要无限循环,每建立一个链接,就异步处理,然后继续等待下一个连接建立。 这里的defer我有点不理解,defer会跟到go协程去么?是不是应该吧defer close conn放到go协程里面处理才合适。](https://geektutu.com/post/quick-go-rpc.html?utm_source=gitalk) [动手写RPC框架 - GeeRPC第七天 服务发现与注册中心(registry)26 评论 ● 6月前![icon](https://avatars.githubusercontent.com/u/190333119?v=4) **U317-AleX** —— @SCUTking 感觉registry与discover这两个东西可以合在一起,这样就不用discover再去发给请求获取registry的数据了。 discover是用在客户端,registry是用在注册中心,两者在物理上都是隔离的,应该不能放一起。这样分开的目的正是微服务架构的基本思想。](https://geektutu.com/post/geerpc-day7.html?utm_source=gitalk) [Go语言动手写Web框架 - Gee第三天 路由Router101 评论 ● 2月前![icon](https://avatars.githubusercontent.com/u/20283879?v=4) **yufeifly** —— 您好,您的邮件已收到,谢谢。——熊宇飞](https://geektutu.com/post/gee-day3.html?utm_source=gitalk) [动手写分布式缓存 - GeeCache第四天 一致性哈希(hash)46 评论 ● 10月前![icon](https://avatars.githubusercontent.com/u/76551623?v=4) **feng384** —— @YvCeung 如果hash(key)的值始终大于m.Keys的最大值,那么使用search得到的idx始终是Keys的长度,最终命中的永远都是环上的第一个节点,这样会不会不均匀? hash(key)得到的值是均匀分布的,不会依赖key的大小,所以不可能始终大于m.Keys的最大值](https://geektutu.com/post/geecache-day4.html?utm_source=gitalk) [Gitalk Plus](https://geektutu.com/post/blog-experience-7.html) [108文章](https://geektutu.com/) [23专题](https://geektutu.com/series) [19标签](https://geektutu.com/tags) [![](https://geektutu.com/img/related_links/github.png)](https://github.com/geektutu) [![](https://geektutu.com/img/related_links/rss.jpg)](https://geektutu.com/feed.xml) [![](https://geektutu.com/img/related_links/zhihu.png)](https://www.zhihu.com/people/gzdaijie) [![](https://geektutu.com/img/related_links/weibo.jpg)](https://weibo.com/geektutu) **TensorFlow 教程** - [mnist手写数字识别(网络搭建)](https://geektutu.com/post/tensorflow-mnist-simplest.html) 1. [mnist数据集](https://geektutu.com/post/tensorflow-mnist-simplest.html#mnist%E6%95%B0%E6%8D%AE%E9%9B%86) 2. [神经网络的重要概念](https://geektutu.com/post/tensorflow-mnist-simplest.html#%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%E7%9A%84%E9%87%8D%E8%A6%81%E6%A6%82%E5%BF%B5) 3. [Tensorflow识别手写数字](https://geektutu.com/post/tensorflow-mnist-simplest.html#Tensorflow%E8%AF%86%E5%88%AB%E6%89%8B%E5%86%99%E6%95%B0%E5%AD%97) 4. [附 推荐](https://geektutu.com/post/tensorflow-mnist-simplest.html#%E9%99%84-%E6%8E%A8%E8%8D%90) - [mnist手写数字识别(模型保存加载)](https://geektutu.com/post/tensorflow-mnist-save-ckpt.html) - [mnist手写数字识别(可视化训练)](https://geektutu.com/post/tensorflow-mnist-tensorboard-training.html) - [mnist手写数字识别(制作h5py训练集)](https://geektutu.com/post/tensorflow-make-npy-hdf5-data-set.html) - [mnist手写数字识别(CNN卷积神经网络)](https://geektutu.com/post/tensorflow2-mnist-cnn.html) - [监督学习玩转 OpenAI gym game](https://geektutu.com/post/tensorflow2-gym-nn.html) - [强化学习 Q-Learning 玩转 OpenAI gym](https://geektutu.com/post/tensorflow2-gym-q-learning.html) - [强化学习 DQN 玩转 gym Mountain Car](https://geektutu.com/post/tensorflow2-gym-dqn.html) - [强化学习 70行代码实战 Policy Gradient](https://geektutu.com/post/tensorflow2-gym-pg.html) **最近的文章** - [Go sync.Cond](https://geektutu.com/post/hpg-sync-cond.html) - [Go 死码消除与调试(debug)模式](https://geektutu.com/post/hpg-dead-code-elimination.html) - [Go sync.Once](https://geektutu.com/post/hpg-sync-once.html) ![](https://geektutu.com/icon/top.png) ![Big Image]() © 2026 - 极客兔兔 - [沪ICP备18001798号-1](http://beian.miit.gov.cn/) Powered by [Hexo](https://hexo.io/) \| Theme [Geektutu](https://geektutu.com/) [![Github Star](data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAYGBgYHBgcICAcKCwoLCg8ODAwODxYQERAREBYiFRkVFRkVIh4kHhweJB42KiYmKjY+NDI0PkxERExfWl98fKcBBgYGBgcGBwgIBwoLCgsKDw4MDA4PFhAREBEQFiIVGRUVGRUiHiQeHB4kHjYqJiYqNj40MjQ+TERETF9aX3x8p//CABEIACIAUAMBIgACEQEDEQH/xAAcAAABBAMBAAAAAAAAAAAAAAAAAQQFBwIDBgj/2gAIAQEAAAAA9KrHSgAYL5/z6zZGuJd12uugbhq3uKtmuRtix20IS7lTLAfAAAn/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/9oACAECEAAAAAAB/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAxAAAAAAAf/EADEQAAICAQIEBQEGBwAAAAAAAAECAwQFAAYREhORBxQhUlQxQVFic5KxJDJCYYGC0f/aAAgBAQABPwCFHnjWUzuvN6hV4cANSRLGjO9yRVUcSzMoA7jVXJYe5N0a2dhmk9kc0bN2GvLN8mbuNeWb5M3ca8s3yZu415Y/Jm7jXlm+TN3H/NeVPyZu40vOk3TZywK8wJ+v3EHVM/wsI/Dq2lrxN3Nnca16eti8chSAIoMbzByhMwP14kHVfwIiSaF5c96J6kwwCOTnHsYk8uvCrdmQy1TI4rJuz3cZLyGR/wCd4+YoOf8AEpUjXitubLYPG4paFsUxcuiGe7yc5gTW3LW44szXmobsi3Dhmic2+Z4+vCVH9CpraPiQ+QvbgTJrPFBWd5YpWrmNIIEXiRO32Pqt4p7cnfHk18lFBdmEVW1LVdIZGOrniTt6plrWKaO69yCykDRxwF+LMAewB0Txtr+Sf31VI8tEPw62fZt7N3Humtbpzz13ucX6CGSWMSuzpLyD1eNgeUka3PuvHbaxq3biTMHfkiSNCS78CwU+3Xg7Vu3MhuTcU6cq3Zemn3Eh2dv8Lzcut+29x1atKbHYqLJUhLwyNMwiZ3j9yDWOxUOV3tgb+3No5LDx1pi9+aeIwRlNY6bc+Jv+IFGrhLxtXJZ7VKcw81diiAAEn0JOrkWZyNfbEr0tz27UGQgkuGzXdIIvyowq99bRxk9ffO/L81SZBPZgEEroQroIxxMZOgeNsfkn99QypHGqO4Vl9CDrN4LDZkwyzyyQ2IgRHZrzGCZVP1XnQglT9oOtw4LC7iqV6uRkZoYpxKFSQpzFRw4EjVRMfSrQ1qqwxQxKFjjTgFUD7BoWYR6iVe+mtxt9Zwf9teaj4AdccPu5tedX5A/VrzUR+sy/q1CwksF19VEfDj/cnQRW+qg66cfsXtrpx+xe2unH7F7a6cfsXtrpx+xe2unH7F7a6cfsXtoxx+xe2gAAOA1//8QAFBEBAAAAAAAAAAAAAAAAAAAAMP/aAAgBAgEBPwB//8QAFBEBAAAAAAAAAAAAAAAAAAAAMP/aAAgBAwEBPwB//9k=)](https://github.com/geektutu/hexo-theme-geektutu) 👁 📚
Readable Markdown
> 源代码/数据集已上传到 [Github - tensorflow-tutorial-samples](https://github.com/geektutu/tensorflow-tutorial-samples) 这篇文章是 **TensorFlow Tutorial** 入门教程的第一篇文章。主要介绍了如何从0开始用tensorflow搭建最简单的网络进行训练。 ## mnist数据集 ### 简介 MNIST是一个入门级的计算机视觉数据集,它包含各种手写数字图片。在机器学习中的地位相当于Python入门的打印`Hello World`。官网是[THE MNIST DATABASE of handwritten digits](http://yann.lecun.com/exdb/mnist/) 该数据集包含以下四个部分 - train-images-idx3-ubyte.gz: 训练集-图片,6w - train-labels-idx1-ubyte.gz: 训练集-标签,6w - t10k-images-idx3-ubyte.gz: 测试集-图片,1w - t10k-labels-idx1-ubyte.gz: 测试集-标签,1w ### 图片和标签 mnist数据集里的每张图片大小为28 \* 28像素,可以用28 \* 28的大小的数组来表示一张图片。 标签用大小为10的数组来表示,这种编码我们称之为One hot(独热编码)。 ### One-hot编码(独热编码) 独热编码使用N位代表N种状态,任意时候只有其中一位有效。 采用独热编码的例子 独热编码的优点在于 - 能够处理非连续型数值特征 - 在一定程度上也扩充了特征。比如性别本身是一个特征,经过编码以后,就变成了男或女两个特征。 > 在神经网络中,独热编码其实具有很强的容错性,比如神经网络的输出结果是 \[0,0.1,0.2,0.7,0,0,0,0,0, 0\]转成独热编码后,表示数字3。即值最大的地方变为1,其余均为0。\[0,0.1,0.4,0.5,0,0,0,0,0, 0\]也能表示数字3。 > numpy中有一个函数,numpy.argmax()可以取得最大值的下标。 ## 神经网络的重要概念 ### 输入(x)输出(y)、标签(label) - 输入是指传入给网络处理的向量,相当于数学函数中的变量。 - 输出是指网络处理后返回的结果,相当于数据函数中的函数值。 - 标签是指我们期望网络返回的结果。 对于识别mnist图片而言,输入是大小为784(28 \* 28)的向量,输出是大小为10的概率向量(概率最大的位置,即预测的数字)。 ### 损失函数(loss function) 损失函数评估网络模型的好坏,值越大,表示模型越差,值越小,表示模型越好。因为传入大量的训练集训练的目标,就是将损失函数的值降到最小。 常见的损失函数定义: - 差的平方和 sum((y - label)^2) - 交叉熵 -sum(label \* log(y)) 当label为0时,交叉熵为0,label为1时,交叉熵为-log(y),交叉熵只关注独热编码中有效位的损失。这样屏蔽了无效位值的变化(无效位的值的变化并不会影响最终结果),并且通过取对数放大了有效位的损失。当有效位的值趋近于0时,交叉熵趋近于正无穷大。 ![x\_y](https://geektutu.com/post/tensorflow-mnist-simplest/x_y.png) ### 回归模型 我们可以将网络理解为一个函数,回归模型,其实是希望对这个函数进行拟合。 比如定义模型为 Y = X \* w + b,对应的损失即 可以通过不断地传入X和label的值,来修正w和b,使得最终得到的Y与label的loss最小。这个训练的过程,可以采用**梯度下降**的方法。通过梯度下降,找到最快的方向,调整w和b值,使得w \* X + b的值越来越接近label。 梯度下降的具体过程,就不在这篇文章中展开了。 ![loss](https://geektutu.com/post/tensorflow-mnist-simplest/loss.png) ### 学习速率 简单说,梯度即一个函数的斜率,找到函数的斜率,其实就知道了w和b的值往哪个方向调整,能够让函数值(loss)降低得最快。那么方向知道了,往这个方向调整多少呢?这个数,神经网络中称之为学习速率。学习速率调得太低,训练速度会很慢,学习速率调得过高,每次迭代波动会很大。 ### softmax激活函数 本文不展开讲解softmax激活函数。事实上,再计算交叉熵前的Y值是经过softmax后的,经过softmax后的Y,并不影响Y向量的每个位置的值之间的大小关系。大致有2个作用,一是放大效果,二是梯度下降时需要一个可导的函数。 ## Tensorflow识别手写数字 ### 构造网络 `model.py` ### 训练 `train.py` ### 验证准确率 `train.py` ### 主函数 `train.py` > 项目已更新在[Github](https://github.com/geektutu/tensorflow-tutorial-samples),数据集由于国内网络等因素,有时候不能正确下载,所以数据集也一并同步了。 **觉得还不错,不要吝惜你的[star](https://github.com/geektutu/tensorflow-tutorial-samples),支持是持续不断更新的动力。** ## 附 推荐 - [一篇文章入门 Python](https://geektutu.com/post/quick-python.html) *** *** [上一篇 « 留言板](https://geektutu.com/post/about.html) [下一篇 » TensorFlow入门(二) - mnist手写数字识别(模型保存加载)](https://geektutu.com/post/tensorflow-mnist-save-ckpt.html) ### 推荐阅读 [Rust 简明教程](https://geektutu.com/post/quick-rust.html) 发表于2019-11-24, 全文28544字, 阅读约96分钟
Shard173 (laksa)
Root Hash1632781748103254173
Unparsed URLcom,geektutu!/post/tensorflow-mnist-simplest.html s443