diff --git a/new/handson-unsup-learn-py/02.md b/new/handson-unsup-learn-py/02.md index 8320e0d4621ff2e6252be96992015c5956f5159a..0225e6ed627670ff6d2953896937a39f8e676f91 100644 --- a/new/handson-unsup-learn-py/02.md +++ b/new/handson-unsup-learn-py/02.md @@ -69,7 +69,9 @@ Bidimensional clustering structure obeying the rule of maximum cohesion and maxi 在理想情况下,簇跨越一些子区域,其密度为`D`,而分隔区域的特征为密度`d << D`。 关于几何特性的讨论可能变得非常复杂,并且在许多情况下,这是非常理论性的。 今后,我们仅考虑属于不同聚类的最近点之间的距离。 如果此值远小于所有聚类的样本与其聚类中心之间的最大距离,则可以确保分离有效,并且很容易区分聚类和分离区域。 相反,当使用距离度量(例如,以 K 均值表示)时,,我们需要考虑的另一个重要要求是聚类的**凸度**。 如果`∀x[1], x[2] ∈ C`且连接`x[1], x[2]`的线段上的所有点属于`C`,泛集`C`是凸的。 在下图中,对凸和非凸(凹)簇进行了比较: -![](img/948fc509-81ad-4ec3-9012-8d8867d41ab3.png)Example of a convex cluster (left) and a concave one (right) +![](img/948fc509-81ad-4ec3-9012-8d8867d41ab3.png) + +Example of a convex cluster (left) and a concave one (right) 不幸的是,由于距离函数的对称性,诸如 K 均值之类的算法无法管理非凸类。 在我们的探索中,我们将展示此限制以及其他方法如何克服它。 diff --git a/new/handson-unsup-learn-py/03.md b/new/handson-unsup-learn-py/03.md index eb610f05bf43def914bf01e5a527477e9ef5745b..622b9fa9a7b5af5731c63cdbce1b9c27db642328 100644 --- a/new/handson-unsup-learn-py/03.md +++ b/new/handson-unsup-learn-py/03.md @@ -690,7 +690,9 @@ X, Y = make_blobs(n_samples=nb_samples, n_features=2, centers=nb_clusters, 下面的屏幕快照显示了数据集(已被改组以除去流传输过程中的任何相互关系): -![](img/c79cce09-3214-4f88-90af-bd1485460604.png)Bidimensional dataset for a comparison between mini-batch K-means and BIRCH +![](img/c79cce09-3214-4f88-90af-bd1485460604.png) + +Bidimensional dataset for a comparison between mini-batch K-means and BIRCH 在执行在线聚类之前,评估标准 K 均值的调整后的兰德得分非常有用,如下所示: @@ -750,7 +752,9 @@ Adjusted Rand score BIRCH: 0.767304858161472 不出所料,当处理完所有样本后,小批量 K 均值几乎达到基准,而 BIRCH 性能稍差。 为了更好地理解行为,让我们考虑将增量分数作为批量函数的图表,如下图所示: -![](img/54ea0ef1-87a0-4c51-b761-14700f6c18b4.png)Incremental adjusted Rand scores as functions of the batches (number of samples) +![](img/54ea0ef1-87a0-4c51-b761-14700f6c18b4.png) + +Incremental adjusted Rand scores as functions of the batches (number of samples) 如您所见,小批量 K 均值很快就达到最大值,所有随后的振荡都是由于重新分配。 相反,BIRCH 的性能总是较差,且呈负趋势。 出现这种差异的主要原因是由于策略不同。 实际上,小批量 K 均值可以在几次批处理后纠正质心的初始猜测,并且重新分配不会显着改变配置。 另一方面,BIRCH 执行的合并数受样本数影响。 diff --git a/new/handson-unsup-learn-py/04.md b/new/handson-unsup-learn-py/04.md index d9a4fd5377d4fa1a6b6bf3cc24b928113387e90e..b47c0c57131d1fddcfff1aca498be4c77c5641c3 100644 --- a/new/handson-unsup-learn-py/04.md +++ b/new/handson-unsup-learn-py/04.md @@ -108,7 +108,9 @@ 单链接方法选择包含最接近的样本对的样本对(每个样本属于不同的簇)。 下图显示了此过程,其中选择了 **C1** 和 **C2** 进行合并: -![](img/ba15026b-5a5e-445b-b800-b80c546f59e8.png)Example of single linkage. C[1] and C[2] are selected to be merged +![](img/ba15026b-5a5e-445b-b800-b80c546f59e8.png) + +Example of single linkage. C[1] and C[2] are selected to be merged 这种方法的主要缺点是可能同时具有很小的簇和很大的簇。 正如我们将在下一部分中看到的那样,单个链接可以使*离群值*保持隔离,直到存在非常高的相异度级别为止。 为了避免或减轻该问题,可以使用平均值和沃德方法。 @@ -118,7 +120,9 @@ 这种链接方法的目的是使属于合并簇的最远样本之间的距离最小。 在下图中,有一个完整链接的示例,其中已选择 *`C[1]`* 和 *`C[3]`* : -![](img/5630c46a-e57c-4099-bcf2-bc30a9ed942e.png)Example of complete linkage. C[1] and C[3] are selected for merging +![](img/5630c46a-e57c-4099-bcf2-bc30a9ed942e.png) + +Example of complete linkage. C[1] and C[3] are selected for merging 该算法选择 *`C[1]`* 和`C`**[3]** 为了增加内部凝聚力。 实际上,很容易理解,考虑所有可能的组合,完全链接会导致群集密度最大化。 在上图所示的示例中,如果所需的簇数为两个,则合并 *`C[1]`* 和 *`C[2]`* 或 *`C[2]`* 和 *`C[3]`* 会产生具有较小内聚力的最终构型,这通常是不希望的结果。 @@ -136,7 +140,9 @@ 这个想法与完全链接非常相​​似,但是在这种情况下,考虑每个群集的平均值,并且目标是考虑所有可能的对( *C [a] ,C [b]* )。 下图显示了平均链接的示例: -![](img/c960034e-9433-4aa2-9418-3442cd67dac3.png)Example of average linkage. C[1] and C[2] are selected for merging. The highlighted points are the averages. +![](img/c960034e-9433-4aa2-9418-3442cd67dac3.png) + +Example of average linkage. C[1] and C[2] are selected for merging. The highlighted points are the averages. 平均链接在生物信息学应用程序(定义分层聚类的主要环境)中特别有用。 对其属性的数学解释是不平凡的,我鼓励您查看原始论文(*一种评估系统关系的统计方法,Sokal R.,Michener C。, 堪萨斯大学科学 1958 年第 38 号公告*),以获取更多详细信息。 @@ -179,7 +185,9 @@ X, Y = make_blobs(n_samples=nb_samples, n_features=2, center_box=[-1, 1], center 数据集(带有标签)显示在以下屏幕截图中: -![](img/9c8ab7a5-cafc-4e28-9f39-0407503eb6c3.png)Dataset employed for dendrogram analysis +![](img/9c8ab7a5-cafc-4e28-9f39-0407503eb6c3.png) + +Dataset employed for dendrogram analysis 为了生成树状图(使用 SciPy),我们首先需要创建一个链接矩阵。 在这种情况下,我们选择了具有 Ward 链接的欧几里德度量标准(但是,与往常一样,我建议您使用不同的配置执行分析): @@ -210,7 +218,9 @@ plt.show() 该图显示在以下屏幕截图中: -![](img/0881b636-fc88-46f7-a273-3812b775e55c.png)Dendrogram corresponding to Ward's linkage applied to the dataset +![](img/0881b636-fc88-46f7-a273-3812b775e55c.png) + +Dendrogram corresponding to Ward's linkage applied to the dataset 如前面的屏幕快照中所述,`x`轴表示旨在最大程度降低交叉连接风险的样本,而`y`轴表示相异程度。 现在让我们从底部开始分析图。 初始状态对应于被视为独立聚类的所有样本(因此相异性为空)。 向上移动,我们开始观察第一次合并。 特别地,当相异度约为 0.35 时,样本 1 和 3 被合并。 @@ -218,7 +228,9 @@ plt.show() 因此,我们有五个聚类,其中两个由一个样本组成。 样本 6 和 11 是最后合并的样本,这并不奇怪。 实际上,它们之间的距离比其他所有区域都远。 在以下屏幕截图中,显示了四个不同的级别(只有包含多个样本的聚类用圆圈标记): -![](img/3f3dda45-7893-433b-b406-faab6e39afaf.png)Clusters generated by cutting the dendrogram at different levels (Ward's linkage) +![](img/3f3dda45-7893-433b-b406-faab6e39afaf.png) + +Clusters generated by cutting the dendrogram at different levels (Ward's linkage) 易于理解,聚集从选择最相似的簇/样本开始,然后通过添加*最近邻*进行,直到到达树的根为止。 在我们的情况下,在相异度等于 2.0 的情况下,已检测到三个定义明确的簇。 左一个也保留在下一个剪切中,而右两个(显然更靠近)被选择合并以生成单个簇。 该过程本身很简单,不需要特别的解释。 但是,有两个重要的考虑因素。 @@ -228,11 +240,15 @@ plt.show() 树状图的第二个优点是可以比较不同链接方法的行为。 使用 Ward 的方法,第一次合并发生的相异度很低,但是五个群集和三个 群集之间存在较大的差距。 这是几何形状和合并策略的结果。 例如,如果我们使用单个链接(本质上非常不同)会发生什么? 以下屏幕快照显示了相应的树状图: -![](img/259e95d8-59c2-40dc-bb7b-4188f5ffd702.png)Dendrogram corresponding to single linkage applied to the dataset +![](img/259e95d8-59c2-40dc-bb7b-4188f5ffd702.png) + +Dendrogram corresponding to single linkage applied to the dataset 结论是,树状图是不对称的,并且簇通常与单个样本或小的附聚物合并。 从右侧开始,我们可以看到样本{ 11 }和{ 6 }合并得很晚。 此外,当必须生成最终的单个簇时,样本{ 6 }(可能是异常值)被合并。 通过以下屏幕快照可以更好地理解该过程: -![](img/fcddb815-9420-4fc1-b74e-59dff373faf9.png)Clusters generated by cutting the dendrogram at different levels (single linkage) +![](img/fcddb815-9420-4fc1-b74e-59dff373faf9.png) + +Clusters generated by cutting the dendrogram at different levels (single linkage) 从屏幕快照中可以看到,虽然 Ward 的方法生成包含所有样本的两个聚类,但单个链接通过将潜在异常值保持在外部来聚集级别 1.0 上的最大块。 因此,树状图还允许定义聚合语义,这在心理学和社会学方面非常有用。 尽管 Ward 的链接与其他对称算法非常相似,但单个链接具有逐步显示的方式,显示了对逐步构建的聚类的潜在偏好,从而避免了相异性方面的巨大差距。 @@ -347,7 +363,9 @@ dff = pd.concat([df, df_tsne], axis=1) 生成的绘图显示在以下屏幕截图中: -![](img/68392175-8413-4141-b51b-1f1808f7a85e.png)t-SNE plot of the Water Treatment Plant dataset +![](img/68392175-8413-4141-b51b-1f1808f7a85e.png) + +t-SNE plot of the Water Treatment Plant dataset 该图显示了潜在的非凸几何形状,其中有许多小的*小岛*(密集区域),这些小岛由空白空间隔开。 但是,如果没有任何域信息,则很难确定哪些斑点可以被视为同一群集的一部分。 我们可以决定施加的唯一*伪约束*(考虑到所有植物都以相似的方式运行)是具有中等或较小的最终簇数。 因此,假设欧氏距离并使用 scikit-learn `AgglomerativeClustering` 类,类,我们可以计算所有链接以及`4`,`6`,`8`和 `10`集群数: @@ -381,7 +399,9 @@ for i, l in enumerate(linkages): 相应的图显示在以下屏幕截图中: -![](img/22e87346-d2f3-4423-b75b-c700146d7550.png)Cophenetic correlation (left) and silhouette score (right) for a different number of clusters and four linkage methods +![](img/22e87346-d2f3-4423-b75b-c700146d7550.png) + +Cophenetic correlation (left) and silhouette score (right) for a different number of clusters and four linkage methods 首先要考虑的一点是,对于完全和平均链接而言,同义相关可以合理地接受,而对于单个链接而言,它太低了。 考虑到轮廓分数,通过单联动和四个簇可实现最大值(约 0.6)。 该结果表明,即使分层算法产生了次优的配置,也可以用中等或高水平的内部凝聚力分离四个区域。 @@ -391,7 +411,9 @@ for i, l in enumerate(linkages): 在这一点上,我们还可以分析截断为 80 片叶子的树状图(可以通过设置`trucate_mode='lastp'` 参数和`p=80`来实现),以避免间隔太小且难以区分 (但是,您可以删除此约束并提高分辨率): -![](img/ce8a15a9-6a97-430f-a742-ed2add760a19.png)Dendrogram of the Water Treatment Plant dataset with the Euclidean metric and complete linkage +![](img/ce8a15a9-6a97-430f-a742-ed2add760a19.png) + +Dendrogram of the Water Treatment Plant dataset with the Euclidean metric and complete linkage 如我们所见,集聚过程不是均匀的。 在过程开始时,相异度的增加非常缓慢,但是在对应于大约 10,000 的值之后,跃变变大。 查看 t-SNE 图,可以理解非凸性的影响对非常大的聚类具有更强的影响,因为密度降低并且隐含地差异增大。 显而易见,很少数量的簇(例如 1、2 或 3)的特征是内部差异非常大,凝聚力非常低。 @@ -415,13 +437,17 @@ pdff = pd.concat([dff, df_pred], axis=1) 最终图显示在以下屏幕截图中: -![](img/98f4f451-1bb3-45a7-b415-72132df4ab00.png)Clustering result of the Water Treatment Plant dataset (eight clusters) +![](img/98f4f451-1bb3-45a7-b415-72132df4ab00.png) + +Clustering result of the Water Treatment Plant dataset (eight clusters) 不出所料,群集是不均匀的,但是它们与几何形状非常一致。 此外,孤立的簇(例如,在 *x∈(-40,-20)*和 *y > 60* 的区域中)非常小,很可能包含真实的 异常值,其行为与大多数其他样本有很大不同。 我们将不分析语义,因为问题非常具体。 但是,可以合理地认为 *x∈(-40,40)*和 *y∈(-40,-10)* -凸,代表合适的基线。 相反,其他大块(在该簇的极端)对应于具有特定特性或行为的植物,这些植物具有足够的扩散性,可以视为标准的替代实践。 当然,如开始时所述,这是不可知的分析,应该有助于理解如何使用分层聚类。 作为最后一步,我们希望以大约 35,000(对应于两个聚类)的相似度水平切割树状图。 结果显示在以下屏幕截图中: -![](img/a886363f-4119-45eb-b45c-a28bfbf0e0a7.png)Clustering result of the Water Treatment Plant dataset (two clusters) +![](img/a886363f-4119-45eb-b45c-a28bfbf0e0a7.png) + +Clustering result of the Water Treatment Plant dataset (two clusters) 在此级别上,树状图显示出属于簇和剩余较小块的样本数量很大。 现在我们知道,这样的次级区域对应于 *x∈(-40,10)*和 *y > 20* 。 同样,结果并不令人惊讶,因为 t-SNE 图表明,这些样本是唯一具有 *y > 20÷25* 的样本(而较大的簇,即使有很大的空白区域,也覆盖了 几乎所有范围)。 @@ -454,7 +480,9 @@ X, Y = make_blobs(n_samples=nb_samples, n_features=2, center_box=[-1, 1], center 标记的数据集显示在以下屏幕截图中: -![](img/2babcaa4-c3d5-4faf-8e30-a7371de35be1.png)Dataset for connectivity constraints example +![](img/2babcaa4-c3d5-4faf-8e30-a7371de35be1.png) + +Dataset for connectivity constraints example 从图中可以看出,样本 18 和 31 ( *x [0] ∈(-2,-1)*和 *x [1] ∈`(1, 2)`*)非常接近; 但是,我们不希望将它们合并,因为样本 18 在较大的中央斑点中有更多邻居,而点 31 被部分隔离,应视为一个自治簇。 我们还希望样本 33 形成单个簇。 这些要求将迫使算法合并不再考虑基础几何(根据高斯分布)的聚类,而是考虑现有知识。 @@ -477,7 +505,9 @@ ax.set_ylabel('Samples', fontsize=18) 以下屏幕快照显示了树状图(从右到左): -![](img/603d9203-3dd1-4123-b027-ffdd7a1f4cc9.png)Dendrogram for the connectivity constraints example with the Euclidean distance and average linkage +![](img/603d9203-3dd1-4123-b027-ffdd7a1f4cc9.png) + +Dendrogram for the connectivity constraints example with the Euclidean distance and average linkage 不出所料,样本 18 和 31 立即合并,然后与另一个包含 2 个样本的簇聚合(当括号中的数字表示这是一个包含更多样本的复合块) ,可能是 44 和 13 。 样本 33 也已合并,因此不会保留在孤立的群集中。 作为确认,让我们使用`n_clusters=8`进行聚类: @@ -490,7 +520,9 @@ Y_pred = ag.fit_predict(X) 以下屏幕快照显示了聚类数据集的图: -![](img/77db8173-7f8c-460b-b7f5-b24274dff263.png)Dataset clustered using the Euclidean distance and average linkage +![](img/77db8173-7f8c-460b-b7f5-b24274dff263.png) + +Dataset clustered using the Euclidean distance and average linkage 结果证实了先前的分析。 在没有限制的情况下,平均链接会产生合理的分区,该分区与基本事实(八高斯分布)兼容。 为了拆分大的中心斑点并保持所需的聚类数量,即使树状图确认它们最终以最高相异度级别合并,该算法也必须合并孤立的样本。 @@ -510,7 +542,9 @@ Y_pred = ag.fit_predict(X) 下一个屏幕截图显示了上一个片段的图形输出: -![](img/a8e4c902-45bd-4510-b43b-c879a8625acb.png)Dataset clustered using the Euclidean distance and average linkage using connectivity constraints +![](img/a8e4c902-45bd-4510-b43b-c879a8625acb.png) + +Dataset clustered using the Euclidean distance and average linkage using connectivity constraints 正如预期的那样,样本 18 已分配给大型中央群集,而点 31 和 33 现在已被隔离。 当然,由于该过程是分层的,因此施加连接约束比分离约束更容易。 实际上,虽然可以在初始阶段轻松合并单个样本,但是使用所有链接都无法轻松保证在最终合并之前将其排除。 diff --git a/new/handson-unsup-learn-py/05.md b/new/handson-unsup-learn-py/05.md index c35715d0de2d682564be3925868fbf500c1acd89..7b04dba88c20db9e88c69487c21c63a973842886 100644 --- a/new/handson-unsup-learn-py/05.md +++ b/new/handson-unsup-learn-py/05.md @@ -116,7 +116,9 @@ for m in np.linspace(1.05, 1.5, 5): 上一个代码段执行不同类型的聚类,并将相应的权重矩阵`W`和分配系数`pc`附加到两个列表中。 在分析特定配置之前,显示测试样本(代表数字 0)的最终权重(对应于每个数字)将非常有帮助: -![](img/3db4c002-6803-4b02-9312-638929fe1d3e.png)Weights (in an inverse logarithmic scale) for the sample X[0], corresponding to different m values +![](img/3db4c002-6803-4b02-9312-638929fe1d3e.png) + +Weights (in an inverse logarithmic scale) for the sample X[0], corresponding to different m values 由于极值往往会非常不同,因此我们选择使用对数逆标(即 *-log(w [0j] )*而不是 *w [0] [j]* )。 当 *m = 1.05* 时,`P[C]`约为 0.96,并且所有权重(与 *C [2 对应的权重除外]* )非常小(请记住,如果 *-log(w)= 30* ,则 *w = e^(-30)* )。 这样的配置清楚地显示了具有主要成分(`C[2]`)的非常硬的聚类。 上图中的后续三个图继续显示优势,但是,尽管`m`增大(`P[C]`减小),但优势和次级之间的差异 组件变得越来越小。 该效果证实了增加的模糊性,达到 *m > 1.38* 的最大值。 实际上,当 *m = 1.5* 时,即使 *P [C] ≈0.1* ,所有权重几乎相同,并且测试样品无法轻松分配给 主导集群。 正如我们之前讨论的那样,我们现在知道像 K 均值这样的算法可以轻松地找到硬分区,因为平均而言,对应于不同数字的样本彼此之间非常不同,并且欧几里得距离足以将它们分配给右边 重心。 在这个例子中,我们要保持适度的模糊性。 因此,我们选择了 *m = 1.2* (对应于`P`*[C]* *0.73* ): @@ -127,7 +129,9 @@ Mu = fc.reshape((10, 8, 8)) `Mu` 数组包含质心,如下图所示: -![](img/613fe7ab-800d-4d83-ba8f-f92841044c5b.png)Centroids corresponding to m = 1.2 and P[C] ≈ 0.73 +![](img/613fe7ab-800d-4d83-ba8f-f92841044c5b.png) + +Centroids corresponding to m = 1.2 and P[C] ≈ 0.73 如您所见,所有不同的数字均已选定,并且按预期,第三个簇(由`C[2]`表示)对应于数字 0。现在,让我们检查一下 对应于`X[0]`的权重(也是`W`的转置,因此它们存储在`W[:, 0]`中): @@ -180,7 +184,9 @@ print(W[:, im]) 示例`X[414]`代表一个数字(8),如以下屏幕快照所示: -![](img/a35690c9-1b3e-4f02-a28d-69b704e008ec.png)Plot of the sample, X[414], corresponding to the weight vector with the smallest standard deviation +![](img/a35690c9-1b3e-4f02-a28d-69b704e008ec.png) + +Plot of the sample, X[414], corresponding to the weight vector with the smallest standard deviation 在这种情况下,存在三个主要簇:`C[8]`,`C[4]`和 *C [7 []* (降序)。 不幸的是,它们都不对应于与`C[5]`相关的数字 8。 不难理解,这种错误主要是由于手指下部的格式不正确而导致的,其结果更类似于 9(这种错误分类也可能发生在人类身上)。 然而,低标准偏差和明显的主导成分的缺乏应告诉我们,这一决定不容易做出,并且样本具有属于三个主要类别的特征。 一个更复杂的监督模型可以轻松避免此错误,但考虑到我们正在执行非监督分析,并且我们仅将基本事实用于评估目的,结果并不是那么负面。 我建议您使用其他`m`值测试结果,并尝试找出一些可能的合成规则(即,大多数 8 位数字都被软分配给`C[i]`和`C[j]`,因此我们可以假设相应的质心对部分共同特征进行编码,例如,由所有 8 位和 9 位数字共享。 @@ -206,11 +212,15 @@ print(W[:, im]) 每个多元高斯变量的每个分量的影响都取决于协方差矩阵的结构。 下图显示了双变量高斯分布的三种主要可能性(结果可以轻松扩展到`n`维空间): -![](img/37882b8c-c2b1-48c3-a901-106fb8c48cb5.png)Full covariance matrix (left); diagonal covariance (center); circular/spherical covariance (right) +![](img/37882b8c-c2b1-48c3-a901-106fb8c48cb5.png) + +Full covariance matrix (left); diagonal covariance (center); circular/spherical covariance (right) 从现在开始,我们将一直在考虑完全协方差矩阵的情况,该矩阵可以实现最大的表达能力。 很容易理解,当这样的分布完全对称(即协方差矩阵是圆形/球形)时,伪簇的形状与 K 均值相同(当然 ,在高斯混合中,簇没有边界,但是始终可以在固定数量的标准偏差后削减高斯)。 相反,当协方差矩阵不是对角线或具有不同的方差时,影响不再是对称的(例如,在双变量的情况下,一个组件可以显示出比另一个更大的方差)。 在这两种情况下,高斯混合均允许我们计算实际概率,而不是测量样本之间的距离,`x`*[i]* 平均载体`μ` *[j]* (以 K 均值表示)。 下图显示了单变量混合的示例: -![](img/45e96e53-863e-4c70-995b-c33388eb96ea.png)Example of a univariate Gaussian mixture +![](img/45e96e53-863e-4c70-995b-c33388eb96ea.png) + +Example of a univariate Gaussian mixture 在这种情况下,每个样本在每个高斯下始终具有非零概率,其影响取决于其均值和协方差矩阵。 例如,对应于`x`-位置的点 2.5 既可以属于中央高斯,也可以属于右手的点(而左手的影响最小)。 如本章开头所述,通过选择影响最大的组件(`argmax`),可以将任何软聚类算法转换为硬聚类算法。 @@ -277,7 +287,9 @@ X, Y = make_blobs(n_samples=nb_samples, n_features=2, center_box=[-1, 1], center 该数据集是通过对两个具有不同标准偏差(1.0 和 0.6)的高斯分布进行采样而生成的,如以下屏幕截图所示: -![](img/db575108-46aa-404e-9944-7ad79dde1310.png)Dataset for the Gaussian mixture example +![](img/db575108-46aa-404e-9944-7ad79dde1310.png) + +Dataset for the Gaussian mixture example 我们的目标是同时使用高斯混合模型和 K 均值,并比较最终结果。 正如我们期望的那样,有两个组成部分,数据生成过程的近似如下: @@ -377,7 +389,9 @@ Y_pred_km = km.predict(X) 群集结果显示在以下屏幕截图中: -![](img/23deac5e-1e50-4c67-a6aa-e83753613d06.png)Gaussian mixture result (left) with the shapes of three horizontal sections; k-means result (right) +![](img/23deac5e-1e50-4c67-a6aa-e83753613d06.png) + +Gaussian mixture result (left) with the shapes of three horizontal sections; k-means result (right) 不出所料,这两种算法都产生非常相似的结果,并且主要差异是由于高斯算法的非对称性造成的。 特别地,与数据集的左下部分相对应的伪群集在两个方向上均具有较大的方差,并且对应的高斯是主要的。 为了检查混合物的行为,让我们计算三个样本点的概率(*(0,-2)*; *(1,-1)*-临界样本​​;以及 *(1、0)*),使用`predict_proba()`方法: @@ -442,7 +456,9 @@ for n in range(1, n_max_components + 1): 生成的图显示在以下屏幕截图中: -![](img/006b6068-1d96-4ada-86ca-44bdd17cd9b0.png)AICs, BICs, and log-likelihoods for Gaussian mixtures with the number of components in the range (1, 20) +![](img/006b6068-1d96-4ada-86ca-44bdd17cd9b0.png) + +AICs, BICs, and log-likelihoods for Gaussian mixtures with the number of components in the range (1, 20) 在这种情况下,我们知道数据集是由两个高斯分布生成的,但是让我们假设我们没有这条信息。 AIC 和 BIC 都具有 *n [c] = 2* 的(局部)最小值。 但是,尽管 BIC 越来越大,但 AIC 的伪全局最小值为 *n [c] = 18* 。 因此,如果我们信任 AIC,则应该选择 18 个分量,这等效于以许多高斯对数据集进行超细分,并且方差很小。 另一方面, *n [c] = 2* 和 *n [c] = 18* 之间的差异不是很大 值,因此考虑到简单得多,我们也可以选择以前的配置。 BIC 确认了这种选择。 实际上,即使还有一个局部最小值对应于 *n [c] = 18* ,其值也比 *n [c] = 2* 。 正如我们之前所解释的,这种行为是由于 BIC 施加的样本量额外罚款。 对于 *n [c] = 2* ,每个二元高斯变量需要一个权重变量,两个均值变量和四个协方差矩阵变量,我们得到 *n [p] = 2(1 + 2+ 4)= 14* ,对于 *n [c] = 18* ,我们得到 *n [p] = 18(1 + 2+ 4)= 126* 。 由于有 300 个样本,BIC 会受到 *log(300)≈5.7* 的惩罚,这会导致 BIC 增加约 350。随着 *n [c []* 变大(因为在极端情况下,每个点都可以被视为由具有零方差的单个高斯生成,等效于狄拉克三角洲),因此参数数量在模型选择中起主要作用 处理。 @@ -524,7 +540,9 @@ print((Y_pred == 4).sum()) 因此,平均而言,所有高斯人都产生相同数量的点。 最终配置显示在以下屏幕截图中: -![](img/c391f825-4d97-41f7-965e-79ccd22623fe.png)Final configuration, with five active components +![](img/c391f825-4d97-41f7-965e-79ccd22623fe.png) + +Final configuration, with five active components 该模型通常可以接受; 但是,假设我们知道根本原因(即产生高斯分布)的数量可能是 4,而不是 5。我们可以尝试的第一件事是保持原始的最大组件数量并减少组件数量。 重量浓度参数(即 0.1)。 如果近似值可以使用较少的高斯分布成功生成`X`,则应该找到一个空权重: @@ -545,7 +563,9 @@ Weights: [3.07496936e-01 2.02264778e-01 2.94642240e-01 1.95417680e-01 1.78366038 可以看到,第五个高斯的权重比其他高斯小得多,可以完全丢弃(我请您检查是否几乎没有分配一些样本)。 以下屏幕快照显示了具有四个活动组件的新配置: -![](img/739c3008-1f01-46c2-81bf-6b710703a427.png)Final configuration, with four active components +![](img/739c3008-1f01-46c2-81bf-6b710703a427.png) + +Final configuration, with four active components 可以看到,该模型执行了组件数量的自动选择,并且已将较大的右 Blob 分成几乎正交的两个部分。 即使使用大量初始组件(例如 10 个)训练模型,此结果也保持不变。 作为练习,我建议使用其他值重复该示例,检查权重之间的差异。 贝叶斯高斯混合因避免过度拟合的能力而非常强大。 实际上,虽然标准的高斯混合将通过减小它们的协方差来使用所有成分,但必要时(以便覆盖密集区域),这些模型利用了 Dirichlet 过程/分布的特性,以避免激活 组件过多。 例如,可以通过检查模型可实现的最少组件数来深入了解潜在的数据生成过程。 在没有任何其他先验知识的情况下,这样的值是最终配置的良好候选者,因为较少数量的组件也将产生较低的最终可能性。 当然,可以将 AIC / BIC 与这种方法一起使用,以进行另一种形式的确认。 但是,与标准高斯混合的主要区别在于可以包括来自专家的先验信息(例如,均值和协方差的原因结构)。 因此,我邀请您通过更改`mean_precision_prior`的值来重复该示例。 例如,可以将`mean_prior`参数设置为与`X`的平均值不同的值,并调整 `mean_precision_prior`,以便基于某些参数强制模型实现不同的细分 先验知识(即,区域中的所有样本应由特定组件生成)。 @@ -604,7 +624,9 @@ q2 = 0.5 下面的屏幕快照显示了数据集和初始高斯分布: -![](img/4fcf89b7-072b-4d1b-b722-af2ee25e79f5.png)Dataset (the unlabeled samples are marked with an x) and initial configuration +![](img/4fcf89b7-072b-4d1b-b722-af2ee25e79f5.png) + +Dataset (the unlabeled samples are marked with an x) and initial configuration 现在,我们可以按照先前定义的规则执行几次迭代(本例中为 10 次)(当然,也可以检查参数的稳定性,以停止迭代)。 使用 SciPy `multivariate_normal`类计算每个高斯下的概率: @@ -677,7 +699,9 @@ Gaussian 2: 正如预期的那样,由于数据集的对称性,权重几乎保持不变,同时均值和协方差矩阵也进行了更新,以使可能性最大化。 最终图显示在以下屏幕截图中: -![](img/4d7b1215-9880-410f-b1a4-f15a2d338d88.png)Final configuration, after 10 iterations +![](img/4d7b1215-9880-410f-b1a4-f15a2d338d88.png) + +Final configuration, after 10 iterations 可以看到,两个高斯函数均已成功优化,并且它们能够从充当**受信任指南**的几个标记样本开始生成整个数据集。 这种方法非常强大,因为它允许我们在不做任何修改的情况下将一些先验知识包括在模型中。 但是,由于标记的样本具有等于 1 的固定概率,因此该方法在异常值方面不是非常可靠。 如果样本尚未通过数据生成过程生成或受噪声影响,则可能导致模型放错高斯分布。 但是,通常不应该考虑这种情况,因为任何先验知识(包括在估计中)都必须进行预评估,以检查其是否可靠。 这样的步骤是必要的,以避免强迫模型仅学习原始数据生成过程的一部分的风险。 相反,当标记的样本真正代表了潜在的过程时,它们的包含减少了错误并加快了收敛速度。 我邀请读者在引入一些噪声点(例如(-20,-10))之后重复该示例,并比较一些未标记的测试样本的概率。 diff --git a/new/handson-unsup-learn-py/07.md b/new/handson-unsup-learn-py/07.md index 9d543ee701114f0cb885cb41cba0ed6cd13778bc..3bea18004b4f8cfbaa595638d7eb1c72ca532ad3 100644 --- a/new/handson-unsup-learn-py/07.md +++ b/new/handson-unsup-learn-py/07.md @@ -228,7 +228,9 @@ d = l[:l.shape[0]-1] - l[1:] 以下屏幕快照显示了展开图像(64 维数组)的差异: -![](img/8109d275-c6a0-42c6-b8cb-b7f2a22c590f.png)Eigenvalue differences for each principal component +![](img/8109d275-c6a0-42c6-b8cb-b7f2a22c590f.png) + +Eigenvalue differences for each principal component 可以看出,第一主成分的差异非常大,与第四主成分( *λ [4] -λ [3]* ); 但是,下一个差异仍然很高,虽然对应`$1[$2]`突然下降。 在这一点上,趋势几乎是稳定的(除了一些残余振荡),直到`$1[$2]`为止,然后趋势开始迅速下降,趋于趋于零 。 由于我们仍然希望获得正方形图像,因此我们将选择 *k = 16* (相当于将每一边除以四)。 在另一个任务中,您可以选择 *k = 15* ,甚至 *k = 8* ; 但是,为了更好地理解降维导致的误差,也将有助于分析所解释的方差。 因此,让我们从执行 PCA 开始: @@ -241,7 +243,9 @@ digits_pca = pca.fit_transform(X) 在拟合模型并将所有样本投影到对应于前 16 个主成分的子空间后,即可获得`digits_pca` 数组。 如果我们想将原始图像与其重构进行比较,则需要调用`inverse_transform()` 方法,该方法将投影投射到原始空间上。 因此,如果 PCA 在这种情况下是变换`f(x): ℜ^64 → ℜ^16`,则逆变换为`g(x): ℜ^16 → ℜ^64`。 以下屏幕截图显示了前 10 位数字与它们的重构之间的比较: -![](img/6b57796e-5007-448a-9bd2-a96bc7e3affb.png)Original samples (top row); reconstructions (bottom row) +![](img/6b57796e-5007-448a-9bd2-a96bc7e3affb.png) + +Original samples (top row); reconstructions (bottom row) 重建显然是有损的,但是数字仍然是可区分的。 现在,让我们通过对`explained_variance_ratio_` 数组的所有值求和来检查总的解释方差,其中包含每个分量的相对解释方差的相对数量(因此,任何`k < n`分量始终小于 1): @@ -259,7 +263,9 @@ print(np.sum(pca.explained_variance_ratio_)) 以下屏幕快照显示了显示所有单个贡献的图: -![](img/f34df112-3c13-4331-b106-31b3c662783d.png)Explained variance ratio corresponding to each principal component +![](img/f34df112-3c13-4331-b106-31b3c662783d.png) + +Explained variance ratio corresponding to each principal component 正如预期的那样,贡献趋于减少,因为在这种情况下,第一个主要成分负责任; 例如,对于一种颜色的线条(例如黑色或白色),而其余的则为灰色。 这种行为非常普遍,几乎在每种情况下都可以观察到。 通过该图,还可以轻松找到额外的损失,以进一步减少损失。 例如,我们可以立即发现,对 3 个成分的严格限制可以解释原始差异的 40% ; 因此,剩余的 45% 被分为剩余的 13 个组成部分。 我邀请您重复此示例,尝试找出人类区分所有数字所需的最少数量的组件。 diff --git a/new/intel-mobi-proj-tf/01.md b/new/intel-mobi-proj-tf/01.md index fc92d4fdb49668a9253e40d613ebf7c2b468698f..e2dcede48919efc3929f0f8941a6f8ce0e4b067d 100644 --- a/new/intel-mobi-proj-tf/01.md +++ b/new/intel-mobi-proj-tf/01.md @@ -101,11 +101,15 @@ sudo pip install --upgrade /tmp/tensorflow_pkg/tensorflow-1.4.0-cp27-cp27m-macos 1. 在[这个页面](https://developer.nvidia.com/cuda-80-ga2-download-archive)中找到 NVIDIA CUDA 8.0 GA2 版本,并进行以下屏幕截图中所示的选择: -![](img/0e74beec-5ac6-4755-8268-dcf83c27a700.png)Fig 1.1 Getting ready to download CUDA 8.0 on Ubuntu 16.04 +![](img/0e74beec-5ac6-4755-8268-dcf83c27a700.png) + +Fig 1.1 Getting ready to download CUDA 8.0 on Ubuntu 16.04 2. 下载基本安装程序,如以下屏幕快照所示: -![](img/49296f66-83aa-48a5-973b-a4d9c8dd4348.png)Fig 1.2 Choosing the CUDA 8.0 installer file for Ubuntu 16.04 +![](img/49296f66-83aa-48a5-973b-a4d9c8dd4348.png) + +Fig 1.2 Choosing the CUDA 8.0 installer file for Ubuntu 16.04 3. 打开一个新的终端并运行以下命令(您还需要将最后两个命令添加到`.bashrc`文件中,以使两个环境变量在您下次启动新终端时生效): @@ -119,7 +123,9 @@ export LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH 4. 通过[这里](https://developer.nvidia.com/rdp/cudnn-download)下载用于 CUDA 8.0 的 NVIDIA cuDNN 6.0,您将被要求先免费注册一个 NVIDIA 开发者帐户(免费)。 您可以下载它,如下一个屏幕截图所示(选择突出显示的 cuDNN v6.0 Linux 版): -![](img/f8e7636c-a193-4915-8c4f-8a234ffaf788.png)Fig 1.3 Selecting cuDNN 6.0 for CUDA 8.0 on Linux +![](img/f8e7636c-a193-4915-8c4f-8a234ffaf788.png) + +Fig 1.3 Selecting cuDNN 6.0 for CUDA 8.0 on Linux 5. 假设下载的文件位于默认的`~/Downloads`目录下,请解压缩该文件,然后您会看到一个名为`cuda`的文件夹,其中包含两个名为`include`和`lib64`的子文件夹 6. 将 cuDNN `include`和`lib64`文件复制到`CUDA_HOME`的`lib64`和`include`文件夹中: @@ -209,11 +215,15 @@ Android Studio 是开发 Android 应用程序的最佳工具,并且 TensorFlow 接下来,打开 Android Studio,您需要提供 Android SDK 的路径,如果您安装了以前版本的 Android Studio,则默认情况下它位于`~/Library/Android/sdk`中,或者您可以选择打开现有的 Android Studio 项目,然后转到“在 MacOS 上设置 TensorFlow”一节中创建的 TensorFlow 1.4 源目录,然后打开`tensorflow/examples/android`文件夹。 之后,您可以通过单击安装工具消息的链接或转到 Android Studio 的`Tools | Android | SDK Manager`来下载 Android SDK,如以下屏幕截图所示。 从 SDK 工具标签中,您可以选中特定版本的 Android SDK 工具旁边的框,然后单击确定按钮以安装该版本: -![](img/3b90efdb-6655-4e35-b74a-a44e69e17487.png)Fig 1.4 Android SDK Manager to install SDK tools and NDK +![](img/3b90efdb-6655-4e35-b74a-a44e69e17487.png) + +Fig 1.4 Android SDK Manager to install SDK tools and NDK 最后,由于 TensorFlow Android 应用程序使用 C++ 中的本机 TensorFlow 库来加载和运行 TensorFlow 模型,因此您需要安装 Android **本机开发套件**(**NDK**),您可以执行以下任一操作 从上一个屏幕快照中显示的 Android SDK Manager 中获取,或者直接从[这里](https://developer.android.com/ndk/downloads/index.html)下载 NDK。 NDK 版本 r16b 和 r15c 均已通过测试可运行本书中的 Android 应用。 如果直接下载 NDK,则在打开项目并选择 Android Studio 的`File | Project Structure`后,您可能还需要设置 Android NDK 位置,如以下屏幕截图所示: -![](img/1f6a2d74-0be0-4f36-9796-2cf66eb1694f.png)Fig 1.5 Setting project-level Android NDK location +![](img/1f6a2d74-0be0-4f36-9796-2cf66eb1694f.png) + +Fig 1.5 Setting project-level Android NDK location 安装并设置了 Android SDK 和 NDK 之后,您就可以测试运行示例 TensorFlow Android 应用程序了。 diff --git a/new/intel-mobi-proj-tf/02.md b/new/intel-mobi-proj-tf/02.md index b93d41937b44da83acdad3e18f432f5cbcf1f6a3..f71ff43cd4db84c88acf0eb1b2be40bb8ecbe7d3 100644 --- a/new/intel-mobi-proj-tf/02.md +++ b/new/intel-mobi-proj-tf/02.md @@ -50,7 +50,9 @@ 在`~/Downloads`中解压缩下载的狗`images.tar`文件,您应该在`~/Downloads/Images`中看到文件夹列表,如以下屏幕截图所示。 每个文件夹对应一个犬种,并且包含约 150 张图像(您无需为图像提供显式标签,因为文件夹名称用于标记文件夹中包含的图像): -![](img/c8c4fa68-5db2-406d-9444-fbf1fdeb5418.png)Figure 2.1 Dogset images separated by folders, or labels of dog breedYou may download the dataset and then run the `retrain.py` script on Mac, as it doesn't take too long (less than an hour) for the script to run on the relatively small dataset (about 20,000 images in total), but if you do that on a GPU-powered Ubuntu, as set up in the last chapter, the script can complete in just a few minutes. In addition, when retraining with a large image dataset, running on Mac may take hours or days so it makes sense to run it on a GPU-powered machine. +![](img/c8c4fa68-5db2-406d-9444-fbf1fdeb5418.png) + +Figure 2.1 Dogset images separated by folders, or labels of dog breedYou may download the dataset and then run the `retrain.py` script on Mac, as it doesn't take too long (less than an hour) for the script to run on the relatively small dataset (about 20,000 images in total), but if you do that on a GPU-powered Ubuntu, as set up in the last chapter, the script can complete in just a few minutes. In addition, when retraining with a large image dataset, running on Mac may take hours or days so it makes sense to run it on a GPU-powered machine. 假设您已经创建了`/tf_file`目录和`/tf_file/dogs_bottleneck`目录,那么重新训练模型的命令如下: @@ -157,15 +159,21 @@ bazel-bin/tensorboard/tensorboard --logdir /tmp/retrain_logs 然后在浏览器中启动 URL `http://localhost:6006`。 首先,您将看到准确性图,如以下屏幕截图所示: -![](img/3ae39776-c298-4b42-9125-f25ca84c9ed2.png)Figure 2.2 Train and validation accuracy of the Inception v3 retrained model +![](img/3ae39776-c298-4b42-9125-f25ca84c9ed2.png) + +Figure 2.2 Train and validation accuracy of the Inception v3 retrained model 在下面的屏幕截图中的交叉熵图,和我们之前对于运行`retrain.py`的输出所描述的一样: -![](img/cd4cea6a-8847-40bd-9ec4-3d9696972a5f.png)Figure 2.3 Train and validation cross entropy of the Inception v3 retrained model +![](img/cd4cea6a-8847-40bd-9ec4-3d9696972a5f.png) + +Figure 2.3 Train and validation cross entropy of the Inception v3 retrained model 现在单击`GRAPHS`选项卡,您将看到一个名为`Mul`的操作,另一个名为`final_result`的操作 ,如下所示: -![](img/18aa75d8-28e3-497c-ba8f-145baa6cee37.png)Figure 2.4 The Mul and final_result nodes in the retrained model +![](img/18aa75d8-28e3-497c-ba8f-145baa6cee37.png) + +Figure 2.4 The Mul and final_result nodes in the retrained model 实际上,如果您希望与 TensorFlow 进行小的交互,则可以尝试几行 Python 代码来找出输出层和输入层的名称,如 iPython 交互所示: @@ -344,7 +352,9 @@ bazel-bin/tensorflow/tools/benchmark/benchmark_model 1. 双击`tensorflow/examples/ios/simple`中的`tf_simple_example.xcworkspace`文件以 Xcode 打开应用 2. 拖动我们用来测试`label_image`脚本的`quantized_stripped_dogs_retrained.pb`模型文件,`dog_retrained_labels.txt`标签文件和`lab1.jpg`图像文件,然后拖放到项目的数据文件夹中,并确保同时复制两个项目 选中和添加到目标,如以下屏幕截图所示: -![](img/d2e25f9d-c88d-4fe5-918d-ba7e64420682.png)Figure 2.5 Adding the retrained model file and the label file to app +![](img/d2e25f9d-c88d-4fe5-918d-ba7e64420682.png) + +Figure 2.5 Adding the retrained model file and the label file to app 3. 单击 Xco​​de 中的`RunModelViewController.mm`文件,该文件使用 TensorFlow C++ API 处理输入图像,通过 Inception v1 模型运行它,并获得图像分类结果,并更改行: @@ -476,7 +486,9 @@ pod 'TensorFlow-experimental' 4. 在 Xcode 中打开`HelloTensorFlow.xcworkspace`文件,然后将两个文件(`ios_image_load.mm`和`ios_image_load.h`)拖放到 TensorFlow iOS 示例目录`tensorflow/examples/ios/simple`到`HelloTensorFlow`项目文件夹中。 5. 将两个模型`quantized_stripped_dogs_retrained.pb`和`dog_retrained_mobilenet10_224.pb`,`label file dog_retrained_labels.txt`以及几个测试图像文件拖放到项目文件夹中,之后,您应该看到类似以下的内容: -![](img/b89b3444-a6a9-45b4-bb02-ddf8388a6992.png)Figure 2.6 Adding utility files, model files, label file and image files +![](img/b89b3444-a6a9-45b4-bb02-ddf8388a6992.png) + +Figure 2.6 Adding utility files, model files, label file and image files 6. 将`ViewController.m`重命名为`ViewController.mm`,因为我们将在该文件中混合使用 C++ 代码和 Objective-C 代码来调用 TensorFlow C++ API 并处理图像输入和推断结果。 然后,在`@interface ViewController`之前,添加以下`#include`和函数原型: @@ -623,11 +635,15 @@ GetTopN(output->flat(), kNumResults, kThreshold, &top_results); 现在,在模拟器中或实际的 iOS 设备上运行该应用程序,首先,您将看到以下消息框,要求您选择重新训练的模型: -![](img/1823f6a6-f212-4ac9-9d78-a978a234c4aa.png)Figure 2.7 Selecting different retrained model for inference +![](img/1823f6a6-f212-4ac9-9d78-a978a234c4aa.png) + +Figure 2.7 Selecting different retrained model for inference 然后,您将在选择模型后看到推断结果: -![](img/b9de1c02-8b3a-4482-b7f5-4d0d8d3e4692.png)Figure 2.8 Inference results based on different retrained models +![](img/b9de1c02-8b3a-4482-b7f5-4d0d8d3e4692.png) + +Figure 2.8 Inference results based on different retrained models 请注意,MobileNet 训练后的模型在同一款 iPhone 上的运行速度要快得多,在 iPhone 6 上要比 Inception v3 训练后的模型快约一秒钟。 @@ -653,11 +669,15 @@ pod 'TensorFlow-experimental' 4. 在 Xcode 中打开`HelloTensorFlow_Swift.xcworkspace`文件,然后将两个文件(`ios_image_load.mm`和`ios_image_load.h`)拖放到 TensorFlow iOS 示例目录`tensorflow/examples/ios/simple`到`HelloTensorFlow_Swift`项目文件夹中。 当将两个文件添加到项目中时,您将看到一个消息框,如以下屏幕截图所示,询问您是否要配置 Objective-C 桥接头,Swift 代码调用 C++ 头需要此头。 Objective-C 代码。 因此,单击创建桥接标题按钮: -![](img/afa22723-f59f-4544-8a61-e73ee7c43e85.png)Figure 2.9 Creating Bridging Header when adding C++ file +![](img/afa22723-f59f-4544-8a61-e73ee7c43e85.png) + +Figure 2.9 Creating Bridging Header when adding C++ file 5. 同样将`quantized_stripped_dogs_retrained .pb`和`dog_retrained_mobilenet10_224.pb`这两个模型,标签文件`dog_retrained_labels.txt`和几个测试图像文件拖放到项目文件夹中–之后,您应该会看到类似以下内容: -![](img/8236a55a-15fe-41a1-9ff7-c7280ae6c43f.png)Figure 2.10 Adding utility files, model files, label file and image files +![](img/8236a55a-15fe-41a1-9ff7-c7280ae6c43f.png) + +Figure 2.10 Adding utility files, model files, label file and image files 6. 使用以下代码创建一个名为`RunInference.h`的新文件(一个窍门是,我们必须在下一步中使用 Objective-C 类作为`RunInferenceOnImage`方法的包装,以便我们的 Swift 代码进行间接调用) 。否则,将发生构建错误): @@ -773,7 +793,9 @@ self.present(alert, animated: true, completion: nil) 现在,在模拟器中运行该应用程序,您将看到一个警报控制器,要求您选择模型: -![](img/098c0b7a-c32a-4ffc-bf3d-49c1ea80d36f.png)Figure 2.11 Selecting a retrained model for inference +![](img/098c0b7a-c32a-4ffc-bf3d-49c1ea80d36f.png) + +Figure 2.11 Selecting a retrained model for inference 以及不同再训练模型的推论结果: @@ -798,15 +820,21 @@ Figure 2.12 Inference results for different retrained models 3. 生成`gradle`文件,您将在`app`目录的位置`app/build/intermediates/transforms/mergeJniLibs/debug/0/lib`的子文件夹内看到`libtensorflow_inference.so`,这是 Java 代码与之对话的 TensorFlow 本机库。 4. 如果这是一个新项目,则可以通过首先切换到软件包,然后右键单击该应用程序并选择“新建 | 文件夹 | `assets`文件夹”来创建`assets`文件夹。 ,如以下屏幕截图所示,然后从软件包切换回 Android: -![](img/6cf6b889-8ecb-4837-9087-19b34d6e68ed.png)Figure 2.13 Adding Assets Folder to a new project +![](img/6cf6b889-8ecb-4837-9087-19b34d6e68ed.png) + +Figure 2.13 Adding Assets Folder to a new project 5. 将两个重新训练的模型文件和标签文件以及几个测试图像拖放到资产文件夹中,如下所示: -![](img/fff27710-5222-410c-8d40-f451dea548f8.png)Figure 2.14 Adding model files, the label file and test images to assets +![](img/fff27710-5222-410c-8d40-f451dea548f8.png) + +Figure 2.14 Adding model files, the label file and test images to assets 6. 按住选项按钮,将`tensorflow/examples/android/src/org/tensorflow/demo`和`Classifier.java`从`tensorflow/examples/android/src/org/tensorflow/demo`拖放到项目的 Java 文件夹中,如下所示: -![](img/7f41c4fe-6454-44e2-82d8-892290761eb5.png)Figure 2.15 Adding TensorFlow classifier files to the project +![](img/7f41c4fe-6454-44e2-82d8-892290761eb5.png) + +Figure 2.15 Adding TensorFlow classifier files to the project 7. 打开`MainActivity`,首先创建与重新训练的 MobileNet 模型相关的常数-输入图像大小,节点名称,模型文件名和标签文件名: @@ -847,11 +875,15 @@ final List results = classifier.recognizeImage(croppedBi 为简单起见,我们没有向 Android 应用程序添加任何与 UI 相关的代码,但是您可以在获取结果后在此行设置一个断点,并调试运行该应用程序; 您将看到以下屏幕截图所示的结果: -![](img/4c91b3a9-1a32-4288-aa75-205d0b71d584.png)Figure 2.16 Recognition results using the MobileNet retrained model +![](img/4c91b3a9-1a32-4288-aa75-205d0b71d584.png) + +Figure 2.16 Recognition results using the MobileNet retrained model 如果您通过将`MODEL_FILE`更改为`quantized_stripped_dogs_retrained.pb`,将`INPUT_SIZE`更改为`299`,并且将`INPUT_NAME`更改为`Mul`来使用 Inception v3 训练后的模型,则调试该应用程序,您将获得如下所示的结果 : -![](img/ca49452a-b256-4c9e-8e96-6de4c75effa7.png)Figure 2.17 Recognition results using the Inception v3 retrained model +![](img/ca49452a-b256-4c9e-8e96-6de4c75effa7.png) + +Figure 2.17 Recognition results using the Inception v3 retrained model 既然您已经了解了如何将 TensorFlow 和经过重新训练的模型添加到自己的 iOS 和 Android 应用程序,那么想要添加非 TensorFlow 相关功能(例如使用手机的摄像头拍摄狗的照片和 认识它的品种。 diff --git a/new/intel-mobi-proj-tf/03.md b/new/intel-mobi-proj-tf/03.md index 24594d6f55150b6933d5db5f9ca9a046904167c8..283d93bc326ef8850e1d59e433c1838f0fe5af77 100644 --- a/new/intel-mobi-proj-tf/03.md +++ b/new/intel-mobi-proj-tf/03.md @@ -214,7 +214,9 @@ image_np_expanded = np.expand_dims(image_np, axis=0) 最后,使用`matplotlib`库将检测到的结果可视化。 如果使用`tensorflow/models`存储库随附的默认两个测试图像,则会在图 3.1 中看到结果: -![](img/0df3a5c2-f983-4921-a901-b14c262d34a4.png)Figure 3.1 Detected objects with bounding boxes and confidence scores +![](img/0df3a5c2-f983-4921-a901-b14c262d34a4.png) + +Figure 3.1 Detected objects with bounding boxes and confidence scores 在“在 iOS 中使用对象检测模型”部分,我们将了解如何在 iOS 设备上使用相同的模型并绘制相同的检测结果。 @@ -383,11 +385,15 @@ python object_detection/eval.py \ 9. 打开另一个终端窗口,在 TensorFlow 根目录下打开`cd`,然后打开`models/research`,然后运行`tensorboard --logdir=.`。 在浏览器中,打开`http://localhost:6006`,您将看到损失图,如图 3.2 所示: -![](img/539aa2c8-da68-42e8-ad74-ad3f2a25e07f.png)Figure 3.2 Total loss trend when retraining an object detection model +![](img/539aa2c8-da68-42e8-ad74-ad3f2a25e07f.png) + +Figure 3.2 Total loss trend when retraining an object detection model 您还将看到一些评估结果,如图 3.3 所示: -![](img/ee6c4a9d-473f-429c-a7e2-df3162500502.png)Figure 3.3 Evaluation image detection results when retraining an object detection model +![](img/ee6c4a9d-473f-429c-a7e2-df3162500502.png) + +Figure 3.3 Evaluation image detection results when retraining an object detection model 10. 同样,您可以为`SSD_MobileNet`模型运行评估脚本,然后使用 TensorBoard 查看其损失趋势和评估图像结果: @@ -469,7 +475,9 @@ If you run the app, after completing the following steps, and encounter an error 1. 在 Xcode 中,单击“文件 | 新增 | 项目…”,选择“Single View App”,然后输入 TFObjectDetectionAPI 作为产品名称,然后选择 Objective-C 作为 语言(如果您想使用 Swift,请参阅上一章有关如何将 TensorFlow 添加到基于 Swift 的 iOS 应用并进行此处所示的必要更改),然后选择项目的位置并单击“创建”。 2. 在`TFObjectDetectionAPI`项目中,单击项目名称,然后在构建设置下,单击`+`并添加用户定义的设置,然后输入`TENSORFLOW_ROOT`作为 TensorFlow 源根的路径(例如`$HOME/tensorflow-1.4`),如图 3.4 所示。 如果您要引用较新的 TensorFlow 来源,此用户定义的设置将在其他设置中使用,以便以后轻松更改项目设置: -![](img/a8474e70-b35d-4585-a9f9-620aa6cff313.png)Figure 3.4 Adding a TENSORFLOW_ROOT user-defined setting +![](img/a8474e70-b35d-4585-a9f9-620aa6cff313.png) + +Figure 3.4 Adding a TENSORFLOW_ROOT user-defined setting 3. 单击目标,然后在“构建设置”下搜索“其他链接器标志”。 向其添加以下值: @@ -489,11 +497,15 @@ $(TENSORFLOW_ROOT) $(TENSORFLOW_ROOT)/tensorflow/contrib/makefile/downloads/prot 之后,您会看到类似图 3.5 的内容: -![](img/bae0f128-065f-4267-b1cc-b2450650e8d7.png)Figure 3.5 Adding all TensorFlow-related build settings for the target +![](img/bae0f128-065f-4267-b1cc-b2450650e8d7.png) + +Figure 3.5 Adding all TensorFlow-related build settings for the target 5. 在目标的“构建阶段”中,在带库的链接二进制文件中添加 Accelerate 框架,如图 3.6 所示: -![](img/3c92f162-ad1d-4718-a72f-07f10ebc71fa.png)Figure 3.6 Adding the Accelerate framework +![](img/3c92f162-ad1d-4718-a72f-07f10ebc71fa.png) + +Figure 3.6 Adding the Accelerate framework 6. 返回用于构建 TensorFlow iOS 库的终端,在`tensorflow/core/platform/default/mutex.h`中找到以下两行代码: @@ -535,7 +547,9 @@ cd /models/research/object_detection/protos 5. `protoc`编译器命令完成后,您将在项目的源目录中看到两个文件:`string_int_label_map.pb.cc`和`string_int_label_map.pb.h`。 将两个文件添加到 Xcode 项目中。 6. 在 Xcode 中,像在上一章中一样,将`ViewController.m`重命名为`ViewController.mm`,然后类似于第 2 章,“通过迁移学习对图像进行分类”的`HelloTensorFlow`应用的`ViewController.mm`,在点击的处理程序中为三个对象检测模型添加三个`UIAlertAction`,我们已将模型添加到项目中并将要测试。 现在,完整的项目文件应如图 3.7 所示: -![](img/7023289e-ae57-4518-920e-140985314d13.png)Figure 3.7 The TFObjectDetection API project files +![](img/7023289e-ae57-4518-920e-140985314d13.png) + +Figure 3.7 The TFObjectDetection API project files 7. 继续在`ViewController.mm`中添加其余代码。 在`viewDidLoad`中,添加以编程方式创建新`UIImageView`的代码,以首先显示测试图像,并在选择了特定模型以在测试图像上运行之后显示检测到的结果,然后添加以下功能实现: @@ -552,7 +566,9 @@ void RunInferenceOnImage(NSString *model) 8. 在 iOS 模拟器或设备中运行该应用。 首先,您会在屏幕上看到一张图片。 点按任意位置,您将看到一个对话框,要求您选择模型。 选择`SSD MobileNet`型号,在模拟器中花费大约一秒钟,在 iPhone 6 上花费五秒钟,以在图像上绘制检测结果。 Faster RCNN Inception V2 需要更长的时间(在模拟器中大约需要 5 秒,在 iPhone 6 上大约需要 20 秒); 该模型也比`SSD MobileNet`更精确,可以捕获`SSD MobileNet`模型遗漏的一个狗物体。 最后一个型号,更快的 RCNN Resnet 101,在 iOS 模拟器中花费了将近 20 秒,但由于其尺寸而在 iPhone 6 上崩溃。 图 3.8 总结了运行结果: -![](img/411e68db-3026-4ba4-964a-3d9a174dce6f.png)Figure 3.8 Running the app with different models and showing detection results +![](img/411e68db-3026-4ba4-964a-3d9a174dce6f.png) + +Figure 3.8 Running the app with different models and showing detection results 返回步骤 7 中的功能,`FilePathForResourceName`功能是用于返回资源文件路径的帮助程序功能:`mscoco_label_map.pbtxt`文件,该文件定义了要检测的 90 个对象类的 ID,内部名称和显示名称。 ,模型图文件和测试图像。 它的实现与我们在上一章的`HelloTensorFlow`应用中看到的实现相同。 @@ -629,7 +645,9 @@ num_detections: 100, detection_scores size: 100, detection_classes size: 100, de 而已。 运行该应用程序,您可以看到针对重新训练的模型对检测到的结果进行了更精细的调整。 例如,使用通过使用牛津宠物数据集进行重新训练而生成的前面的重新训练模型,我们希望看到边界框围绕头部区域而不是整个身体,而这正是我们在图 3.9 中所示的测试图像所看到的: -![](img/ced173a8-1b82-4868-a274-3cdf666556e1.png)Figure 3.9 Comparing detected results of pre-trained and retrained models +![](img/ced173a8-1b82-4868-a274-3cdf666556e1.png) + +Figure 3.9 Comparing detected results of pre-trained and retrained models @@ -675,7 +693,9 @@ python tensorflow/tools/quantization/quantize_graph.py --input=darkflow/built_gr 1. 将`quantized_tiny-yolo-voc.pb`和`quantized_tiny-yolo.pb`都拖到`TFObjectDetectionAPI`项目中 2. 在`ViewController.mm`中添加两个新的警报操作,因此在运行该应用程序时,您将看到可用于运行的模型,如图 3.10 所示: -![](img/532a45ca-35ee-452b-b33a-79d557fee667.png)Figure 3.10 Adding two YOLO models to the iOS app +![](img/532a45ca-35ee-452b-b33a-79d557fee667.png) + +Figure 3.10 Adding two YOLO models to the iOS app 3. 添加以下代码以将输入图像处理到张量中以馈送到输入节点,并在加载了 YOLO 模型图的情况下运行 TensorFlow 会话以生成检测输出: diff --git a/new/intel-mobi-proj-tf/04.md b/new/intel-mobi-proj-tf/04.md index 4e4703babc827e355bf630e1d17f93b55ddac932..a7955c0502218a62cc99f204e3cafff386ef9ac1 100644 --- a/new/intel-mobi-proj-tf/04.md +++ b/new/intel-mobi-proj-tf/04.md @@ -56,7 +56,9 @@ python style.py --style images/starry_night.jpg --test images/ww1.jpg --test-dir `images`目录中还有一些其他样式的图像,可用于创建不同的检查点文件。 此处使用的`starry_night.jpg`样式图片是梵高的一幅著名画作,如图 4.1 所示: -![](img/ea1f4494-b7f4-4be2-a897-adfcbc4f0ef4.jpg)Figure 4.1 Using Van Gogh's painting as the style image +![](img/ea1f4494-b7f4-4be2-a897-adfcbc4f0ef4.jpg) + +Figure 4.1 Using Van Gogh's painting as the style image 在第 1 章, “移动 TensorFlow 入门”中设置的 NVIDIA GTX 1070 GPU 驱动的 Ubuntu 上,整个训练大约需要 5 个小时,并且在 CPU 上肯定要花更长的时间 。 @@ -144,11 +146,15 @@ $(TENSORFLOW_ROOT) $(TENSORFLOW_ROOT)/tensorflow/contrib/makefile/downloads/prot 4. 在 iOS 模拟器或 iOS 设备上运行该应用程序,您将看到一张狗图片,如图 4.2 所示: -![](img/9bdc2a19-7e59-4f72-b41f-ea3eeba0c5c5.png)Figure 4.2 The original dog picture before style applied +![](img/9bdc2a19-7e59-4f72-b41f-ea3eeba0c5c5.png) + +Figure 4.2 The original dog picture before style applied 5. 点击以选择快速样式转移,几秒钟后,您将在图 4.3 中看到一张新图片,其中已转移了繁星点点的夜色: -![](img/a78207bb-2407-4343-b84d-2f17aacfd4ff.png)Figure 4.3 Like having Van Gogh draw your favorite dog +![](img/a78207bb-2407-4343-b84d-2f17aacfd4ff.png) + +Figure 4.3 Like having Van Gogh draw your favorite dog 您只需选择喜欢的图片作为样式图像,然后按照上一节中的步骤操作,即可轻松构建具有不同样式的其他模型。 然后,您可以按照本节中的步骤在 iOS 应用中使用模型。 如果您想了解模型的训练方法,则应在上一节的 GitHub 存储库 中查看代码。 让我们详细看一下使用该模型完成魔术的 iOS 代码。 @@ -412,7 +418,9 @@ mHandler.sendMessage(msg); 因此,总共不到 100 行代码,您就有了一个完整的 Android 应用程序,可以对图像进行惊人的样式转换。 在 Android 设备或虚拟设备上运行该应用程序,首先将看到一个带有按钮的测试图像,点击该按钮,几秒钟后,您将看到样式转换的图像,如图 4.4 所示: -![](img/07ef305b-1e23-4a4c-98f5-faf14f398d65.png)Figure 4.4 The original image and style transferred image on Android +![](img/07ef305b-1e23-4a4c-98f5-faf14f398d65.png) + +Figure 4.4 The original image and style transferred image on Android 快速神经样式模型存在的一个问题是,即使量化后每个模型只有 1.7MB,我们仍然需要针对每种样式分别进行训练,并且每个训练的模型只能支持一种样式转换。 幸运的是,这个问题有很好的解决方案。 @@ -464,7 +472,9 @@ auto image_tensor_mapped = image_tensor.tensor(); 5. 我们还需要将`style_tensor`定义为形状为`[NUM_STYLES * 1]`的另一个张量,其中`NUM_STYLES`在`ViewController.mm`的开头定义为`const int NUM_STYLES = 26;`。 数字 26 是 `stylize_quantized.pb`模型文件中内置的样式数,您可以在其中运行 Android TF 风格化应用并查看 26 种结果,如图 4.5 所示。 请注意,第 20 张图片(左下角的图片)是梵高熟悉的繁星点点的夜晚: -![](img/ea7a04fe-8b56-47b2-ac5a-7f25ced4acbd.png)Figure 4.5 The 26 style images in the multi-style model +![](img/ea7a04fe-8b56-47b2-ac5a-7f25ced4acbd.png) + +Figure 4.5 The 26 style images in the multi-style model ```py tensorflow::Tensor style_tensor(tensorflow::DT_FLOAT, tensorflow::TensorShape({ NUM_STYLES, 1})); @@ -503,19 +513,27 @@ tensorflow::Status run_status = session->Run({{input_layer, image_tensor}, {styl 这些就是使用多样式模型运行 iOS 应用所需的全部更改。 现在运行您的应用程序,您将首先看到如图 4.6 所示的内容: -![](img/f2841f1f-b0c3-412d-822b-5e9d0f34f235.png)Figure 4.6 Showing the original content image +![](img/f2841f1f-b0c3-412d-822b-5e9d0f34f235.png) + +Figure 4.6 Showing the original content image 点击任意位置,您将看到两个样式选择,如图 4.7 所示: -![](img/c462927f-71be-46f1-995f-5cbd536ae175.png)Figure 4.7 Showing the choice of two style models +![](img/c462927f-71be-46f1-995f-5cbd536ae175.png) + +Figure 4.7 Showing the choice of two style models 两张已传输图像的结果,`out_style[19] = 1.0`; 如图 4.8 所示: -![](img/cc28a550-1a66-4845-b330-1c01d3806e62.png)Figure 4.8 The style-transferred results with two different models (fast style transfer on the left, multi-style on the right) +![](img/cc28a550-1a66-4845-b330-1c01d3806e62.png) + +Figure 4.8 The style-transferred results with two different models (fast style transfer on the left, multi-style on the right) 图 4.9 显示了在图 4.5 中使用星夜图像和右上角图像的均等混合以及所有 26 种样式的均等混合的结果,如图 4.9 所示: -![](img/c5dd63f4-32a7-4177-afb8-af0e8a8770e8.png)Figure 4.9 Results of different mixes of multiple styles (half starry night half the other on the left, mix of all 26 styles on the right) +![](img/c5dd63f4-32a7-4177-afb8-af0e8a8770e8.png) + +Figure 4.9 Results of different mixes of multiple styles (half starry night half the other on the left, mix of all 26 styles on the right) 多样式模型在 iPhone 6 上运行大约需要 5 秒钟,比快速样式传输模型运行快大约 2-3 倍。 @@ -603,7 +621,9 @@ for (int i=0; i < intValues.length; ++i) { 将第 20 和第 5 种样式图像按步骤 3 中的代码片段进行均等混合后,原始图像和传输的图像如图 4.10 所示: -![](img/f582db90-6795-43d5-8d6d-28e2835e58de.png)Figure 4.10 The original content image and the style transferred image with a mix of the 5th image and the starry night image +![](img/f582db90-6795-43d5-8d6d-28e2835e58de.png) + +Figure 4.10 The original content image and the style transferred image with a mix of the 5th image and the starry night image 如果替换以下两行代码: @@ -632,7 +652,9 @@ for (int i = 0; i < NUM_STYLES; ++i) { 然后,您将在图 4.11 中看到效果: -![](img/a6009bea-e770-4c76-b7ab-9f426ea66e0b.png)Figure 4.11 Images stylized with the starry night style only and with all the 26 styles mixed equally +![](img/a6009bea-e770-4c76-b7ab-9f426ea66e0b.png) + +Figure 4.11 Images stylized with the starry night style only and with all the 26 styles mixed equally 在一些强大的 TensorFlow 模型的帮助下以及我们如何在移动应用程序中使用它们的知识,看起来我们的移动开发人员也可以成为伟大的艺术家。 diff --git a/new/intel-mobi-proj-tf/05.md b/new/intel-mobi-proj-tf/05.md index df29e2f6e0def4a2eb620b0b99574061deef7f87..fd23b639128413b1fc2c82d60cdee3b6561cfd4c 100644 --- a/new/intel-mobi-proj-tf/05.md +++ b/new/intel-mobi-proj-tf/05.md @@ -386,15 +386,21 @@ runOnUiThread(new Runnable() { 现在,在您的 Android 设备上运行该应用。 您将看到如图 5.1 所示的初始屏幕: -![](img/a321196b-4e44-43ec-94c5-42ee47ea29d9.png)Figure 5.1 Showing the initial screen after app starts +![](img/a321196b-4e44-43ec-94c5-42ee47ea29d9.png) + +Figure 5.1 Showing the initial screen after app starts 点击`START`按钮,然后开始说上面显示的 10 个命令之一。 您将看到按钮标题更改为“侦听...”,然后是“识别...”,如图 5.2 所示: -![](img/f4eb7e04-1d5f-4c70-a91c-055d8cdcb1c6.png)Figure 5.2 Listening to record audio and recognizing the recorded audio +![](img/f4eb7e04-1d5f-4c70-a91c-055d8cdcb1c6.png) + +Figure 5.2 Listening to record audio and recognizing the recorded audio 识别结果几乎实时显示在屏幕中间,如图 5.3 所示: -![](img/bc4d09f3-f7d6-47fa-91f5-d0130635da7c.png)Figure 5.3 Showing the recognized speech commands +![](img/bc4d09f3-f7d6-47fa-91f5-d0130635da7c.png) + +Figure 5.3 Showing the recognized speech commands 整个识别过程几乎立即完成,用于识别的`speech_commands_graph.pb`模型仅为 3.7MB。 当然,它仅支持 10 条语音命令,但是即使使用`train.py`脚本的 `--wanted_words`参数或您自己的数据集支持数十个命令,大小也不会发生太大变化,正如我们在训练部分中讨论的那样。 @@ -601,7 +607,9 @@ return commands[idx]; 现在,在 iOS 模拟器上运行该应用程序(如果您的 Xcode 版本早于 9.2,而 iOS 模拟器版本早于 10.0,则您可能必须在实际的 iOS 设备上运行该应用程序,因为您可能无法在 iOS 中录制音频 模拟器(10.0 之前的版本)或 iPhone,您将首先看到带有 Start 按钮位于中间的初始屏幕,然后点击该按钮并说出 10 个命令之一,识别结果应出现在顶部 ,如图 5.4 所示: -![](img/71ef1770-f7c0-4152-bb72-ea7993f5b728.png)Figure 5.4 Showing the initial screen and recognition result +![](img/71ef1770-f7c0-4152-bb72-ea7993f5b728.png) + +Figure 5.4 Showing the initial screen and recognition result 是的,应该会出现识别结果,但实际上不会出现,因为在 Xcode 输出窗格中会出现错误: @@ -655,7 +663,9 @@ The process on how to fix the "Not found: Op type not registered" error is a big 现在,您在 Xcode 中的应用程序应类似于图 5.5: -![](img/3febd651-7749-4a23-ba86-ae458ef8cfea.png)Figure 5.5 The Swift-based iOS app project +![](img/3febd651-7749-4a23-ba86-ae458ef8cfea.png) + +Figure 5.5 The Swift-based iOS app project 4. 打开`ViewController.swift`。 在`import UIKit`之后的顶部添加以下代码: diff --git a/new/intel-mobi-proj-tf/06.md b/new/intel-mobi-proj-tf/06.md index 1a3dfac853ebc4fd8b56d6031e4a0407bff89cea..0995f8002b23d29d0df075364704cb902bd940fb 100644 --- a/new/intel-mobi-proj-tf/06.md +++ b/new/intel-mobi-proj-tf/06.md @@ -273,15 +273,21 @@ Running the `bazel build` command to build a TensorFlow Python script is optiona 现在我们到了,让我们快速使用 TensorBoard 看一下我们的图形–只需运行`tensorboard --logdir logdir`,然后从浏览器中打开`http://localhost:6006`。 图 6.1 显示了三个输出节点名称(顶部为`softmax`,以及`lstm/initial_state`和红色矩形顶部的突出显示的`lstm/state`)和一个输入节点名称(底部的`state_feed`): -![](img/d47ea13b-441c-4fb1-bccc-bbceaf2a8bdf.png)Figure 6.1: Diagram showing the three output node names and one input node name +![](img/d47ea13b-441c-4fb1-bccc-bbceaf2a8bdf.png) + +Figure 6.1: Diagram showing the three output node names and one input node name 图 6.2 显示了另一个输入节点名称`image_feed`: -![](img/a7c39f91-68d3-4cd4-8e9b-0ef0b6dd11ff.png)Figure 6.2: Diagram showing one additional input node name image_feed +![](img/a7c39f91-68d3-4cd4-8e9b-0ef0b6dd11ff.png) + +Figure 6.2: Diagram showing one additional input node name image_feed 最后,图 6.3 显示了最后一个输入节点名称`input_feed`: -![](img/887360ce-b609-4f8a-95d4-c1c3d2e8f97b.png)Figure 6.3: Diagram showing the last input node name input_feed +![](img/887360ce-b609-4f8a-95d4-c1c3d2e8f97b.png) + +Figure 6.3: Diagram showing the last input node name input_feed 当然,这里有很多我们不能也不会涵盖的细节。 但是,您将了解大局,同样重要的是,有足够的细节可以继续前进。 现在运行`freeze_graph.py`应该像轻风(双关语): @@ -348,7 +354,9 @@ x[:6] 实际上,在图 6.2 中也暗示了对此烦恼的解决方法,其中`convert_image`节点用作`image_feed`输入的解码版本。 为了更准确,单击 TensorBoard 图中的转换和**解码**节点,如图 6.4 所示,您将从右侧的 TensorBoard 信息卡中看到输入转换(名为`convert_image/Cast`)的输出为`decode/DecodeJpeg`和`convert_image`,解码的输入和输出为`image_feed`和`convert_image/Cast`: -![](img/eeb4e7ad-04ef-4ad5-ac89-a9a4a1e2f1e4.png)Figure 6.4: Looking into the decode and conver_image nodes +![](img/eeb4e7ad-04ef-4ad5-ac89-a9a4a1e2f1e4.png) + +Figure 6.4: Looking into the decode and conver_image nodes 实际上,在`im2txt/ops/image_processing.py`中有一行`image = tf.image.convert_image_dtype(image, dtype=tf.float32)`将解码的图像转换为浮点数。 让我们用`convert_image/Cast`代替 TensorBoard 中显示的名称`image_feed`,以及前面代码片段的输出,然后再次运行`strip_unused`: @@ -457,7 +465,9 @@ target 'Image2Text' 2. 添加在上一节末尾生成的两个模型文件,在“训练和测试字幕生成”小节第 2 步中生成的`word_counts.txt`文件,以及一些测试图像–我们保存了 并使用 [TensorFlow im2txt 模型页面](https://github.com/tensorflow/models/tree/master/research/im2txt) )顶部的四个图像,以便我们比较我们的字幕结果 模型,以及那些由模型训练得出的模型,需要经过更多步骤。 还将`ViewController.m`重命名为`.mm`,从现在开始,我们将只处理`ViewController.mm`文件即可完成应用程序。 现在,您的 Xcode `Image2Text`项目应类似于图 6.5: -![](img/62be062e-39dc-4f0c-8a59-7e0e675bafaa.png)Figure 6.5: Setting up the Image2Text iOS app, also showing how LoadMemoryMappedModel is implemented +![](img/62be062e-39dc-4f0c-8a59-7e0e675bafaa.png) + +Figure 6.5: Setting up the Image2Text iOS app, also showing how LoadMemoryMappedModel is implemented 3. 打开`ViewController.mm`并添加一堆 Objective-C 和 C++ 常量,如下所示: @@ -675,17 +685,23 @@ return sentence; 这就是在 iOS 应用程序中运行模型所需的一切。 现在,在 iOS 模拟器或设备中运行该应用程序,点击并选择一个模型,如图 6.6 所示: -![](img/dd9bd09b-1b39-47ff-8a8f-f7f180faff3c.png)Figure 6.6: Running the Image2Text iOS app and selecting a model +![](img/dd9bd09b-1b39-47ff-8a8f-f7f180faff3c.png) + +Figure 6.6: Running the Image2Text iOS app and selecting a model 在 iOS 模拟器上,运行非映射模型需要 10 秒钟以上,运行映射模型则需要 5 秒钟以上。 在 iPhone 6 上,运行贴图模型还需要大约 5 秒钟,但由于模型文件和内存压力较大,运行非贴图模型时会崩溃。 至于结果,图 6.7 显示了四个测试图像结果: -![](img/59f462cb-59e6-4165-bd6f-80166f84bd61.png)Figure 6.7: Showing the image captioning results +![](img/59f462cb-59e6-4165-bd6f-80166f84bd61.png) + +Figure 6.7: Showing the image captioning results 图 6.8 显示了 TensorFlow im2txt 网站上的结果,您可以看到我们更简单的贪婪搜索结果看起来也不错。 但是对于长颈鹿图片,看来我们的模型或推理代码不够好。 完成本章中的工作后,希望您会在改进训练或模型推断方面有所收获: -![](img/e08dec95-3b49-432a-bc4f-e3077151f2e9.png)Figure 6.8: The example captioning results in the TensorFlow im2txt model website +![](img/e08dec95-3b49-432a-bc4f-e3077151f2e9.png) + +Figure 6.8: The example captioning results in the TensorFlow im2txt model website 在我们进行下一个智能任务之前,是时候给 Android 开发人员一个不错的选择了。 @@ -924,7 +940,9 @@ mHandler.sendMessage(msg); 在您的虚拟或真实 Android 设备上运行该应用。 大约需要 10 秒钟才能看到结果。 您可以使用上一节中显示的四个不同的测试图像,并在图 6.9 中查看结果: -![](img/249e6bc8-7f89-45d4-a217-2cf1c54bf5fe.png)Figure 6.9: Showing image captioning results in Android +![](img/249e6bc8-7f89-45d4-a217-2cf1c54bf5fe.png) + +Figure 6.9: Showing image captioning results in Android 一些结果与 iOS 结果以及 TensorFlow im2txt 网站上的结果略有不同。 但是它们看起来都不错。 另外,在相对较旧的 Android 设备(例如 Nexus 5)上运行该模型的非映射版本也可以。 但是最好在 Android 中加载映射模型,以查看性能的显着提高,我们可能会在本书后面的章节中介绍。 diff --git a/new/intel-mobi-proj-tf/07.md b/new/intel-mobi-proj-tf/07.md index e6319b2515d77de026e220224b9e7bc6f8657b75..05a1ba5f2763c6fbf91b290d219dfd181222ee0f 100644 --- a/new/intel-mobi-proj-tf/07.md +++ b/new/intel-mobi-proj-tf/07.md @@ -32,7 +32,9 @@ [TensorFlow 教程](https://www.tensorflow.org/tutorials/recurrent_quickdraw)中内置的图纸分类模型首先将表示为点列表的用户图纸输入转换为张量 连续点的增量以及有关每个点是否是新笔画的开始的信息。 然后将张量穿过几个卷积层和 LSTM 层,最后穿过 softmax 层,如图 7.1 所示,以对用户图形进行分类: -![](img/ef475044-6568-4e50-bc98-8ff0a0d6efbf.png)Figure 7.1: The drawing classification mode +![](img/ef475044-6568-4e50-bc98-8ff0a0d6efbf.png) + +Figure 7.1: The drawing classification mode 与接受 2D 图像输入的 2D 卷积 API `tf.layers.conv2d` 不同,此处将 1D 卷积 API `tf.layers.conv1d`用于时间卷积(例如绘图)。 默认情况下,在图形分类模型中,使用三个 1D 卷积层,每个层具有 48、64 和 96 个过滤器,其长度分别为 5、5 和 3。 卷积层之后,将创建 3 个 LSTM 层,每层具有 128 个正向`BasicLSTMCell`节点和 128 个反向`BasicLSTMCell`节点,然后将其用于创建动态双向循环神经网络,该网络的输出将发送到最终的完全连接层以计算`logits`(非标准化的对数概率)。 @@ -83,7 +85,9 @@ drwxr-xr-x 2 jeff jeff 4096 Feb 12 00:11 eval 如果您运行`tensorboard --logdir quickdraw_model`,然后从浏览器在`http://localhost:6006`上启动 TensorBoard,您会看到精度达到约 0.55,损失到约 2.0。 如果继续进行约 200k 的训练,则精度将提高到约 0.65,损失将下降到 1.3,如图 7.2 所示: -![](img/479a1d37-1775-459d-a616-c45f2f10f0f1.png)Figure 7.2: The accuracy and loss of the model after 300k training steps +![](img/479a1d37-1775-459d-a616-c45f2f10f0f1.png) + +Figure 7.2: The accuracy and loss of the model after 300k training steps 现在,我们可以像上一章一样运行`freeze_graph.py`工具,以生成用于移动设备的模型文件。 但是在执行此操作之前,我们首先来看一下如何在 Python 中使用该模型进行推断,例如上一章中的`run_inference.py`脚本。 @@ -189,7 +193,9 @@ def predict_input_fn(): 让我们使用 TensorBoard 看看我们能找到什么。 在我们模型的 TensorBoard 视图的 GRAPHS 部分中,您可以看到,如图 7.3 所示,以红色突出显示的`BiasAdd`节点是使用的`ArgMax`操作的输入 计算精度以及 softmax 操作的输入。 我们可以使用`SparseSoftmaxCrossEntropyWithLogits`(图 7.3 仅显示为`SparseSiftnaxCr ...`)操作,也可以仅使用`Dense`/`BiasAdd`作为输出 节点名称,但我们将`ArgMax`和`Dense`/`BiasAdd`用作`freeze_graph`工具的两个输出节点名称,因此我们可以更轻松地查看 最终密集层的输出以及`ArgMax`结果: -![](img/d911bab2-cfc2-41d3-a352-d00db55b1f71.png)Figure 7.3: Showing possible output node names of the model +![](img/d911bab2-cfc2-41d3-a352-d00db55b1f71.png) + +Figure 7.3: Showing possible output node names of the model 用您的`graph.pbtxt`文件的路径和最新的模型检查点前缀替换`--input_graph`和`--input_checkpoint`值后,在 TensorFlow 根目录中运行以下脚本以获取冻结的图: @@ -201,12 +207,16 @@ python tensorflow/python/tools/freeze_graph.py --input_graph=/tmp/graph.pbtxt - 我们在前面的小节中讨论了`OneShotIterator`的含义。 回到 TensorBoard `GRAPHS`部分,我们可以看到`OneShotIterator`(如图 7.4 所示),该区域以红色突出显示,并且还显示在右下方的信息面板中,在图表的底部,以及上方的几个层次中,有一个 `Reshape`操作用作第一卷积层的输入: -![](img/a88ae370-8a39-4ee3-8ce0-ebaa5fd8a8ed.png)Figure 7.4: Finding out possible input node namesYou may wonder why we can't fix the `Not found: Op type not registered 'OneShotIterator'` error with a technique we used before, which is to first find out which source file contains the op using the command `grep 'REGISTER.*"OneShotIterator"' tensorflow/core/ops/*.cc` +![](img/a88ae370-8a39-4ee3-8ce0-ebaa5fd8a8ed.png) + +Figure 7.4: Finding out possible input node namesYou may wonder why we can't fix the `Not found: Op type not registered 'OneShotIterator'` error with a technique we used before, which is to first find out which source file contains the op using the command `grep 'REGISTER.*"OneShotIterator"' tensorflow/core/ops/*.cc` (and you'll see the output as `tensorflow/core/ops/dataset_ops.cc:REGISTER_OP("OneShotIterator")`) then add `tensorflow/core/ops/dataset_ops.cc` to `tf_op_files.txt` and rebuild the TensorFlow library. Even if this were feasible, it would complicate the solution as now we need to feed the model with some data related to `OneShotIterator`, instead of the direct user drawing in points. 此外,在右侧上方一层(图 7.5),还有另一种操作 `Squeeze` ,它是 `rnn_classification` 子图的输入: -![](img/6230229e-1c21-4280-b60a-cac640c1cb1f.png)Figure 7.5: Further research to find out input node names +![](img/6230229e-1c21-4280-b60a-cac640c1cb1f.png) + +Figure 7.5: Further research to find out input node names 我们不必担心`Reshape`右侧的`Shape`运算,因为它实际上是`rnn_classification`子图的输出。 因此,所有这些研究背后的直觉是,我们可以使用`Reshape`和`Squeeze`作为两个输入节点,然后使用在上一章中看到的`transform_graph` 工具,我们应该能够删除 `Reshape`和`Squeeze`以下的节点,包括`OneShotIterator`。 @@ -225,7 +235,9 @@ strip_unused_nodes(name=Squeeze,type_for_name=int64,shape_for_name="8",name=Resh 即使我们不确切知道它的用途,我们也可以确保它与模型推断无关,该模型推断只需要一些输入(图 7.4 和图 7.5)并生成图形分类作为输出(图 7.3)。 : -![](img/6cc9946c-dfb2-41de-af95-a35e47d405a7.png)Figure 7.6: Finding out nodes causing model loading error but not related to model inference +![](img/6cc9946c-dfb2-41de-af95-a35e47d405a7.png) + +Figure 7.6: Finding out nodes causing model loading error but not related to model inference 那么,如何摆脱`global_step`以及其他相关的`cond`节点,由于它们的隔离性,它们不会被变换图工具剥离掉? 幸运的是,`freeze_graph`脚本支持这一点 – [仅在其源代码中记录](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/python/tools/freeze_graph.py)。 我们可以为脚本使用`variable_names_blacklist`参数来指定应在冻结模型中删除的节点: @@ -319,7 +331,9 @@ tensorflow/core/kernels/random_op.cc 还将`ViewController.m`重命名为`ViewController.mm`,并在`tensorflow_util.h`中注释`GetTopN`函数定义,并在`tensorflow_util.mm`中注释其实现,因为我们将在`ViewController.mm`中实现修改后的版本。 您的项目现在应如图 7.7 所示: -![](img/ee464972-a065-4400-aea9-72ce9306b901.png)Figure 7.7: Showing the QuickDraw Xcode project with initial content of ViewController.mm +![](img/ee464972-a065-4400-aea9-72ce9306b901.png) + +Figure 7.7: Showing the QuickDraw Xcode project with initial content of ViewController.mm 我们现在准备单独处理`ViewController.mm`,以完成我们的任务。 @@ -609,7 +623,9 @@ void normalizeScreenCoordinates(NSMutableArray *allPoints, float *normalized) { 现在,您可以在 iOS 模拟器或设备中运行该应用程序,开始绘图,并查看模型认为您正在绘图的内容。 图 7.8 显示了一些图纸和分类结果–不是最佳图纸,而是整个过程! -![](img/48678dd2-0490-4b97-a0a6-fa4ba52bc27b.png)Figure 7.8: Showing drawing and classification results on iOS +![](img/48678dd2-0490-4b97-a0a6-fa4ba52bc27b.png) + +Figure 7.8: Showing drawing and classification results on iOS @@ -675,7 +691,9 @@ When using a manually built native library in an Android app, you need to let th 构建完成后,您将在`bazel-bin/tensorflow/contrib/android`文件夹中看到 TensorFlow 本机库文件`libtensorflow_inference.so`。 将其拖到`android/app/src/main/jniLibs/armeabi-v7a`或 `android/app/src/main/jniLibs/x86_64`的`app`文件夹中,如图 7.9 所示: -![](img/0865ad60-dece-4349-9825-24ca46220d07.png)Figure 7.9: Showing the TensorFlow native library file +![](img/0865ad60-dece-4349-9825-24ca46220d07.png) + +Figure 7.9: Showing the TensorFlow native library file 4. 通过运行以下命令构建 TensorFlow 本机库的 Java 接口: @@ -685,7 +703,9 @@ bazel build //tensorflow/contrib/android:android_tensorflow_inference_java 这将在`bazel-bin/tensorflow/contrib/android`处生成文件`libandroid_tensorflow_inference_java.jar`。 将文件移动到 `android/app/lib`文件夹,如图 7.10 所示: -![](img/51e4c597-7447-4623-8e07-396b56faddfa.png)Figure 7.10: Showing the Java interface file to the TensorFlow library +![](img/51e4c597-7447-4623-8e07-396b56faddfa.png) + +Figure 7.10: Showing the Java interface file to the TensorFlow library 现在,我们准备在 Android 中编码和测试模型。 @@ -1009,13 +1029,17 @@ private double[] normalizeScreenCoordinates() { 在您的 Android 模拟器或设备上运行该应用,并享受分类结果的乐趣。 您应该看到类似图 7.11 的内容: -![](img/560fa3a2-94a9-4f93-ae05-bd09921b8e0c.png)Figure 7.11: Showing drawing and classification results on Android +![](img/560fa3a2-94a9-4f93-ae05-bd09921b8e0c.png) + +Figure 7.11: Showing drawing and classification results on Android 既然您已经了解了训练 Quick Draw 模型的全过程,并在 iOS 和 Android 应用程序中使用了它,那么您当然可以微调训练方法,使其更加准确,并改善移动应用程序的乐趣。 在本章我们不得不结束有趣旅程之前的最后一个提示是,如果您使用错误的 ABI 构建适用于 Android 的 TensorFlow 本机库,您仍然可以从 Android Studio 构建和运行该应用程序,但您将 出现运行时错误`java.lang.RuntimeException: Native TF methods not found; check that the correct native libraries are present in the APK.`,这意味着您的应用程序的`jniLibs`文件夹中没有正确的 TensorFlow 本机库(图 7.9)。 要找出`jniLibs`内特定 ABI 文件夹中是否缺少该文件,可以从`Android Studio | View | Tool Windows`中打开`Device File Explorer`,然后选择设备的`data | app | package | lib`来查看,如图 7.12 所示。 如果您更喜欢命令行,则也可以使用`adb`工具找出来。 -![](img/16494075-d42a-4b86-a48a-4cb0bc2ec865.png)Figure 7.12: Checking out the TensorFlow native library file with Device File Explorer +![](img/16494075-d42a-4b86-a48a-4cb0bc2ec865.png) + +Figure 7.12: Checking out the TensorFlow native library file with Device File Explorer diff --git a/new/intel-mobi-proj-tf/08.md b/new/intel-mobi-proj-tf/08.md index cfd8062393257a1357bc99f138cee859b020682c..622e0b2b5ccdc3114d94e9a2a61211fa6582ed01 100644 --- a/new/intel-mobi-proj-tf/08.md +++ b/new/intel-mobi-proj-tf/08.md @@ -269,7 +269,9 @@ You can replace BasicRNNCell in step 4 with BasicLSTMCell and run the training c 现在运行代码将显示如图 8.1 所示,正确预测的比率为 56.25% : -![](img/71f57975-9e80-4886-a13f-7a38b52dc84d.png)Figure 8.1 Showing the stock price prediction correctness trained with TensorFlow RNN +![](img/71f57975-9e80-4886-a13f-7a38b52dc84d.png) + +Figure 8.1 Showing the stock price prediction correctness trained with TensorFlow RNN 注意,每次运行此训练和测试代码时,您获得的比率可能都会有所不同。 通过微调模型的超参数,您可能会获得超过 60% 的比率,这似乎比随机预测要好。 如果您乐观的话,您可能会认为至少有 50% (56.25%)的东西要显示出来,并且可能希望看到该模型在移动设备上运行。 但首先让我们看看是否可以使用酷的 Keras 库来构建更好的模型-在执行此操作之前,让我们通过简单地运行来冻结经过训练的 TensorFlow 模型: @@ -516,7 +518,9 @@ plt.show() 您会看到类似图 8.2 的内容: -![](img/b8227667-1d0d-4ea7-bf0b-fa7dac192064.png)Figure 8.2 Making stock price predictions with the Keras bidirectional and stacked LSTM layers +![](img/b8227667-1d0d-4ea7-bf0b-fa7dac192064.png) + +Figure 8.2 Making stock price predictions with the Keras bidirectional and stacked LSTM layers 很容易在堆栈中添加更多 LSTM 层,或者使用诸如学习率和辍学率以及许多恒定设置之类的超参数。 但是,对于使用`pred_len`和`shift_pred`的不同设置,正确率的差异还没有发现。 也许我们现在应该对接近 60% 的正确率感到满意,并看看如何在 iOS 和 Android 上使用 TensorFlow 和 Keras 训练的模型-我们可以在以后继续尝试改进模型,但是 了解使用 TensorFlow 和 Keras 训练的 RNN 模型是否会遇到任何问题将非常有价值。 @@ -540,7 +544,9 @@ python tensorflow/python/tools/freeze_graph.py --input_meta_graph=/tmp/keras_amz 我们不会通过重复项目设置步骤来烦您-只需按照我们之前的操作即可创建一个名为 StockPrice 的新 Objective-C 项目,该项目将使用手动构建的 TensorFlow 库(请参阅第 7 章,“使用 CNN 和 LSTM 识别图形”的 iOS 部分(如果需要详细信息)。 然后将两个`amzn_tf_frozen.pb`和`amzn_keras_frozen.pb` 模型文件 添加到项目中,您应该在 Xcode 中拥有 StockPrice 项目,如图 8.3 所示: -![](img/454020d6-1f32-480d-b159-b474b6878540.png)Figure 8.3 iOS app using the TensorFlow- and Keras-trained models in Xcode +![](img/454020d6-1f32-480d-b159-b474b6878540.png) + +Figure 8.3 iOS app using the TensorFlow- and Keras-trained models in Xcode 在`ViewController.mm`中,我们将首先声明一些变量和一个常量: @@ -681,7 +687,9 @@ const int SEQ_LEN = 20; 如果您现在运行该应用程序并点击`Predict`按钮,您将看到型号选择消息(图 8.4): -![](img/067fa448-a497-4f13-944f-e976240694c9.png)Figure 8.4 Selecting the TensorFlow or Keras RNN model +![](img/067fa448-a497-4f13-944f-e976240694c9.png) + +Figure 8.4 Selecting the TensorFlow or Keras RNN model 如果选择 TensorFlow 模型,则可能会出现错误: @@ -703,11 +711,15 @@ Could not create TensorFlow Graph: Invalid argument: No OpKernel was registered 现在选择 TensorFlow 模型,您将看到如图 8.5 所示的结果: -![](img/28715473-1f89-4f14-8e81-f98242a11c8d.png)Figure 8.5 Predicting with the TensorFlow RNN model +![](img/28715473-1f89-4f14-8e81-f98242a11c8d.png) + +Figure 8.5 Predicting with the TensorFlow RNN model 使用 Keras 模型输出不同的预测,如图 8.6 所示: -![](img/4114a6b9-15da-41f7-b535-bf04c7fb4dad.png)Figure 8.6 Predicting with the Keras RNN model +![](img/4114a6b9-15da-41f7-b535-bf04c7fb4dad.png) + +Figure 8.6 Predicting with the Keras RNN model 我们无法确定哪个模型能在没有进一步研究的情况下更好地工作,但是我们可以确定的是,我们的两个 RNN 模型都使用 TensorFlow 和 Keras API 从头开始训练了,其准确性接近 60%, 在 iOS 上运行良好,这很值得我们付出努力,因为我们正在尝试建立一个许多专家认为将达到与随机选择相同的性能的模型,并且在此过程中,我们学到了一些新奇的东西-使用 TensorFlow 和 Keras 构建 RNN 模型并在 iOS 上运行它们。 在下一章中,我们只剩下一件事了:如何在 Android 上使用模型? 我们会遇到新的障碍吗? @@ -844,7 +856,9 @@ public void run() { 现在运行该应用程序,然后点击`TF PREDICTION`按钮,您将在图 8.7 中看到结果: -![](img/8ce6016b-658a-46c4-a051-04c772d503fc.png)Figure 8.7 Using the TensorFlow model to make stock price predictions on Amazon +![](img/8ce6016b-658a-46c4-a051-04c772d503fc.png) + +Figure 8.7 Using the TensorFlow model to make stock price predictions on Amazon 选择 KERAS 预测将为您提供如图 8.8 所示的结果: diff --git a/new/intel-mobi-proj-tf/09.md b/new/intel-mobi-proj-tf/09.md index 3775f79ab13c5ca9aeb884f5bcfdd48bd7bbbbac..5c146e4b7a0bba94115dc03d6037c079d98be5f8 100644 --- a/new/intel-mobi-proj-tf/09.md +++ b/new/intel-mobi-proj-tf/09.md @@ -251,7 +251,9 @@ if a.mode == "test": 图 9.1 显示了原始测试图像,其模糊版本以及经过训练的 GAN 模型的生成器输出。 结果并不理想,但是 GAN 模型确实具有更好的分辨率而没有模糊效果: -![](img/b73deef3-1598-4019-ac72-5c0212d53c74.png)Figure 9.1: The original, the blurry, and the generated +![](img/b73deef3-1598-4019-ac72-5c0212d53c74.png) + +Figure 9.1: The original, the blurry, and the generated 10. 现在,将`newckpt`目录复制到`/tmp`,我们可以如下冻结模型: @@ -328,7 +330,9 @@ No OpKernel was registered to support Op 'FIFOQueueV2' with these attrs. Registe 现在,您的 Xcode 应该类似于图 9.2: -![](img/9cb1fa66-5a4e-4a1b-aa51-a16fd9051f57.png)Figure 9.2: Showing the GAN app in Xcode +![](img/9cb1fa66-5a4e-4a1b-aa51-a16fd9051f57.png) + +Figure 9.2: Showing the GAN app in Xcode 我们将创建一个按钮,在点击该按钮时,提示用户选择一个模型以生成数字或增强图像: @@ -539,13 +543,17 @@ No OpKernel was registered to support Op 'FIFOQueueV2' with these attrs. Registe 现在,在 iOS 模拟器或设备中运行该应用程序,点击 GAN 按钮,然后选择生成数字,您将看到 GAN 生成的手写数字的结果,如图 9.3 所示: -![](img/0e0f47b1-2efa-4ec0-9eaa-4b21356cad23.png)Figure 9.3: Showing GAN model selection and results of generated handwritten digits +![](img/0e0f47b1-2efa-4ec0-9eaa-4b21356cad23.png) + +Figure 9.3: Showing GAN model selection and results of generated handwritten digits 这些数字看起来很像真实的人类手写数字,都是在训练了基本 GAN 模型之后完成的。 如果您返回并查看进行训练的代码,并且停下来思考一下 GAN 的工作原理,一般来说,则生成器和判别器如何相互竞争,以及 尝试达到稳定的纳什均衡状态,在这种状态下,生成器可以生成区分器无法分辨出真实还是伪造的真实假数据,您可能会更欣赏 GAN 的魅力。 现在,让我们选择`Enhance Image`选项,您将在图 9.4 中看到结果,该结果与图 9.1 中的 Python 测试代码生成的结果相同: -![](img/63898b4a-4c1d-4605-9fa3-97c8aa00c968.png)Figure 9.4: The original blurry and enhanced images on iOS +![](img/63898b4a-4c1d-4605-9fa3-97c8aa00c968.png) + +Figure 9.4: The original blurry and enhanced images on iOS 你知道该怎么做。 是时候将我们的爱献给 Android 了。 @@ -561,7 +569,9 @@ No OpKernel was registered to support Op 'FIFOQueueV2' with these attrs. Registe 现在,您在 Android Studio 中的项目应如图 9.5 所示: -![](img/f1c741dd-1fc6-41da-9243-3b0840aa9b20.png)Figure 9.5: Android Studio GAN app overview, showing constant definitions +![](img/f1c741dd-1fc6-41da-9243-3b0840aa9b20.png) + +Figure 9.5: Android Studio GAN app overview, showing constant definitions 请注意,为简单起见,我们将`BATCH_SIZE`设置为 1。您可以轻松地将其设置为任何数字,并像在 iOS 中一样获得很多输出。 除了图 9.5 中定义的常量之外,我们还将创建一些实例变量: @@ -710,7 +720,9 @@ void runMNISTModel() { 如果现在运行该应用程序,并使用`void runPix2PixBlurryModel() {}`的空白实现来避免生成错误,则在单击`GENERATE DIGITS`后会看到初始屏幕和结果,如图 9.6 所示: -![](img/1b2a1b02-e084-40bf-a33d-ce5561a34850.png)Figure 9.6: Showing the generated digits +![](img/1b2a1b02-e084-40bf-a33d-ce5561a34850.png) + +Figure 9.6: Showing the generated digits @@ -779,7 +791,9 @@ void runPix2PixBlurryModel() { 再次运行该应用程序,然后立即点击增强图像按钮,您将在几秒钟内看到图 9.7 中的增强图像: -![](img/7e7c6110-09d5-4908-bfaa-e9b5b67596d3.png)Figure 9.7: The blurry and enhanced images on Android +![](img/7e7c6110-09d5-4908-bfaa-e9b5b67596d3.png) + +Figure 9.7: The blurry and enhanced images on Android 这使用两个 GAN 模型完成了我们的 Android 应用程序。 diff --git a/new/intel-mobi-proj-tf/10.md b/new/intel-mobi-proj-tf/10.md index 0856acb504ef828abc6b1bbab5fa9aa7b0b130ea..ad6fe5de3a89826c950faa52b9209d5871c4cd0b 100644 --- a/new/intel-mobi-proj-tf/10.md +++ b/new/intel-mobi-proj-tf/10.md @@ -107,13 +107,17 @@ pip install keras `model.png`文件包含深度神经网络架构的详细视图。 卷积层的许多残差块之后是批处理归一化和 ReLU 层,以稳定训练,它的深度非常大。 该模型的顶部如下图所示(中间部分很大,因此我们将不显示其中间部分,建议您打开`model.png`文件以供参考): -![](img/99dc16a9-52c9-4adf-bd8f-1a244504de79.png)Figure 10.1 The first layers of the deep residual network +![](img/99dc16a9-52c9-4adf-bd8f-1a244504de79.png) + +Figure 10.1 The first layers of the deep residual network 值得注意的是,神经网络称为残差网络(ResNet),由 Microsoft 于 2015 年在 ImageNet 和 COCO 2015 竞赛的获奖作品中引入。 在 ResNet 中,使用身份映射(图 10.1 右侧的箭头)可避免在网络越深时出现更高的训练错误。 有关 ResNet 的更多信息,您可以查看原始论文[《用于图像识别的深度残差学习》](https://arxiv.org/pdf/1512.03385v1.pdf), 以及博客[《了解深度残差网络》](https://blog.waya.ai/deep-residual-learning-9610bb62c355) - 一个简单的模块化学习框架,它重新定义了构成最新技术的内容。 深度网络的最后一层如图 10.2 所示,您可以看到,在最后的残差块和具有批处理归一化和 ReLU 层的卷积层之后,将应用密集的全连接层以输出`value_head and policy_head`值: -![](img/e3383760-5f06-4d10-a903-8978f41281de.png)Figure 10.2 The last layers of the deep resnet +![](img/e3383760-5f06-4d10-a903-8978f41281de.png) + +Figure 10.2 The last layers of the deep resnet 在本节的最后部分,您将看到一些使用 Keras API 的 Python 代码片段,该片段对 ResNet 有着很好的支持,以构建这样的网络。 现在让我们让这些模型首先互相对抗,然后与我们一起对抗,看看这些模型有多好。 @@ -374,7 +378,9 @@ Couldn't load model: Invalid argument: No OpKernel was registered to support Op 现在,只需创建一个名为 AlphaZero 的新 Xcode iOS 项目,然后将上一章中的 iOS 项目中的`tensorflow_utils.mm`和`tensorflow_utils.h`文件以及上一节中生成的`alphazero19.pb`模型文件拖放到 项目。 将`ViewController.m`重命名为`ViewController.mm`,并添加一些常量和变量。 您的项目应如图 10.3 所示: -![](img/a0639a2a-55f3-485a-92cd-4ffdc99b398c.png)Figure 10.3 Showing the AlphaZero iOS app in Xcode +![](img/a0639a2a-55f3-485a-92cd-4ffdc99b398c.png) + +Figure 10.3 Showing the AlphaZero iOS app in Xcode 我们只需要使用三个 UI 组件: @@ -818,11 +824,15 @@ int winners[69][4] = { 现在运行该应用程序,您将看到类似于图 10.4 的屏幕: -![](img/fa949c2a-3114-4a56-9041-9acb069b1ff4.png)Figure 10.4 Playing with Connect4 on iOS +![](img/fa949c2a-3114-4a56-9041-9acb069b1ff4.png) + +Figure 10.4 Playing with Connect4 on iOS 使用 AI 玩一些游戏,图 10.5 显示了一些可能的最终游戏: -![](img/1e45df24-e772-462b-aef9-67c8f49bed67.png)Figure 10.5 Some game results of Connect4 on iOS +![](img/1e45df24-e772-462b-aef9-67c8f49bed67.png) + +Figure 10.5 Some game results of Connect4 on iOS 在我们暂停之前,让我们快速看一下使用该模型并玩游戏的 Android 代码。 @@ -1305,7 +1315,9 @@ void softmax(float vals[], int count) { 现在,在 Android 虚拟或真实设备上运行该应用程序并使用该应用程序进行游戏,您将看到初始屏幕和一些游戏结果: -![](img/2d40ca7c-5d3d-4586-9034-2b2ae1c71ecb.png)Figure 10.6 Showing the game board and some results on Android +![](img/2d40ca7c-5d3d-4586-9034-2b2ae1c71ecb.png) + +Figure 10.6 Showing the game board and some results on Android 当您使用前面的代码在 iOS 和 Android 上玩游戏时,很快就会发现该模型返回的策略并不强大-主要原因是 MCTS 没有出现在这里,由于范围限制,不会与深度神经网络模型一起使用。 强烈建议您自己研究和实现 MCTS,或者在源代码存储库中使用我们的实现作为参考。 您还应该将网络模型和 MCTS 应用于您感兴趣的其他游戏-毕竟,AlphaZero 使用了通用 MCTS 和无领域知识的自我强化学习,从而使超人学习轻松移植到其他问题领域。 通过将 MCTS 与深度神经网络模型结合,您可以实现 AlphaZero 所做的事情。 diff --git a/new/intel-mobi-proj-tf/11.md b/new/intel-mobi-proj-tf/11.md index 36b8512cad5bf9b567e68c1a15bdf00ec0ae8471..38fa213d5271f9b2c252aefca54d58718e931755 100644 --- a/new/intel-mobi-proj-tf/11.md +++ b/new/intel-mobi-proj-tf/11.md @@ -116,7 +116,9 @@ target 'HelloTFLite' 运行`pod install`。 然后在 Xcode 中打开 `HelloTFLite.xcworkspace`,将`ViewController.m`重命名为`ViewController.mm`,并添加必要的 C++ 头文件和 TensorFlow Lite 头文件。 您的 Xcode 项目应类似于以下屏幕截图: -![](img/b4b1750b-cc97-42f8-a032-226b595d7e46.png)Figure 11.1 A new Xcode iOS project using the TensorFlow Lite pod +![](img/b4b1750b-cc97-42f8-a032-226b595d7e46.png) + +Figure 11.1 A new Xcode iOS project using the TensorFlow Lite pod 我们仅向您展示如何在 iOS 应用中使用 TensorFlow Lite Pod。 还有另一种将 TensorFlow Lite 添加到 iOS 的方法,类似于构建自定义 TensorFlow Mobile iOS 库的过程,我们在前几章中已经做过很多次了。 有关如何构建自己的自定义 TensorFlow Lite iOS 库的更多信息,请参阅[以下位置的文档](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/contrib/lite/g3doc/ios.md)。 @@ -162,15 +164,21 @@ NSString* RunInferenceOnImage() { 6. 在以与在`HelloTensorFlow`应用程序中相同的方式加载`labels.txt`文件后,也以相同的方式加载要分类的图像,但是使用 TensorFlow Lite 的`Interpreter`的`typed_tensor`方法而不是 TensorFlow Mobile 的`Tensor`类及其`tensor`方法。 图 11.2 比较了用于加载和处理图像文件数据的 TensorFlow Mobile 和 Lite 代码: -![](img/8df9836e-fbf9-4caf-97af-7d415b6dc5bb.png)Figure 11.2 The TensorFlow Mobile (left) and Lite code of loading and processing the image input +![](img/8df9836e-fbf9-4caf-97af-7d415b6dc5bb.png) + +Figure 11.2 The TensorFlow Mobile (left) and Lite code of loading and processing the image input 7. 在调用`GetTopN`辅助方法以获取前`N`个分类结果之前,调用`Interpreter`上的`Invoke`方法运行模型,并调用`typed_out_tensor`方法以获取模型的输出。 TensorFlow Mobile 和 Lite 之间的代码差异如图 11.3 所示: -![](img/c3e31c5c-775f-4af8-a000-d8d65f75f657.png)Figure 11.3 The TensorFlow Mobile (left) and Lite code of running the model and getting the output +![](img/c3e31c5c-775f-4af8-a000-d8d65f75f657.png) + +Figure 11.3 The TensorFlow Mobile (left) and Lite code of running the model and getting the output 8. 以类似于 HelloTensorFlow 中方法的方式实现`GetTopN`方法,对于 TensorFlow Lite 使用`const float* prediction`类型而不是对于 TensorFlow Mobile 使用`const Eigen::TensorMap, Eigen::Aligned>& prediction`。 TensorFlow Mobile 和 Lite 中`GetTopN`方法的比较如图 11.4 所示: -![](img/0f0c6dc7-939f-4b15-9542-c56a9f3f427f.png)Figure 11.4 The TensorFlow Mobile (left) and Lite code of processing the model output to return the top results +![](img/0f0c6dc7-939f-4b15-9542-c56a9f3f427f.png) + +Figure 11.4 The TensorFlow Mobile (left) and Lite code of processing the model output to return the top results 9. 如果值大于阈值(设置为`0.1f`),则使用简单的`UIAlertController`显示带有 TensorFlow Lite 模型返回的置信度值的最佳结果: @@ -190,7 +198,9 @@ NSString* RunInferenceOnImage() { 立即运行 iOS 应用,然后点击屏幕以运行模型。 对于`lab1.jpg`测试图像,您将在图 11.5 中看到模型的结果: -![](img/5568ba52-1f2e-4968-b6d5-5a1d33061c46.png)Figure 11.5 The test image and model inference result +![](img/5568ba52-1f2e-4968-b6d5-5a1d33061c46.png) + +Figure 11.5 The test image and model inference result 这就是您可以在新的 iOS 应用程序中使用预构建的 MobileNet TensorFlow Lite 模型的方式。 现在让我们看看如何使用经过重新训练的 TensorFlow 模型。 @@ -319,7 +329,9 @@ bazel-bin/tensorflow/contrib/lite/toco/toco \ 现在,Android Studio 中的 HelloTFLite 应用程序应类似于图 11.6: -![](img/9df4ffa8-cd63-4b4c-a728-47cba1394711.png)Figure 11.6 New Android app using TensorFlow Lite and the prebuilt MobileNet image classification model +![](img/9df4ffa8-cd63-4b4c-a728-47cba1394711.png) + +Figure 11.6 New Android app using TensorFlow Lite and the prebuilt MobileNet image classification model 5. 像以前一样,在`activity_main.xml`中添加`ImageView`和`Button`,然后在`MainActivity.java`的`onCreate`方法中,将`ImageView`设置为测试图像的内容,然后单击 `Button`的侦听器以启动新线程,并实例化名为`classifier`的`ImageClassifier`实例: @@ -525,7 +537,9 @@ coreml_model.save("HouseSVM.mlmodel") 在将两个 Core ML 模型文件`HouseLR.mlmodel`和`HouseSVM.mlmodel`添加到新的基于 Swift 的 Xcode iOS 项目中之后, `HouseLR.mlmodel`如图 11.7 所示: -![](img/aaa2a1dd-d7f2-4fbc-8e70-3e6041ddda6e.png)Figure 11.7 Showing the Swift iOS project and the Linear Regression Core ML model +![](img/aaa2a1dd-d7f2-4fbc-8e70-3e6041ddda6e.png) + +Figure 11.7 Showing the Swift iOS project and the Linear Regression Core ML model 其他`HouseSVM.mlmodel` 模型 看起来完全一样,只是机器学习模型名称和模型类从`HouseLR`更改为`HouseSVM`。 @@ -590,7 +604,9 @@ coreml_model.save("Stock.mlmodel") 将生成的`Stock.mlmodel`文件拖放到 Xcode 9.2 iOS 项目中时,它将使用默认的输入名称`input1`和默认的输出名称`output1`,如图 11.8 所示。 基于 Objective-C 和 Swift 的 iOS 应用: -![](img/fdf48153-937d-4066-9dd3-cc13ce841e6e.png)Figure 11.8 Showing the stock prediction Core ML model converted from Keras and TensorFlow in an Objective-C app +![](img/fdf48153-937d-4066-9dd3-cc13ce841e6e.png) + +Figure 11.8 Showing the stock prediction Core ML model converted from Keras and TensorFlow in an Objective-C app 使用 coremltools 生成模型的 Core ML 格式的另一种方法是,首先将 Keras 构建的模型保存为 Keras HDF5 模型格式,这是我们在第 10 章,“构建类似 AlphaZero 的移动游戏应用程序”中,在转换为 AlphaZero TensorFlow 检查点文件之前使用的格式。 为此,只需运行`model.save('stock.h5')`。 @@ -606,7 +622,9 @@ coreml_model.save('Stock.mlmodel') 请注意,此处使用与冻结 TensorFlow 检查点文件相同的输入和输出名称。 如果将`Stock.mlmodel`拖放到 Objective-C 项目,则自动生成的`Stock.h`中将出现错误,因为 Xcode 9.2 中的错误无法正确处理代码中的`/`字符`activation_1/Identity`输出名称。 如果它是 Swift iOS 对象,则自动生成的`Stock.swift`文件会正确地将`/`字符更改为`_`,从而避免了编译器错误,如图 11.9 所示。 -![](img/b77107fa-7de7-4602-84d1-d4c5b01c6efc.png)Figure 11.9 Showing the stock prediction Core ML model converted from Keras and TensorFlow in a Swift app +![](img/b77107fa-7de7-4602-84d1-d4c5b01c6efc.png) + +Figure 11.9 Showing the stock prediction Core ML model converted from Keras and TensorFlow in a Swift app 要在 Objective-C 中使用该模型,请创建具有指定数据类型和形状的`Stock`对象和`MLMultiArray`对象,然后使用一些输入数据填充数组对象,并使用`StockInput`调用`predictionFromFeatures`方法 用 `MLMultiArray`数据初始化的实例: diff --git a/new/intel-mobi-proj-tf/12.md b/new/intel-mobi-proj-tf/12.md index 522c0251348cd27b028e938733648854f051482e..6f59d5d2f4eb6884886c3616117fcc356bed0b71 100644 --- a/new/intel-mobi-proj-tf/12.md +++ b/new/intel-mobi-proj-tf/12.md @@ -152,7 +152,9 @@ GoPiGo 是一个流行的工具包,可将您的 Raspberry Pi 板变成移动 完成后,您的 Raspberry Pi 机器人以及我们之前列出的所有附件应如下所示: -![](img/a745c220-8c27-4b70-bef4-bc8dcbc518d8.png)Figure 12\. 1 Raspberry Pi robot with GoPiGo Kit and camera, USB speaker, and USB microphone +![](img/a745c220-8c27-4b70-bef4-bc8dcbc518d8.png) + +Figure 12\. 1 Raspberry Pi robot with GoPiGo Kit and camera, USB speaker, and USB microphone 现在,使用 Raspberry Pi 电源打开 Pi 机器人,并在启动后使用`ssh pi@`连接到它。 要安装 GoPiGo Python 库,以便我们可以使用 [GoPiGo 的 Python API](http://gopigo3.readthedocs.io/en/master/api-basic.html) 控制机器人,请运行以下命令 ,它将执行一个 shell 脚本,该脚本创建一个新的`/home/pi/Dexter`目录并在其中安装所有库和固件文件: