diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 00000000..80e0543a Binary files /dev/null and b/.DS_Store differ diff --git a/README.md b/README.md index 8a458a5d..29aa84ad 100644 --- a/README.md +++ b/README.md @@ -1,34 +1,52 @@ ### Deeplearning Algorithms tutorial +

+ + + +

+ 最近以来一直在学习机器学习和算法,然后自己就在不断总结和写笔记,记录下自己的学习AI与算法历程。 机器学习(Machine Learning, ML)是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能。 +

+ +

+ * 机器学习是计算机科学的一个子领域,在人工智能领域,机器学习逐渐发展成模式识别和计算科学理论的研究。 * 机器学习:多领域交叉学科,涉及概率论统计学,逼近论,凸分析,算法复杂度理论等多门学科。 * 机器学习的应用:语音识别,自动驾驶,语言翻译,计算机视觉,推荐系统,无人机,识别垃圾邮件,人脸识别,电商推荐系统。 * 机器学习的基本概念:训练集,测试集,特征值,监督学习,非监督学习,分类,回归 目前国内在AI感知层面应用已经百花齐放,主要是无人驾驶、智能音箱、嵌入式。但在认知层面还是比较缺乏,所以新入行的AI应用团队可以放在认知层。如开头所述,认知层最重要的是算法,因此需要阅读Nature上最领先的算法公司DeepMind的几篇大作,如下: + * 2016.01.Mastering the game of Go with deep neural networks and tree search * 2016.10.Hybrid computing using a neural network with dynamic external memory * 2017.10.Mastering the game of Go without human knowledge - #### 机器学习步骤框架 + * 把数据拆分为训练集合测试集 * 用训练集合训练集的特征向量来训练算法 * 用学习来的算法运用在测试集上累评估算法(可能要设计到调整参数(parameter tuning) 用来验证集(validation set)) +#### 机器学习 + +* 机器学习:机器学习是计算机科学的一个子领域,在人工智能领域,机器学习逐渐发展成模式识别和计算科学理论的研究。通俗的讲机器学习是一种能够赋予机器学习的能力,可以让它完成直接编程无法完成的功能的方法。但从实践的意义上来说,机器学习是一种通过利用数据,训练出模型,然后使用模型预测的一种方法。 +* 机器学习的应用:机器学习已广泛应用于数据挖掘、计算机视觉、自然语言处理、生物特征识别、搜索引擎、医学诊断、检测信用卡欺诈、证券市场分析、DNA序列测序、语音和手写识别、战略游戏和机器人等领域。下面开启我们的机器学习! + + * [机器学习环境的搭建](https://github.com/AI-algorithms/Algorithms-Tutorial/blob/master/src/Machine%20Learning/ML.01.md) + * [机器学习的入门](https://github.com/AI-algorithms/Algorithms-Tutorial/blob/master/src/Machine%20Learning/ML.02.md) + * [机器学习的框架](https://github.com/AI-algorithms/Algorithms-Tutorial/blob/master/src/Machine%20Learning/ML.03.md) + * [机器学习的应用案例]() #### 深度学习 -深度学习:深度学习是基于机器学习延伸出来的一个新的领域,由以人大脑结构为启发的神经网络算法为起源加之模型结构深度的增加发展,并伴随大数据和计算能力的提高而产生的一系列新的算法。 -深度学习的方向:被应用在图像处理与计算机视觉,自然语言处理以及语音识别等领域。 +* 深度学习:深度学习是基于机器学习延伸出来的一个新的领域,由以人大脑结构为启发的神经网络算法为起源加之模型结构深度的增加发展,并伴随大数据和计算能力的提高而产生的一系列新的算法。 +* 深度学习的方向:被应用在图像处理与计算机视觉,自然语言处理以及语音识别等领域。 - * [深度神经网络](https://github.com/AI-algorithms/Algorithms-Tutorial/blob/master/src/Neural%20Network/NNK.md) - * [深度学习的入门]() + * [深度神经网络](https://github.com/AI-algorithms/Algorithms-Tutorial/blob/master/src/Neural%20Network/NNK.01.md) + * [深度学习的入门](https://github.com/AI-algorithms/Algorithms-Tutorial/blob/master/src/Neural%20Network/NNK.02.md) + * [深度学习环境的搭建](https://github.com/AI-algorithms/Algorithms-Tutorial/blob/master/src/Neural%20Network/NNK.03.md) * [深度学习的应用案例]() - * [深度学习所需要的数据]() - - #### 机器学习算法概览

@@ -56,80 +74,88 @@ * [PageRank](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/PRK/PRK.md) * [AdaBoost](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ABT/ABT.md) * [CBA](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/CBA/CBA.md) - * [KNN]() - * [Hopfield神经网络]() - * [决策树]() - * [聚类分析]() - * [关联规则]() - * [支持向量机(SVM)]() + * [KNN](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/KNN/KNN.md) + * [Hopfield神经网络](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/HPD/HPD.md) + * [决策树](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DT/DT.md) + * [聚类分析](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/CAS/CAS.md) + * [关联规则](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ARS/ARS.md) + * [支持向量机(SVM)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/SVM/SVM.md) 后面的算法和我们的算法模型,我会持续更新整理,后续的算法章节会不断的补上,希望可以对新入门学习AI开发和算法的开发者有所帮助! #### 算法模型 - * [回归算法]() - * [线性回归]() - * [逻辑回归]() - * [多元自适应回归(MARS)]() - * [本地散点平滑估计(LOESS)]() - * [基于实例的学习算法]() - * [K-邻近算法(KNN)]() - * [学习矢量化(LVQ)]() - * [自组织映射算法(SOM)]() - * [局部加权学习算法(LWL)]() - * [正则化算法]() - * [岭回归(Ridge Regression)]() - * [LASSO(Least Absolute Shrinkage and Selection Operator)]() - * [Elastic Net]() - * [最小角回归(LARS)]() - * [决策树算法]() - * [分类和回归树(CART)]() - * [ID3算法(Iterative Dichotomiser 3)]() - * [CHAID(Chi-squared Automatic Interaction Detection]() - * [随机森林(Random Forest)]() - * [多元自适应回归样条(MARS)]() - * [梯度推进机(Gradient Boosting Machine, GBM)]() - * [贝叶斯算法]() - * [朴素贝叶斯]() - * [高斯朴素贝叶斯]() - * [多项式朴素贝叶斯]() - * [AODE(Averaged One-Dependence Estimators)]() - * [贝叶斯网络(Bayesian Belief Network)]() - * [基于核的算法]() - * [支持向量机(SVM)]() - * [径向基函数(Radial Basis Function ,RBF)]() - * [线性判别分析(Linear Discriminate Analysis ,LDA)]() - * [聚类算法]() - * [K-均值]() - * [K-中位数]() - * [EM算法]() - * [分层聚类]() - * [关联规则学习]() - * [Apriori算法]() - * [Eclat算法]() - * [神经网络]() - * [感知器]() - * [反向传播算法(BP)]() - * [Hopfield网络]() - * [径向基函数网络(RBFN)]() - * [深度学习]() - * [深度玻尔兹曼机(DBM)]() - * [卷积神经网络(CNN)]() - * [递归神经网络(RNN、LSTM)]() - * [栈式自编码算法(Stacked Auto-Encoder)]() - * [降维算法]() - * [主成分分析法(PCA)]() - * [主成分回归(PCR)]() - * [偏最小二乘回归(PLSR)]() - * [萨蒙映射]() - * [多维尺度分析法(MDS]() - * [投影寻踪法(PP)]() - * [线性判别分析法(LDA)]() - * [混合判别分析法(MDA)]() - * [二次判别分析法(QDA)]() - * [灵活判别分析法(Flexible Discriminant Analysis,FDA]() - * [集成算法]() - * [Boosting]() - * [Bagging]() + * [回归算法](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/RAM/RAM.0.1.md) + * [线性回归](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/RAM/RAM.0.2.md) + * [逻辑回归](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/RAM/RAM.0.3.md) + * [多元自适应回归(MARS)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/RAM/RAM.0.4.md) + * [本地散点平滑估计(LOESS)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/RAM/RAM.0.5.md) + * [基于实例的学习算法](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/BA/BA.0.1.md) + * [K-近邻算法(KNN)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/BA/BA.0.2.md) + * [学习矢量化(LVQ)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/BA/BA.0.3.md) + * [自组织映射算法(SOM)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/BA/BA.0.4.md) + * [局部加权学习算法(LWR)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/BA/BA.0.5.md) + * [正则化算法](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/RGN/RGN.0.1.md) + * [岭回归(Ridge Regression)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/RGN/RGN.0.2.md) + * [LASSO(Least Absolute Shrinkage and Selection Operator)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/RGN/RGN.0.3.md) + * [弹性网络(Elastic Net)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/RGN/RGN.0.4.md) + * [最小角回归(LARS)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/RGN/RGN.0.5.md) + * [决策树算法](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DT/DT.0.1.md) + * [分类和回归树(CART)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DT/DT.0.2.md) + * [ID3算法(Iterative Dichotomiser 3)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DT/DT.0.3.md) + * [CHAID(Chi-squared Automatic Interaction Detection)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DT/DT.0.4.md) + * [随机森林(Random Forest)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DT/DT.0.5.md) + * [多元自适应回归样条(MARS)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DT/DT.0.6.md) + * [梯度推进机(Gradient Boosting Machine,GBM)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DT/DT.0.7.md) + * [贝叶斯算法](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/BNS/BNS.0.1.md) + * [朴素贝叶斯(Naive Bayes)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/BNS/BNS.0.2.md) + * [高斯朴素贝叶斯(Gaussian Naive Bayes)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/BNS/BNS.0.3.md) + * [多项式朴素贝叶斯(Multinomial Naive Bayes)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/BNS/BNS.0.4.md) + * [平均单依赖估计量(Averaged One-Dependence Estimators)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/BNS/BNS.0.5.md) + * [贝叶斯网络(Bayesian Belief Network)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/BNS/BNS.0.6.md) + * [基于核的算法](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/KBO/KBO.0.1.md) + * [支持向量机(SVM)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/KBO/KBO.0.2.md) + * [径向基函数(Radial Basis Function ,RBF)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/KBO/KBO.0.3.md) + * [线性判别分析(Linear Discriminate Analysis ,LDA)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/KBO/KBO.0.4.md) + * [聚类算法(Cluster analysis)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/CA/CA.0.1.md) + * [K-均值(K-Means Algorithm)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/CA/CA.0.2.md) + * [模糊c-均值聚类算法(Fuzzy C-means Algorithm)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/CA/CA.0.3.md) + * [期望最大化(Expectation-Maximization)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/CA/CA.0.4.md) + * [聚类分析(Cluster Analysis)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/CA/CA.0.5.md) + * [关联规则学习(Association Rule Learning)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ARL/ARL.0.1.md) + * [先验算法(Apriori Algorithm)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ARL/ARL.0.2.md) + * [Eclat算法(Eclat Algorithm)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ARL/ARL.0.3.md) + * [FP-growth算法(FP-Growth Algorithm)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ARL/ARL.0.4.md) + * [人工神经网络(Artificial Neural Network)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ANN/ANN.0.1.md) + * [自动编码器(Autoencoder)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ANN/ANN.0.2.md) + * [反向传播(Backpropagation)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ANN/ANN.0.3.md) + * [递归神经网络(Recurrent Neural Network)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ANN/ANN.0.4.md)) + * [多层感知器(Multilayer Perceptron)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ANN/ANN.0.5.md) + * [玻尔兹曼机(Boltzmann Machine)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ANN/ANN.0.6.md) + * [卷积神经网络(Convolutional Neural Network)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ANN/ANN.0.7.md) + * [Hopfield网络(Hopfield Network)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ANN/ANN.0.8.md) + * [径向基函数网络(Radial Basis Function Network)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ANN/ANN.0.9.md) + * [受限玻尔兹曼机(Restricted Boltzmann Machine)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ANN/ANN.0.10.md) + * [自组织映射(Self-Organizing Map)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ANN/ANN.0.11.md) + * [脉冲神经网络(Spiking Neural Network)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/ANN/ANN.0.12.md) + * [深度学习(Deep Learning)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DL/DL.0.1.md) + * [深度信念网络(Deep Belief Machines)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DL/DL.0.2.md) + * [深度卷积神经网络(Deep Convolutional Neural Networks)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DL/DL.0.3.md) + * [深度递归神经网络(Deep Recurrent Neural Networks)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DL/DL.0.4.md) + * [分层时间记忆(Hierarchical Temporal Memory)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DL/DL.0.5.md) + * [堆叠自动编码器(Stacked AutoEncoder)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DL/DL.0.6.md) + * [生成式对抗网络(Generative Adversarial Networks)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DL/DL.0.7.md) + * [降维算法(Dimensionality Reduction Algorithm)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DRA/DRA.0.1.md) + * [主成分分析法(Principal Component Analysis)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DRA/DRA.0.2.md) + * [多维缩放(Mutiple Dimensional Scaling)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DRA/DRA.0.3.md) + * [线性判别分析(Linear Discriminant Analysis)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DRA/DRA.0.4.md) + * [等度量映射(IsometricMapping,Isomap)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DRA/DRA.0.5.md) + * [局部线性嵌入(Locally Linear Embedding)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DRA/DRA.0.6.md) + * [拉普拉斯特征映射(Laplacian Eigenmaps)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DRA/DRA.0.7.md) + * [t-分布随机近邻嵌入(t-SNE)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DRA/DRA.0.8.md) + * [深度自动编码器(Deep Autoencoder Networks)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/DRA/DRA.0.9.md) + * [集成算法(Ensemble Learning)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/EL/EL.0.1.md) + * [Boosting](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/EL/EL.0.2.md) + * [Bagging](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/EL/EL.0.3.md) * [AdaBoost]() * [堆叠泛化(混合)]() * [GBM 算法]() @@ -145,7 +171,27 @@ * [迁移学习]() 算法模型的整体基本就是这样目录,后续的算法模型我会不断完善和补充,更新! + +#### 大模型LLM + +大型语言模型(LLM,Large Language Model)伴随着chatgpt的诞生,走进了我们的视野,GPT 3.0它不仅仅是一项具体的技术,其实体现的是LLM应该往何处去的一个发展理念。 + +自此之后,差距拉得越来越远,ChatGPT只是这种发展理念差异的一个自然结果。 + +那么什么是大语言模型呢, 我们深入探索和学习下。 + +大型语言模型(LLM)是基于大量数据进行预训练的超大型深度学习模型。底层转换器是一组神经网络,这些神经网络由具有自注意力功能的编码器和解码器组成。编码器和解码器从一系列文本中提取含义,并理解其中的单词和短语之间的关系。 + +转换器 LLM 能够进行无监督的训练,但更精确的解释是转换器可以执行自主学习。通过此过程,转换器可学会理解基本的语法、语言和知识。 + +与早期按顺序处理输入的循环神经网络(RNN)不同,转换器并行处理整个序列。这可让数据科学家使用 GPU 训练基于转换器的 LLM,从而大幅度缩短训练时间。 + +借助转换器神经网络架构,您可使用非常大规模的模型,其中通常具有数千亿个参数。这种大规模模型可以摄取通常来自互联网的大量数据,但也可以从包含 500 多亿个网页的 Common Crawl 和拥有约 5700 万个页面的 Wikipedia 等来源摄取数据。 + +* [走进大语言模型LLM)](https://github.com/KeKe-Li/tutorial/blob/master/assets/src/LLM/llm.md) + #### 机器学习的基础 + * 机器学习需要的理论基础:数学,线性代数,数理统计,概率论,高等数学、凸优化理论,形式逻辑等 #### 参考书籍 @@ -163,10 +209,15 @@ * [梯度下降](https://github.com/KeKe-Li/book/blob/master/AI/%E6%A2%AF%E5%BA%A6%E4%B8%8B%E9%99%8D.pdf) * [无监督神经元](https://blog.openai.com/unsupervised-sentiment-neuron/) * [Tensorflow实践](https://tensorflow.feisky.xyz/install/cpu.html) +* [Artificial Intelligence](https://github.com/owainlewis/awesome-artificial-intelligence) +* [Tensorflow新手入门](http://www.tensorfly.cn/tfdoc/tutorials/mnist_beginners.html) ### 机器学习 -觉得此文章不错可以给我star!如果有问题可以加我的微信Sen0676,可以一起交流算法和机器学习! +觉得此文章不错,支持我的话可以给我star ,:star:! 如果有问题可以加我的微信,也可以加入我们的交流群一起交流技术! +

+ +

### License This is free software distributed under the terms of the MIT license diff --git a/assets/images/100.jpg b/assets/images/100.jpg new file mode 100644 index 00000000..2429a406 Binary files /dev/null and b/assets/images/100.jpg differ diff --git a/assets/images/101.jpg b/assets/images/101.jpg new file mode 100644 index 00000000..29cc113d Binary files /dev/null and b/assets/images/101.jpg differ diff --git a/assets/images/102.jpg b/assets/images/102.jpg new file mode 100644 index 00000000..f004e88d Binary files /dev/null and b/assets/images/102.jpg differ diff --git a/assets/images/103.jpg b/assets/images/103.jpg new file mode 100644 index 00000000..36104f0b Binary files /dev/null and b/assets/images/103.jpg differ diff --git a/assets/images/104.jpg b/assets/images/104.jpg new file mode 100644 index 00000000..f13364a2 Binary files /dev/null and b/assets/images/104.jpg differ diff --git a/assets/images/105.jpg b/assets/images/105.jpg new file mode 100644 index 00000000..bf333c64 Binary files /dev/null and b/assets/images/105.jpg differ diff --git a/assets/images/106.jpg b/assets/images/106.jpg new file mode 100644 index 00000000..db4b6bea Binary files /dev/null and b/assets/images/106.jpg differ diff --git a/assets/images/107.jpg b/assets/images/107.jpg new file mode 100644 index 00000000..641be22e Binary files /dev/null and b/assets/images/107.jpg differ diff --git a/assets/images/108.jpg b/assets/images/108.jpg new file mode 100644 index 00000000..02ddb02f Binary files /dev/null and b/assets/images/108.jpg differ diff --git a/assets/images/109.jpg b/assets/images/109.jpg new file mode 100644 index 00000000..fb2fc12c Binary files /dev/null and b/assets/images/109.jpg differ diff --git a/assets/images/110.jpg b/assets/images/110.jpg new file mode 100644 index 00000000..9ec3d075 Binary files /dev/null and b/assets/images/110.jpg differ diff --git a/assets/images/111.jpg b/assets/images/111.jpg new file mode 100644 index 00000000..f86ac774 Binary files /dev/null and b/assets/images/111.jpg differ diff --git a/assets/images/112.jpg b/assets/images/112.jpg new file mode 100644 index 00000000..f029e053 Binary files /dev/null and b/assets/images/112.jpg differ diff --git a/assets/images/113.jpg b/assets/images/113.jpg new file mode 100644 index 00000000..d25ea361 Binary files /dev/null and b/assets/images/113.jpg differ diff --git a/assets/images/114.jpg b/assets/images/114.jpg new file mode 100644 index 00000000..8eec4ed4 Binary files /dev/null and b/assets/images/114.jpg differ diff --git a/assets/images/115.jpg b/assets/images/115.jpg new file mode 100644 index 00000000..ba82436f Binary files /dev/null and b/assets/images/115.jpg differ diff --git a/assets/images/116.jpg b/assets/images/116.jpg new file mode 100644 index 00000000..9d318e71 Binary files /dev/null and b/assets/images/116.jpg differ diff --git a/assets/images/117.jpg b/assets/images/117.jpg new file mode 100644 index 00000000..11e1ab91 Binary files /dev/null and b/assets/images/117.jpg differ diff --git a/assets/images/119.jpg b/assets/images/119.jpg new file mode 100644 index 00000000..3b0df401 Binary files /dev/null and b/assets/images/119.jpg differ diff --git a/assets/images/120.jpg b/assets/images/120.jpg new file mode 100644 index 00000000..cbaf5ca5 Binary files /dev/null and b/assets/images/120.jpg differ diff --git a/assets/images/121.jpg b/assets/images/121.jpg new file mode 100644 index 00000000..5f44795e Binary files /dev/null and b/assets/images/121.jpg differ diff --git a/assets/images/122.jpg b/assets/images/122.jpg new file mode 100644 index 00000000..89e3fe2a Binary files /dev/null and b/assets/images/122.jpg differ diff --git a/assets/images/123.jpg b/assets/images/123.jpg new file mode 100644 index 00000000..178c25c0 Binary files /dev/null and b/assets/images/123.jpg differ diff --git a/assets/images/124.jpg b/assets/images/124.jpg new file mode 100644 index 00000000..3691f81d Binary files /dev/null and b/assets/images/124.jpg differ diff --git a/assets/images/125.jpg b/assets/images/125.jpg new file mode 100644 index 00000000..9c6348b8 Binary files /dev/null and b/assets/images/125.jpg differ diff --git a/assets/images/126.jpg b/assets/images/126.jpg new file mode 100644 index 00000000..e2259e52 Binary files /dev/null and b/assets/images/126.jpg differ diff --git a/assets/images/127.jpg b/assets/images/127.jpg new file mode 100644 index 00000000..21b0fa95 Binary files /dev/null and b/assets/images/127.jpg differ diff --git a/assets/images/128.jpg b/assets/images/128.jpg new file mode 100644 index 00000000..63d69d1a Binary files /dev/null and b/assets/images/128.jpg differ diff --git a/assets/images/129.jpg b/assets/images/129.jpg new file mode 100644 index 00000000..aa9c6941 Binary files /dev/null and b/assets/images/129.jpg differ diff --git a/assets/images/130.jpg b/assets/images/130.jpg new file mode 100644 index 00000000..745f7ef5 Binary files /dev/null and b/assets/images/130.jpg differ diff --git a/assets/images/131.jpg b/assets/images/131.jpg new file mode 100644 index 00000000..5367bc77 Binary files /dev/null and b/assets/images/131.jpg differ diff --git a/assets/images/132.jpg b/assets/images/132.jpg new file mode 100644 index 00000000..008f260b Binary files /dev/null and b/assets/images/132.jpg differ diff --git a/assets/images/133.jpg b/assets/images/133.jpg new file mode 100644 index 00000000..4553d21d Binary files /dev/null and b/assets/images/133.jpg differ diff --git a/assets/images/134.jpg b/assets/images/134.jpg new file mode 100644 index 00000000..26a6d972 Binary files /dev/null and b/assets/images/134.jpg differ diff --git a/assets/images/135.jpg b/assets/images/135.jpg new file mode 100644 index 00000000..f9481290 Binary files /dev/null and b/assets/images/135.jpg differ diff --git a/assets/images/136.jpg b/assets/images/136.jpg new file mode 100644 index 00000000..6c52abfc Binary files /dev/null and b/assets/images/136.jpg differ diff --git a/assets/images/137.jpg b/assets/images/137.jpg new file mode 100644 index 00000000..31255e68 Binary files /dev/null and b/assets/images/137.jpg differ diff --git a/assets/images/138.jpg b/assets/images/138.jpg new file mode 100644 index 00000000..ef35ec40 Binary files /dev/null and b/assets/images/138.jpg differ diff --git a/assets/images/139.jpg b/assets/images/139.jpg new file mode 100644 index 00000000..b86a6130 Binary files /dev/null and b/assets/images/139.jpg differ diff --git a/assets/images/140.jpg b/assets/images/140.jpg new file mode 100644 index 00000000..0264f2d8 Binary files /dev/null and b/assets/images/140.jpg differ diff --git a/assets/images/141.jpg b/assets/images/141.jpg new file mode 100644 index 00000000..b9a193f8 Binary files /dev/null and b/assets/images/141.jpg differ diff --git a/assets/images/142.jpg b/assets/images/142.jpg new file mode 100644 index 00000000..a028649e Binary files /dev/null and b/assets/images/142.jpg differ diff --git a/assets/images/143.jpg b/assets/images/143.jpg new file mode 100644 index 00000000..d0c1ead8 Binary files /dev/null and b/assets/images/143.jpg differ diff --git a/assets/images/144.jpg b/assets/images/144.jpg new file mode 100644 index 00000000..7ae84200 Binary files /dev/null and b/assets/images/144.jpg differ diff --git a/assets/images/145.jpg b/assets/images/145.jpg new file mode 100644 index 00000000..e3293ad7 Binary files /dev/null and b/assets/images/145.jpg differ diff --git a/assets/images/146.jpg b/assets/images/146.jpg new file mode 100644 index 00000000..fb4e5151 Binary files /dev/null and b/assets/images/146.jpg differ diff --git a/assets/images/147.jpg b/assets/images/147.jpg new file mode 100644 index 00000000..67bcb801 Binary files /dev/null and b/assets/images/147.jpg differ diff --git a/assets/images/148.jpg b/assets/images/148.jpg new file mode 100644 index 00000000..b07c6cd6 Binary files /dev/null and b/assets/images/148.jpg differ diff --git a/assets/images/149.jpg b/assets/images/149.jpg new file mode 100644 index 00000000..86147dd8 Binary files /dev/null and b/assets/images/149.jpg differ diff --git a/assets/images/150.jpg b/assets/images/150.jpg new file mode 100644 index 00000000..a5b3630c Binary files /dev/null and b/assets/images/150.jpg differ diff --git a/assets/images/151.jpg b/assets/images/151.jpg new file mode 100644 index 00000000..7c47dce7 Binary files /dev/null and b/assets/images/151.jpg differ diff --git a/assets/images/152.jpg b/assets/images/152.jpg new file mode 100644 index 00000000..645d0418 Binary files /dev/null and b/assets/images/152.jpg differ diff --git a/assets/images/153.jpg b/assets/images/153.jpg new file mode 100644 index 00000000..26ee5ed1 Binary files /dev/null and b/assets/images/153.jpg differ diff --git a/assets/images/154.jpg b/assets/images/154.jpg new file mode 100644 index 00000000..58dc32f5 Binary files /dev/null and b/assets/images/154.jpg differ diff --git a/assets/images/155.jpg b/assets/images/155.jpg new file mode 100644 index 00000000..b5c90956 Binary files /dev/null and b/assets/images/155.jpg differ diff --git a/assets/images/156.jpg b/assets/images/156.jpg new file mode 100644 index 00000000..ce28de5f Binary files /dev/null and b/assets/images/156.jpg differ diff --git a/assets/images/157.jpg b/assets/images/157.jpg new file mode 100644 index 00000000..06ee01e0 Binary files /dev/null and b/assets/images/157.jpg differ diff --git a/assets/images/158.jpg b/assets/images/158.jpg new file mode 100644 index 00000000..a40fd992 Binary files /dev/null and b/assets/images/158.jpg differ diff --git a/assets/images/159.jpg b/assets/images/159.jpg new file mode 100644 index 00000000..64751d6a Binary files /dev/null and b/assets/images/159.jpg differ diff --git a/assets/images/160.jpg b/assets/images/160.jpg new file mode 100644 index 00000000..dbed6843 Binary files /dev/null and b/assets/images/160.jpg differ diff --git a/assets/images/161.jpg b/assets/images/161.jpg new file mode 100644 index 00000000..327f65e2 Binary files /dev/null and b/assets/images/161.jpg differ diff --git a/assets/images/162.jpg b/assets/images/162.jpg new file mode 100644 index 00000000..1806d7db Binary files /dev/null and b/assets/images/162.jpg differ diff --git a/assets/images/163.jpg b/assets/images/163.jpg new file mode 100644 index 00000000..cf422949 Binary files /dev/null and b/assets/images/163.jpg differ diff --git a/assets/images/164.jpg b/assets/images/164.jpg new file mode 100644 index 00000000..d3cc647f Binary files /dev/null and b/assets/images/164.jpg differ diff --git a/assets/images/165.jpg b/assets/images/165.jpg new file mode 100644 index 00000000..cc53b9c5 Binary files /dev/null and b/assets/images/165.jpg differ diff --git a/assets/images/166.jpg b/assets/images/166.jpg new file mode 100644 index 00000000..5d12b6bc Binary files /dev/null and b/assets/images/166.jpg differ diff --git a/assets/images/167.jpg b/assets/images/167.jpg new file mode 100644 index 00000000..341978d4 Binary files /dev/null and b/assets/images/167.jpg differ diff --git a/assets/images/168.jpg b/assets/images/168.jpg new file mode 100644 index 00000000..6cd53b8d Binary files /dev/null and b/assets/images/168.jpg differ diff --git a/assets/images/169.jpg b/assets/images/169.jpg new file mode 100644 index 00000000..74fef6bc Binary files /dev/null and b/assets/images/169.jpg differ diff --git a/assets/images/170.jpg b/assets/images/170.jpg new file mode 100644 index 00000000..2e5ba710 Binary files /dev/null and b/assets/images/170.jpg differ diff --git a/assets/images/171.jpg b/assets/images/171.jpg new file mode 100644 index 00000000..6b127fe6 Binary files /dev/null and b/assets/images/171.jpg differ diff --git a/assets/images/172.jpg b/assets/images/172.jpg new file mode 100644 index 00000000..ea48d59c Binary files /dev/null and b/assets/images/172.jpg differ diff --git a/assets/images/173.jpg b/assets/images/173.jpg new file mode 100644 index 00000000..c6942f42 Binary files /dev/null and b/assets/images/173.jpg differ diff --git a/assets/images/174.jpg b/assets/images/174.jpg new file mode 100644 index 00000000..7d8ae864 Binary files /dev/null and b/assets/images/174.jpg differ diff --git a/assets/images/175.jpg b/assets/images/175.jpg new file mode 100644 index 00000000..c952cf38 Binary files /dev/null and b/assets/images/175.jpg differ diff --git a/assets/images/176.jpg b/assets/images/176.jpg new file mode 100644 index 00000000..10e7c440 Binary files /dev/null and b/assets/images/176.jpg differ diff --git a/assets/images/177.jpg b/assets/images/177.jpg new file mode 100644 index 00000000..ff7dff82 Binary files /dev/null and b/assets/images/177.jpg differ diff --git a/assets/images/178.jpg b/assets/images/178.jpg new file mode 100644 index 00000000..31237762 Binary files /dev/null and b/assets/images/178.jpg differ diff --git a/assets/images/179.jpg b/assets/images/179.jpg new file mode 100644 index 00000000..c949ca5f Binary files /dev/null and b/assets/images/179.jpg differ diff --git a/assets/images/180.jpg b/assets/images/180.jpg new file mode 100644 index 00000000..60084620 Binary files /dev/null and b/assets/images/180.jpg differ diff --git a/assets/images/181.jpg b/assets/images/181.jpg new file mode 100644 index 00000000..bd5e05e1 Binary files /dev/null and b/assets/images/181.jpg differ diff --git a/assets/images/182.jpg b/assets/images/182.jpg new file mode 100644 index 00000000..ce19c0dd Binary files /dev/null and b/assets/images/182.jpg differ diff --git a/assets/images/183.jpg b/assets/images/183.jpg new file mode 100644 index 00000000..3805e7ab Binary files /dev/null and b/assets/images/183.jpg differ diff --git a/assets/images/184.jpg b/assets/images/184.jpg new file mode 100644 index 00000000..4e151f31 Binary files /dev/null and b/assets/images/184.jpg differ diff --git a/assets/images/185.jpg b/assets/images/185.jpg new file mode 100644 index 00000000..9bd1b4d6 Binary files /dev/null and b/assets/images/185.jpg differ diff --git a/assets/images/186.jpg b/assets/images/186.jpg new file mode 100644 index 00000000..eca8fac6 Binary files /dev/null and b/assets/images/186.jpg differ diff --git a/assets/images/187.jpg b/assets/images/187.jpg new file mode 100644 index 00000000..e91a5440 Binary files /dev/null and b/assets/images/187.jpg differ diff --git a/assets/images/188.jpg b/assets/images/188.jpg new file mode 100644 index 00000000..7ac581aa Binary files /dev/null and b/assets/images/188.jpg differ diff --git a/assets/images/189.jpg b/assets/images/189.jpg new file mode 100644 index 00000000..b8303802 Binary files /dev/null and b/assets/images/189.jpg differ diff --git a/assets/images/190.jpg b/assets/images/190.jpg new file mode 100644 index 00000000..993f59ee Binary files /dev/null and b/assets/images/190.jpg differ diff --git a/assets/images/191.jpg b/assets/images/191.jpg new file mode 100644 index 00000000..9e44fe7e Binary files /dev/null and b/assets/images/191.jpg differ diff --git a/assets/images/192.jpg b/assets/images/192.jpg new file mode 100644 index 00000000..2c5aeef8 Binary files /dev/null and b/assets/images/192.jpg differ diff --git a/assets/images/193.jpg b/assets/images/193.jpg new file mode 100644 index 00000000..8aedcd9f Binary files /dev/null and b/assets/images/193.jpg differ diff --git a/assets/images/194.jpg b/assets/images/194.jpg new file mode 100644 index 00000000..79101199 Binary files /dev/null and b/assets/images/194.jpg differ diff --git a/assets/images/195.jpg b/assets/images/195.jpg new file mode 100644 index 00000000..704bf125 Binary files /dev/null and b/assets/images/195.jpg differ diff --git a/assets/images/196.jpg b/assets/images/196.jpg new file mode 100644 index 00000000..c86c9a72 Binary files /dev/null and b/assets/images/196.jpg differ diff --git a/assets/images/197.jpg b/assets/images/197.jpg new file mode 100644 index 00000000..7a721c79 Binary files /dev/null and b/assets/images/197.jpg differ diff --git a/assets/images/198.jpg b/assets/images/198.jpg new file mode 100644 index 00000000..4878af04 Binary files /dev/null and b/assets/images/198.jpg differ diff --git a/assets/images/199.jpg b/assets/images/199.jpg new file mode 100644 index 00000000..d0b69146 Binary files /dev/null and b/assets/images/199.jpg differ diff --git a/assets/images/200.jpg b/assets/images/200.jpg new file mode 100644 index 00000000..e0af6d9c Binary files /dev/null and b/assets/images/200.jpg differ diff --git a/assets/images/201.jpg b/assets/images/201.jpg new file mode 100644 index 00000000..60358420 Binary files /dev/null and b/assets/images/201.jpg differ diff --git a/assets/images/202.jpg b/assets/images/202.jpg new file mode 100644 index 00000000..96e2afc0 Binary files /dev/null and b/assets/images/202.jpg differ diff --git a/assets/images/203.jpg b/assets/images/203.jpg new file mode 100644 index 00000000..27ea39bd Binary files /dev/null and b/assets/images/203.jpg differ diff --git a/assets/images/204.jpg b/assets/images/204.jpg new file mode 100644 index 00000000..f465c0bb Binary files /dev/null and b/assets/images/204.jpg differ diff --git a/assets/images/205.jpg b/assets/images/205.jpg new file mode 100644 index 00000000..9dedc86b Binary files /dev/null and b/assets/images/205.jpg differ diff --git a/assets/images/206.jpg b/assets/images/206.jpg new file mode 100644 index 00000000..405eaa3c Binary files /dev/null and b/assets/images/206.jpg differ diff --git a/assets/images/207.jpg b/assets/images/207.jpg new file mode 100644 index 00000000..1f23e9bb Binary files /dev/null and b/assets/images/207.jpg differ diff --git a/assets/images/208.jpg b/assets/images/208.jpg new file mode 100644 index 00000000..e2eccf57 Binary files /dev/null and b/assets/images/208.jpg differ diff --git a/assets/images/209.jpg b/assets/images/209.jpg new file mode 100644 index 00000000..87da205e Binary files /dev/null and b/assets/images/209.jpg differ diff --git a/assets/images/210.jpg b/assets/images/210.jpg new file mode 100644 index 00000000..07925bf8 Binary files /dev/null and b/assets/images/210.jpg differ diff --git a/assets/images/211.jpg b/assets/images/211.jpg new file mode 100644 index 00000000..91556561 Binary files /dev/null and b/assets/images/211.jpg differ diff --git a/assets/images/212.jpg b/assets/images/212.jpg new file mode 100644 index 00000000..5b75fe4a Binary files /dev/null and b/assets/images/212.jpg differ diff --git a/assets/images/213.jpg b/assets/images/213.jpg new file mode 100644 index 00000000..0bbb2a93 Binary files /dev/null and b/assets/images/213.jpg differ diff --git a/assets/images/214.jpg b/assets/images/214.jpg new file mode 100644 index 00000000..b2c86fa0 Binary files /dev/null and b/assets/images/214.jpg differ diff --git a/assets/images/215.jpg b/assets/images/215.jpg new file mode 100644 index 00000000..0dfeb799 Binary files /dev/null and b/assets/images/215.jpg differ diff --git a/assets/images/216.jpg b/assets/images/216.jpg new file mode 100644 index 00000000..a943b4dc Binary files /dev/null and b/assets/images/216.jpg differ diff --git a/assets/images/217.jpg b/assets/images/217.jpg new file mode 100644 index 00000000..2e3e0939 Binary files /dev/null and b/assets/images/217.jpg differ diff --git a/assets/images/218.jpg b/assets/images/218.jpg new file mode 100644 index 00000000..cdd79684 Binary files /dev/null and b/assets/images/218.jpg differ diff --git a/assets/images/219.jpg b/assets/images/219.jpg new file mode 100644 index 00000000..ca6e0116 Binary files /dev/null and b/assets/images/219.jpg differ diff --git a/assets/images/220.jpg b/assets/images/220.jpg new file mode 100644 index 00000000..9c74564e Binary files /dev/null and b/assets/images/220.jpg differ diff --git a/assets/images/221.jpg b/assets/images/221.jpg new file mode 100644 index 00000000..e8ed690a Binary files /dev/null and b/assets/images/221.jpg differ diff --git a/assets/images/222.jpg b/assets/images/222.jpg new file mode 100644 index 00000000..7e5aa0f2 Binary files /dev/null and b/assets/images/222.jpg differ diff --git a/assets/images/223.jpg b/assets/images/223.jpg new file mode 100644 index 00000000..60d2e524 Binary files /dev/null and b/assets/images/223.jpg differ diff --git a/assets/images/224.jpg b/assets/images/224.jpg new file mode 100644 index 00000000..77b7ec91 Binary files /dev/null and b/assets/images/224.jpg differ diff --git a/assets/images/225.jpg b/assets/images/225.jpg new file mode 100644 index 00000000..373d27d5 Binary files /dev/null and b/assets/images/225.jpg differ diff --git a/assets/images/226.jpg b/assets/images/226.jpg new file mode 100644 index 00000000..8bd8aa03 Binary files /dev/null and b/assets/images/226.jpg differ diff --git a/assets/images/227.jpg b/assets/images/227.jpg new file mode 100644 index 00000000..68b9dae5 Binary files /dev/null and b/assets/images/227.jpg differ diff --git a/assets/images/228.jpg b/assets/images/228.jpg new file mode 100644 index 00000000..f381c86a Binary files /dev/null and b/assets/images/228.jpg differ diff --git a/assets/images/229.jpg b/assets/images/229.jpg new file mode 100644 index 00000000..d1fa1bf3 Binary files /dev/null and b/assets/images/229.jpg differ diff --git a/assets/images/230.jpg b/assets/images/230.jpg new file mode 100644 index 00000000..7a7fb1b4 Binary files /dev/null and b/assets/images/230.jpg differ diff --git a/assets/images/231.jpg b/assets/images/231.jpg new file mode 100644 index 00000000..fbb326ce Binary files /dev/null and b/assets/images/231.jpg differ diff --git a/assets/images/232.jpg b/assets/images/232.jpg new file mode 100644 index 00000000..a53b3dbd Binary files /dev/null and b/assets/images/232.jpg differ diff --git a/assets/images/233.jpg b/assets/images/233.jpg new file mode 100644 index 00000000..722f7346 Binary files /dev/null and b/assets/images/233.jpg differ diff --git a/assets/images/234.jpg b/assets/images/234.jpg new file mode 100644 index 00000000..3e835bbe Binary files /dev/null and b/assets/images/234.jpg differ diff --git a/assets/images/235.jpg b/assets/images/235.jpg new file mode 100644 index 00000000..0df481c8 Binary files /dev/null and b/assets/images/235.jpg differ diff --git a/assets/images/236.jpg b/assets/images/236.jpg new file mode 100644 index 00000000..0df481c8 Binary files /dev/null and b/assets/images/236.jpg differ diff --git a/assets/images/237.jpg b/assets/images/237.jpg new file mode 100644 index 00000000..6261b318 Binary files /dev/null and b/assets/images/237.jpg differ diff --git a/assets/images/238.jpg b/assets/images/238.jpg new file mode 100644 index 00000000..c3a432af Binary files /dev/null and b/assets/images/238.jpg differ diff --git a/assets/images/239.jpg b/assets/images/239.jpg new file mode 100644 index 00000000..af50b3b3 Binary files /dev/null and b/assets/images/239.jpg differ diff --git a/assets/images/240.jpg b/assets/images/240.jpg new file mode 100644 index 00000000..ada5ba63 Binary files /dev/null and b/assets/images/240.jpg differ diff --git a/assets/images/241.jpg b/assets/images/241.jpg new file mode 100644 index 00000000..ea7a4ebd Binary files /dev/null and b/assets/images/241.jpg differ diff --git a/assets/images/242.jpg b/assets/images/242.jpg new file mode 100644 index 00000000..f6dbf310 Binary files /dev/null and b/assets/images/242.jpg differ diff --git a/assets/images/243.jpg b/assets/images/243.jpg new file mode 100644 index 00000000..3c7dcf11 Binary files /dev/null and b/assets/images/243.jpg differ diff --git a/assets/images/244.jpg b/assets/images/244.jpg new file mode 100644 index 00000000..522fc107 Binary files /dev/null and b/assets/images/244.jpg differ diff --git a/assets/images/245.jpg b/assets/images/245.jpg new file mode 100644 index 00000000..7b921b1f Binary files /dev/null and b/assets/images/245.jpg differ diff --git a/assets/images/246.jpg b/assets/images/246.jpg new file mode 100644 index 00000000..00485810 Binary files /dev/null and b/assets/images/246.jpg differ diff --git a/assets/images/247.jpg b/assets/images/247.jpg new file mode 100644 index 00000000..c753600d Binary files /dev/null and b/assets/images/247.jpg differ diff --git a/assets/images/248.jpg b/assets/images/248.jpg new file mode 100644 index 00000000..2eb8eb2d Binary files /dev/null and b/assets/images/248.jpg differ diff --git a/assets/images/249.jpg b/assets/images/249.jpg new file mode 100644 index 00000000..0e30341a Binary files /dev/null and b/assets/images/249.jpg differ diff --git a/assets/images/250.jpg b/assets/images/250.jpg new file mode 100644 index 00000000..1ce06018 Binary files /dev/null and b/assets/images/250.jpg differ diff --git a/assets/images/251.jpg b/assets/images/251.jpg new file mode 100644 index 00000000..69286d42 Binary files /dev/null and b/assets/images/251.jpg differ diff --git a/assets/images/252.jpg b/assets/images/252.jpg new file mode 100644 index 00000000..98d794d3 Binary files /dev/null and b/assets/images/252.jpg differ diff --git a/assets/images/253.jpg b/assets/images/253.jpg new file mode 100644 index 00000000..bb68197c Binary files /dev/null and b/assets/images/253.jpg differ diff --git a/assets/images/254.jpg b/assets/images/254.jpg new file mode 100644 index 00000000..d419b240 Binary files /dev/null and b/assets/images/254.jpg differ diff --git a/assets/images/255.jpg b/assets/images/255.jpg new file mode 100644 index 00000000..184fbe60 Binary files /dev/null and b/assets/images/255.jpg differ diff --git a/assets/images/256.jpg b/assets/images/256.jpg new file mode 100644 index 00000000..02ce715a Binary files /dev/null and b/assets/images/256.jpg differ diff --git a/assets/images/257.jpg b/assets/images/257.jpg new file mode 100644 index 00000000..86db49da Binary files /dev/null and b/assets/images/257.jpg differ diff --git a/assets/images/258.jpg b/assets/images/258.jpg new file mode 100644 index 00000000..8779c37d Binary files /dev/null and b/assets/images/258.jpg differ diff --git a/assets/images/259.jpg b/assets/images/259.jpg new file mode 100644 index 00000000..4a53aaf1 Binary files /dev/null and b/assets/images/259.jpg differ diff --git a/assets/images/260.jpg b/assets/images/260.jpg new file mode 100644 index 00000000..3334f311 Binary files /dev/null and b/assets/images/260.jpg differ diff --git a/assets/images/261.jpg b/assets/images/261.jpg new file mode 100644 index 00000000..14e13392 Binary files /dev/null and b/assets/images/261.jpg differ diff --git a/assets/images/262.jpg b/assets/images/262.jpg new file mode 100644 index 00000000..fd93957a Binary files /dev/null and b/assets/images/262.jpg differ diff --git a/assets/images/263.jpg b/assets/images/263.jpg new file mode 100644 index 00000000..6eda4092 Binary files /dev/null and b/assets/images/263.jpg differ diff --git a/assets/images/264.jpg b/assets/images/264.jpg new file mode 100644 index 00000000..6b08dd70 Binary files /dev/null and b/assets/images/264.jpg differ diff --git a/assets/images/265.jpg b/assets/images/265.jpg new file mode 100644 index 00000000..95950824 Binary files /dev/null and b/assets/images/265.jpg differ diff --git a/assets/images/266.jpg b/assets/images/266.jpg new file mode 100644 index 00000000..73b975fe Binary files /dev/null and b/assets/images/266.jpg differ diff --git a/assets/images/267.png b/assets/images/267.png new file mode 100644 index 00000000..bb059ba9 Binary files /dev/null and b/assets/images/267.png differ diff --git a/assets/images/268.jpg b/assets/images/268.jpg new file mode 100644 index 00000000..78d88713 Binary files /dev/null and b/assets/images/268.jpg differ diff --git a/assets/images/269.jpg b/assets/images/269.jpg new file mode 100644 index 00000000..8c73ade9 Binary files /dev/null and b/assets/images/269.jpg differ diff --git a/assets/images/270.jpg b/assets/images/270.jpg new file mode 100644 index 00000000..22018713 Binary files /dev/null and b/assets/images/270.jpg differ diff --git a/assets/images/271.jpg b/assets/images/271.jpg new file mode 100644 index 00000000..2daf2f10 Binary files /dev/null and b/assets/images/271.jpg differ diff --git a/assets/images/272.jpg b/assets/images/272.jpg new file mode 100644 index 00000000..233aeb82 Binary files /dev/null and b/assets/images/272.jpg differ diff --git a/assets/images/273.jpg b/assets/images/273.jpg new file mode 100644 index 00000000..419e61ff Binary files /dev/null and b/assets/images/273.jpg differ diff --git a/assets/images/274.jpg b/assets/images/274.jpg new file mode 100644 index 00000000..cc5c216b Binary files /dev/null and b/assets/images/274.jpg differ diff --git a/assets/images/275.jpg b/assets/images/275.jpg new file mode 100644 index 00000000..2f29c464 Binary files /dev/null and b/assets/images/275.jpg differ diff --git a/assets/images/276.jpg b/assets/images/276.jpg new file mode 100644 index 00000000..47cf5e95 Binary files /dev/null and b/assets/images/276.jpg differ diff --git a/assets/images/277.jpg b/assets/images/277.jpg new file mode 100644 index 00000000..73234c84 Binary files /dev/null and b/assets/images/277.jpg differ diff --git a/assets/images/278.jpg b/assets/images/278.jpg new file mode 100644 index 00000000..21ac60e6 Binary files /dev/null and b/assets/images/278.jpg differ diff --git a/assets/images/279.jpg b/assets/images/279.jpg new file mode 100644 index 00000000..f01f9afa Binary files /dev/null and b/assets/images/279.jpg differ diff --git a/assets/images/280.jpg b/assets/images/280.jpg new file mode 100644 index 00000000..8d8a47c3 Binary files /dev/null and b/assets/images/280.jpg differ diff --git a/assets/images/281.jpg b/assets/images/281.jpg new file mode 100644 index 00000000..897b6078 Binary files /dev/null and b/assets/images/281.jpg differ diff --git a/assets/images/282.jpg b/assets/images/282.jpg new file mode 100644 index 00000000..20d905e6 Binary files /dev/null and b/assets/images/282.jpg differ diff --git a/assets/images/283.jpg b/assets/images/283.jpg new file mode 100644 index 00000000..cdd94b34 Binary files /dev/null and b/assets/images/283.jpg differ diff --git a/assets/images/284.jpg b/assets/images/284.jpg new file mode 100644 index 00000000..170f4dca Binary files /dev/null and b/assets/images/284.jpg differ diff --git a/assets/images/285.jpg b/assets/images/285.jpg new file mode 100644 index 00000000..82933b66 Binary files /dev/null and b/assets/images/285.jpg differ diff --git a/assets/images/286.jpg b/assets/images/286.jpg new file mode 100644 index 00000000..f123d163 Binary files /dev/null and b/assets/images/286.jpg differ diff --git a/assets/images/287.jpg b/assets/images/287.jpg new file mode 100644 index 00000000..8ede40a9 Binary files /dev/null and b/assets/images/287.jpg differ diff --git a/assets/images/288.jpg b/assets/images/288.jpg new file mode 100644 index 00000000..dde37259 Binary files /dev/null and b/assets/images/288.jpg differ diff --git a/assets/images/289.jpg b/assets/images/289.jpg new file mode 100644 index 00000000..dc8c322e Binary files /dev/null and b/assets/images/289.jpg differ diff --git a/assets/images/290.jpg b/assets/images/290.jpg new file mode 100644 index 00000000..1ef756d9 Binary files /dev/null and b/assets/images/290.jpg differ diff --git a/assets/images/291.jpg b/assets/images/291.jpg new file mode 100644 index 00000000..bf08ac5b Binary files /dev/null and b/assets/images/291.jpg differ diff --git a/assets/images/292.jpg b/assets/images/292.jpg new file mode 100644 index 00000000..f927a237 Binary files /dev/null and b/assets/images/292.jpg differ diff --git a/assets/images/293.jpg b/assets/images/293.jpg new file mode 100644 index 00000000..a92e2a94 Binary files /dev/null and b/assets/images/293.jpg differ diff --git a/assets/images/294.jpg b/assets/images/294.jpg new file mode 100644 index 00000000..8a58d8e0 Binary files /dev/null and b/assets/images/294.jpg differ diff --git a/assets/images/295.jpg b/assets/images/295.jpg new file mode 100644 index 00000000..c25d0f8c Binary files /dev/null and b/assets/images/295.jpg differ diff --git a/assets/images/296.jpg b/assets/images/296.jpg new file mode 100644 index 00000000..846adfd2 Binary files /dev/null and b/assets/images/296.jpg differ diff --git a/assets/images/297.jpg b/assets/images/297.jpg new file mode 100644 index 00000000..4bdfc345 Binary files /dev/null and b/assets/images/297.jpg differ diff --git a/assets/images/298.jpg b/assets/images/298.jpg new file mode 100644 index 00000000..061d82ee Binary files /dev/null and b/assets/images/298.jpg differ diff --git a/assets/images/299.jpg b/assets/images/299.jpg new file mode 100644 index 00000000..958de9e9 Binary files /dev/null and b/assets/images/299.jpg differ diff --git a/assets/images/300.jpg b/assets/images/300.jpg new file mode 100644 index 00000000..ec1bd45b Binary files /dev/null and b/assets/images/300.jpg differ diff --git a/assets/images/301.jpg b/assets/images/301.jpg new file mode 100644 index 00000000..aa5300c8 Binary files /dev/null and b/assets/images/301.jpg differ diff --git a/assets/images/302.jpg b/assets/images/302.jpg new file mode 100644 index 00000000..d43a0058 Binary files /dev/null and b/assets/images/302.jpg differ diff --git a/assets/images/303.jpg b/assets/images/303.jpg new file mode 100644 index 00000000..fac6dd18 Binary files /dev/null and b/assets/images/303.jpg differ diff --git a/assets/images/304.jpg b/assets/images/304.jpg new file mode 100644 index 00000000..2f05ce70 Binary files /dev/null and b/assets/images/304.jpg differ diff --git a/assets/images/305.jpg b/assets/images/305.jpg new file mode 100644 index 00000000..330d4bf7 Binary files /dev/null and b/assets/images/305.jpg differ diff --git a/assets/images/306.jpg b/assets/images/306.jpg new file mode 100644 index 00000000..0d851fea Binary files /dev/null and b/assets/images/306.jpg differ diff --git a/assets/images/307.jpg b/assets/images/307.jpg new file mode 100644 index 00000000..48e94475 Binary files /dev/null and b/assets/images/307.jpg differ diff --git a/assets/images/308.jpg b/assets/images/308.jpg new file mode 100644 index 00000000..f17c488c Binary files /dev/null and b/assets/images/308.jpg differ diff --git a/assets/images/309.jpg b/assets/images/309.jpg new file mode 100644 index 00000000..5c1d121b Binary files /dev/null and b/assets/images/309.jpg differ diff --git a/assets/images/310.jpg b/assets/images/310.jpg new file mode 100644 index 00000000..7a042f4b Binary files /dev/null and b/assets/images/310.jpg differ diff --git a/assets/images/311.jpg b/assets/images/311.jpg new file mode 100644 index 00000000..ff3f74c6 Binary files /dev/null and b/assets/images/311.jpg differ diff --git a/assets/images/312.jpg b/assets/images/312.jpg new file mode 100644 index 00000000..7dcaeb4a Binary files /dev/null and b/assets/images/312.jpg differ diff --git a/assets/images/313.jpg b/assets/images/313.jpg new file mode 100644 index 00000000..2401f526 Binary files /dev/null and b/assets/images/313.jpg differ diff --git a/assets/images/314.jpg b/assets/images/314.jpg new file mode 100644 index 00000000..511c99fe Binary files /dev/null and b/assets/images/314.jpg differ diff --git a/assets/images/315.jpg b/assets/images/315.jpg new file mode 100644 index 00000000..622f1a70 Binary files /dev/null and b/assets/images/315.jpg differ diff --git a/assets/images/316.jpg b/assets/images/316.jpg new file mode 100644 index 00000000..e690578b Binary files /dev/null and b/assets/images/316.jpg differ diff --git a/assets/images/317.jpg b/assets/images/317.jpg new file mode 100644 index 00000000..246d332c Binary files /dev/null and b/assets/images/317.jpg differ diff --git a/assets/images/318.jpg b/assets/images/318.jpg new file mode 100644 index 00000000..5bacf5e0 Binary files /dev/null and b/assets/images/318.jpg differ diff --git a/assets/images/319.jpg b/assets/images/319.jpg new file mode 100644 index 00000000..eb8e33ec Binary files /dev/null and b/assets/images/319.jpg differ diff --git a/assets/images/320.jpg b/assets/images/320.jpg new file mode 100644 index 00000000..fda09a03 Binary files /dev/null and b/assets/images/320.jpg differ diff --git a/assets/images/321.jpg b/assets/images/321.jpg new file mode 100644 index 00000000..7c0fe5e8 Binary files /dev/null and b/assets/images/321.jpg differ diff --git a/assets/images/322.jpg b/assets/images/322.jpg new file mode 100644 index 00000000..450bd11b Binary files /dev/null and b/assets/images/322.jpg differ diff --git a/assets/images/323.jpg b/assets/images/323.jpg new file mode 100644 index 00000000..1c214ee6 Binary files /dev/null and b/assets/images/323.jpg differ diff --git a/assets/images/324.jpg b/assets/images/324.jpg new file mode 100644 index 00000000..7ac44d89 Binary files /dev/null and b/assets/images/324.jpg differ diff --git a/assets/images/325.jpg b/assets/images/325.jpg new file mode 100644 index 00000000..8106158b Binary files /dev/null and b/assets/images/325.jpg differ diff --git a/assets/images/326.jpg b/assets/images/326.jpg new file mode 100644 index 00000000..d0b273eb Binary files /dev/null and b/assets/images/326.jpg differ diff --git a/assets/images/327.jpg b/assets/images/327.jpg new file mode 100644 index 00000000..7cb8301a Binary files /dev/null and b/assets/images/327.jpg differ diff --git a/assets/images/328.jpg b/assets/images/328.jpg new file mode 100644 index 00000000..a0b4f026 Binary files /dev/null and b/assets/images/328.jpg differ diff --git a/assets/images/329.jpg b/assets/images/329.jpg new file mode 100644 index 00000000..ce630839 Binary files /dev/null and b/assets/images/329.jpg differ diff --git a/assets/images/330.jpg b/assets/images/330.jpg new file mode 100644 index 00000000..540b8645 Binary files /dev/null and b/assets/images/330.jpg differ diff --git a/assets/images/331.jpg b/assets/images/331.jpg new file mode 100644 index 00000000..480f1ae8 Binary files /dev/null and b/assets/images/331.jpg differ diff --git a/assets/images/332.jpg b/assets/images/332.jpg new file mode 100644 index 00000000..d2fe95d5 Binary files /dev/null and b/assets/images/332.jpg differ diff --git a/assets/images/333.jpg b/assets/images/333.jpg new file mode 100644 index 00000000..28ea7aa8 Binary files /dev/null and b/assets/images/333.jpg differ diff --git a/assets/images/334.jpg b/assets/images/334.jpg new file mode 100644 index 00000000..0d14b64b Binary files /dev/null and b/assets/images/334.jpg differ diff --git a/assets/images/335.jpg b/assets/images/335.jpg new file mode 100644 index 00000000..cc28939b Binary files /dev/null and b/assets/images/335.jpg differ diff --git a/assets/images/336.jpg b/assets/images/336.jpg new file mode 100644 index 00000000..ec142341 Binary files /dev/null and b/assets/images/336.jpg differ diff --git a/assets/images/337.jpg b/assets/images/337.jpg new file mode 100644 index 00000000..0a9bb3b4 Binary files /dev/null and b/assets/images/337.jpg differ diff --git a/assets/images/338.jpg b/assets/images/338.jpg new file mode 100644 index 00000000..ea691f5c Binary files /dev/null and b/assets/images/338.jpg differ diff --git a/assets/images/339.jpg b/assets/images/339.jpg new file mode 100644 index 00000000..7f1313c9 Binary files /dev/null and b/assets/images/339.jpg differ diff --git a/assets/images/340.jpg b/assets/images/340.jpg new file mode 100644 index 00000000..4abbf832 Binary files /dev/null and b/assets/images/340.jpg differ diff --git a/assets/images/341.jpg b/assets/images/341.jpg new file mode 100644 index 00000000..e7c43a10 Binary files /dev/null and b/assets/images/341.jpg differ diff --git a/assets/images/342.jpg b/assets/images/342.jpg new file mode 100644 index 00000000..40a277f2 Binary files /dev/null and b/assets/images/342.jpg differ diff --git a/assets/images/343.jpg b/assets/images/343.jpg new file mode 100644 index 00000000..e649afbe Binary files /dev/null and b/assets/images/343.jpg differ diff --git a/assets/images/344.jpg b/assets/images/344.jpg new file mode 100644 index 00000000..3bc8a948 Binary files /dev/null and b/assets/images/344.jpg differ diff --git a/assets/images/345.jpg b/assets/images/345.jpg new file mode 100644 index 00000000..45bad571 Binary files /dev/null and b/assets/images/345.jpg differ diff --git a/assets/images/346.jpg b/assets/images/346.jpg new file mode 100644 index 00000000..432280b9 Binary files /dev/null and b/assets/images/346.jpg differ diff --git a/assets/images/347.jpg b/assets/images/347.jpg new file mode 100644 index 00000000..7e84ec27 Binary files /dev/null and b/assets/images/347.jpg differ diff --git a/assets/images/348.jpg b/assets/images/348.jpg new file mode 100644 index 00000000..f3ff64e5 Binary files /dev/null and b/assets/images/348.jpg differ diff --git a/assets/images/349.jpg b/assets/images/349.jpg new file mode 100644 index 00000000..5d12798a Binary files /dev/null and b/assets/images/349.jpg differ diff --git a/assets/images/350.jpg b/assets/images/350.jpg new file mode 100644 index 00000000..15decb89 Binary files /dev/null and b/assets/images/350.jpg differ diff --git a/assets/images/351.jpg b/assets/images/351.jpg new file mode 100644 index 00000000..ddcf8877 Binary files /dev/null and b/assets/images/351.jpg differ diff --git a/assets/images/352.jpg b/assets/images/352.jpg new file mode 100644 index 00000000..877f88f5 Binary files /dev/null and b/assets/images/352.jpg differ diff --git a/assets/images/353.jpg b/assets/images/353.jpg new file mode 100644 index 00000000..d35de1e2 Binary files /dev/null and b/assets/images/353.jpg differ diff --git a/assets/images/354.jpg b/assets/images/354.jpg new file mode 100644 index 00000000..c3bf5f90 Binary files /dev/null and b/assets/images/354.jpg differ diff --git a/assets/images/355.jpg b/assets/images/355.jpg new file mode 100644 index 00000000..1ab76792 Binary files /dev/null and b/assets/images/355.jpg differ diff --git a/assets/images/356.jpg b/assets/images/356.jpg new file mode 100644 index 00000000..7c70bac8 Binary files /dev/null and b/assets/images/356.jpg differ diff --git a/assets/images/357.jpg b/assets/images/357.jpg new file mode 100644 index 00000000..b7f6edfd Binary files /dev/null and b/assets/images/357.jpg differ diff --git a/assets/images/358.jpg b/assets/images/358.jpg new file mode 100644 index 00000000..36aae949 Binary files /dev/null and b/assets/images/358.jpg differ diff --git a/assets/images/359.jpg b/assets/images/359.jpg new file mode 100644 index 00000000..a4adbb57 Binary files /dev/null and b/assets/images/359.jpg differ diff --git a/assets/images/360.jpg b/assets/images/360.jpg new file mode 100644 index 00000000..c05133c8 Binary files /dev/null and b/assets/images/360.jpg differ diff --git a/assets/images/361.jpg b/assets/images/361.jpg new file mode 100644 index 00000000..ea011809 Binary files /dev/null and b/assets/images/361.jpg differ diff --git a/assets/images/362.jpg b/assets/images/362.jpg new file mode 100644 index 00000000..a4110b26 Binary files /dev/null and b/assets/images/362.jpg differ diff --git a/assets/images/363.jpg b/assets/images/363.jpg new file mode 100644 index 00000000..43695b02 Binary files /dev/null and b/assets/images/363.jpg differ diff --git a/assets/images/364.jpg b/assets/images/364.jpg new file mode 100644 index 00000000..9867e404 Binary files /dev/null and b/assets/images/364.jpg differ diff --git a/assets/images/365.jpg b/assets/images/365.jpg new file mode 100644 index 00000000..e2e78647 Binary files /dev/null and b/assets/images/365.jpg differ diff --git a/assets/images/366.jpg b/assets/images/366.jpg new file mode 100644 index 00000000..67515ce9 Binary files /dev/null and b/assets/images/366.jpg differ diff --git a/assets/images/367.jpg b/assets/images/367.jpg new file mode 100644 index 00000000..39190102 Binary files /dev/null and b/assets/images/367.jpg differ diff --git a/assets/images/368.jpg b/assets/images/368.jpg new file mode 100644 index 00000000..6edd78e2 Binary files /dev/null and b/assets/images/368.jpg differ diff --git a/assets/images/370.jpg b/assets/images/370.jpg new file mode 100644 index 00000000..6fdab4fd Binary files /dev/null and b/assets/images/370.jpg differ diff --git a/assets/images/371.jpg b/assets/images/371.jpg new file mode 100644 index 00000000..acf2deda Binary files /dev/null and b/assets/images/371.jpg differ diff --git a/assets/images/372.jpg b/assets/images/372.jpg new file mode 100644 index 00000000..52445fae Binary files /dev/null and b/assets/images/372.jpg differ diff --git a/assets/images/373.jpg b/assets/images/373.jpg new file mode 100644 index 00000000..ddf137f8 Binary files /dev/null and b/assets/images/373.jpg differ diff --git a/assets/images/374.jpg b/assets/images/374.jpg new file mode 100644 index 00000000..fb22998c Binary files /dev/null and b/assets/images/374.jpg differ diff --git a/assets/images/375.jpg b/assets/images/375.jpg new file mode 100644 index 00000000..d730db23 Binary files /dev/null and b/assets/images/375.jpg differ diff --git a/assets/images/376.jpg b/assets/images/376.jpg new file mode 100644 index 00000000..2b3534db Binary files /dev/null and b/assets/images/376.jpg differ diff --git a/assets/images/377.jpg b/assets/images/377.jpg new file mode 100644 index 00000000..73d2fc0d Binary files /dev/null and b/assets/images/377.jpg differ diff --git a/assets/images/378.jpg b/assets/images/378.jpg new file mode 100644 index 00000000..22e780a1 Binary files /dev/null and b/assets/images/378.jpg differ diff --git a/assets/images/379.jpg b/assets/images/379.jpg new file mode 100644 index 00000000..321e6a7f Binary files /dev/null and b/assets/images/379.jpg differ diff --git a/assets/images/380.jpg b/assets/images/380.jpg new file mode 100644 index 00000000..8c29496d Binary files /dev/null and b/assets/images/380.jpg differ diff --git a/assets/images/381.jpg b/assets/images/381.jpg new file mode 100644 index 00000000..58f26c47 Binary files /dev/null and b/assets/images/381.jpg differ diff --git a/assets/images/382.jpg b/assets/images/382.jpg new file mode 100644 index 00000000..0b6c297f Binary files /dev/null and b/assets/images/382.jpg differ diff --git a/assets/images/383.jpg b/assets/images/383.jpg new file mode 100644 index 00000000..fafe75fc Binary files /dev/null and b/assets/images/383.jpg differ diff --git a/assets/images/384.jpg b/assets/images/384.jpg new file mode 100644 index 00000000..8397be00 Binary files /dev/null and b/assets/images/384.jpg differ diff --git a/assets/images/385.jpg b/assets/images/385.jpg new file mode 100644 index 00000000..51a964f4 Binary files /dev/null and b/assets/images/385.jpg differ diff --git a/assets/images/386.jpg b/assets/images/386.jpg new file mode 100644 index 00000000..55643222 Binary files /dev/null and b/assets/images/386.jpg differ diff --git a/assets/images/387.jpg b/assets/images/387.jpg new file mode 100644 index 00000000..eed1e1b8 Binary files /dev/null and b/assets/images/387.jpg differ diff --git a/assets/images/388.jpg b/assets/images/388.jpg new file mode 100644 index 00000000..e1ecb25b Binary files /dev/null and b/assets/images/388.jpg differ diff --git a/assets/images/389.jpg b/assets/images/389.jpg new file mode 100644 index 00000000..7aa7f911 Binary files /dev/null and b/assets/images/389.jpg differ diff --git a/assets/images/390.jpg b/assets/images/390.jpg new file mode 100644 index 00000000..04568e74 Binary files /dev/null and b/assets/images/390.jpg differ diff --git a/assets/images/391.jpg b/assets/images/391.jpg new file mode 100644 index 00000000..0ed56cb3 Binary files /dev/null and b/assets/images/391.jpg differ diff --git a/assets/images/392.jpg b/assets/images/392.jpg new file mode 100644 index 00000000..3f394880 Binary files /dev/null and b/assets/images/392.jpg differ diff --git a/assets/images/393.jpg b/assets/images/393.jpg new file mode 100644 index 00000000..1bd81a7a Binary files /dev/null and b/assets/images/393.jpg differ diff --git a/assets/images/394.jpg b/assets/images/394.jpg new file mode 100644 index 00000000..2de2b7c1 Binary files /dev/null and b/assets/images/394.jpg differ diff --git a/assets/images/395.jpg b/assets/images/395.jpg new file mode 100644 index 00000000..5de01c6e Binary files /dev/null and b/assets/images/395.jpg differ diff --git a/assets/images/396.jpg b/assets/images/396.jpg new file mode 100644 index 00000000..15e74e7e Binary files /dev/null and b/assets/images/396.jpg differ diff --git a/assets/images/397.jpg b/assets/images/397.jpg new file mode 100644 index 00000000..b6dcdf8a Binary files /dev/null and b/assets/images/397.jpg differ diff --git a/assets/images/398.jpg b/assets/images/398.jpg new file mode 100644 index 00000000..b6dcdf8a Binary files /dev/null and b/assets/images/398.jpg differ diff --git a/assets/images/399.jpg b/assets/images/399.jpg new file mode 100644 index 00000000..8a4261bb Binary files /dev/null and b/assets/images/399.jpg differ diff --git a/assets/images/400.jpg b/assets/images/400.jpg new file mode 100644 index 00000000..624350a8 Binary files /dev/null and b/assets/images/400.jpg differ diff --git a/assets/images/401.jpg b/assets/images/401.jpg new file mode 100644 index 00000000..365e8bee Binary files /dev/null and b/assets/images/401.jpg differ diff --git a/assets/images/402.jpg b/assets/images/402.jpg new file mode 100644 index 00000000..e3b3fbe7 Binary files /dev/null and b/assets/images/402.jpg differ diff --git a/assets/images/403.jpg b/assets/images/403.jpg new file mode 100644 index 00000000..a5d834e2 Binary files /dev/null and b/assets/images/403.jpg differ diff --git a/assets/images/404.jpg b/assets/images/404.jpg new file mode 100644 index 00000000..2d3aae83 Binary files /dev/null and b/assets/images/404.jpg differ diff --git a/assets/images/405.jpg b/assets/images/405.jpg new file mode 100644 index 00000000..7bc9a825 Binary files /dev/null and b/assets/images/405.jpg differ diff --git a/assets/images/406.jpg b/assets/images/406.jpg new file mode 100644 index 00000000..3c959104 Binary files /dev/null and b/assets/images/406.jpg differ diff --git a/assets/images/407.jpg b/assets/images/407.jpg new file mode 100644 index 00000000..eace28d2 Binary files /dev/null and b/assets/images/407.jpg differ diff --git a/assets/images/408.jpg b/assets/images/408.jpg new file mode 100644 index 00000000..3aecb9ba Binary files /dev/null and b/assets/images/408.jpg differ diff --git a/assets/images/409.jpg b/assets/images/409.jpg new file mode 100644 index 00000000..8ee05ea6 Binary files /dev/null and b/assets/images/409.jpg differ diff --git a/assets/images/410.jpg b/assets/images/410.jpg new file mode 100644 index 00000000..b6813ad1 Binary files /dev/null and b/assets/images/410.jpg differ diff --git a/assets/images/411.jpg b/assets/images/411.jpg new file mode 100644 index 00000000..97b6271d Binary files /dev/null and b/assets/images/411.jpg differ diff --git a/assets/images/412.jpg b/assets/images/412.jpg new file mode 100644 index 00000000..f8b27613 Binary files /dev/null and b/assets/images/412.jpg differ diff --git a/assets/images/413.jpg b/assets/images/413.jpg new file mode 100644 index 00000000..f58642cb Binary files /dev/null and b/assets/images/413.jpg differ diff --git a/assets/images/414.jpg b/assets/images/414.jpg new file mode 100644 index 00000000..f3afb16a Binary files /dev/null and b/assets/images/414.jpg differ diff --git a/assets/images/415.jpg b/assets/images/415.jpg new file mode 100644 index 00000000..e4616895 Binary files /dev/null and b/assets/images/415.jpg differ diff --git a/assets/images/416.jpg b/assets/images/416.jpg new file mode 100644 index 00000000..b722b47f Binary files /dev/null and b/assets/images/416.jpg differ diff --git a/assets/images/417.jpg b/assets/images/417.jpg new file mode 100644 index 00000000..5f522872 Binary files /dev/null and b/assets/images/417.jpg differ diff --git a/assets/images/418.jpg b/assets/images/418.jpg new file mode 100644 index 00000000..5d4fce9d Binary files /dev/null and b/assets/images/418.jpg differ diff --git a/assets/images/419.jpg b/assets/images/419.jpg new file mode 100644 index 00000000..57fc552d Binary files /dev/null and b/assets/images/419.jpg differ diff --git a/assets/images/420.jpg b/assets/images/420.jpg new file mode 100644 index 00000000..db016b93 Binary files /dev/null and b/assets/images/420.jpg differ diff --git a/assets/images/421.jpg b/assets/images/421.jpg new file mode 100644 index 00000000..bb508a93 Binary files /dev/null and b/assets/images/421.jpg differ diff --git a/assets/images/422.jpg b/assets/images/422.jpg new file mode 100644 index 00000000..bedb6054 Binary files /dev/null and b/assets/images/422.jpg differ diff --git a/assets/images/423.jpg b/assets/images/423.jpg new file mode 100644 index 00000000..95bcb018 Binary files /dev/null and b/assets/images/423.jpg differ diff --git a/assets/images/424.jpg b/assets/images/424.jpg new file mode 100644 index 00000000..044f87a8 Binary files /dev/null and b/assets/images/424.jpg differ diff --git a/assets/images/425.jpg b/assets/images/425.jpg new file mode 100644 index 00000000..96cfa38c Binary files /dev/null and b/assets/images/425.jpg differ diff --git a/assets/images/426.jpg b/assets/images/426.jpg new file mode 100644 index 00000000..10ceb988 Binary files /dev/null and b/assets/images/426.jpg differ diff --git a/assets/images/427.jpg b/assets/images/427.jpg new file mode 100644 index 00000000..5290aec6 Binary files /dev/null and b/assets/images/427.jpg differ diff --git a/assets/images/428.jpg b/assets/images/428.jpg new file mode 100644 index 00000000..105f6297 Binary files /dev/null and b/assets/images/428.jpg differ diff --git a/assets/images/429.jpg b/assets/images/429.jpg new file mode 100644 index 00000000..d1bf4f81 Binary files /dev/null and b/assets/images/429.jpg differ diff --git a/assets/images/430.jpg b/assets/images/430.jpg new file mode 100644 index 00000000..9adee733 Binary files /dev/null and b/assets/images/430.jpg differ diff --git a/assets/images/431.jpg b/assets/images/431.jpg new file mode 100644 index 00000000..93b5d030 Binary files /dev/null and b/assets/images/431.jpg differ diff --git a/assets/images/432.jpg b/assets/images/432.jpg new file mode 100644 index 00000000..e9c800e8 Binary files /dev/null and b/assets/images/432.jpg differ diff --git a/assets/images/433.jpg b/assets/images/433.jpg new file mode 100644 index 00000000..53002886 Binary files /dev/null and b/assets/images/433.jpg differ diff --git a/assets/images/434.jpg b/assets/images/434.jpg new file mode 100644 index 00000000..fa3945b2 Binary files /dev/null and b/assets/images/434.jpg differ diff --git a/assets/images/435.jpg b/assets/images/435.jpg new file mode 100644 index 00000000..3bf28244 Binary files /dev/null and b/assets/images/435.jpg differ diff --git a/assets/images/436.jpg b/assets/images/436.jpg new file mode 100644 index 00000000..9a139266 Binary files /dev/null and b/assets/images/436.jpg differ diff --git a/assets/images/437.jpg b/assets/images/437.jpg new file mode 100644 index 00000000..83b294d9 Binary files /dev/null and b/assets/images/437.jpg differ diff --git a/assets/images/438.jpg b/assets/images/438.jpg new file mode 100644 index 00000000..c491823b Binary files /dev/null and b/assets/images/438.jpg differ diff --git a/assets/images/439.jpg b/assets/images/439.jpg new file mode 100644 index 00000000..3a8d2531 Binary files /dev/null and b/assets/images/439.jpg differ diff --git a/assets/images/440.jpg b/assets/images/440.jpg new file mode 100644 index 00000000..9114a740 Binary files /dev/null and b/assets/images/440.jpg differ diff --git a/assets/images/441.jpg b/assets/images/441.jpg new file mode 100644 index 00000000..18ab03ec Binary files /dev/null and b/assets/images/441.jpg differ diff --git a/assets/images/442.jpg b/assets/images/442.jpg new file mode 100644 index 00000000..7fb2b6ce Binary files /dev/null and b/assets/images/442.jpg differ diff --git a/assets/images/443.jpg b/assets/images/443.jpg new file mode 100644 index 00000000..753a98bf Binary files /dev/null and b/assets/images/443.jpg differ diff --git a/assets/images/444.jpg b/assets/images/444.jpg new file mode 100644 index 00000000..bb5dd40a Binary files /dev/null and b/assets/images/444.jpg differ diff --git a/assets/images/445.jpg b/assets/images/445.jpg new file mode 100644 index 00000000..f81c5e7a Binary files /dev/null and b/assets/images/445.jpg differ diff --git a/assets/images/446.jpg b/assets/images/446.jpg new file mode 100644 index 00000000..45c0ec5d Binary files /dev/null and b/assets/images/446.jpg differ diff --git a/assets/images/447.jpg b/assets/images/447.jpg new file mode 100644 index 00000000..7c0f7372 Binary files /dev/null and b/assets/images/447.jpg differ diff --git a/assets/images/448.jpg b/assets/images/448.jpg new file mode 100644 index 00000000..fd13db09 Binary files /dev/null and b/assets/images/448.jpg differ diff --git a/assets/images/449.jpg b/assets/images/449.jpg new file mode 100644 index 00000000..981f3dc2 Binary files /dev/null and b/assets/images/449.jpg differ diff --git a/assets/images/450.jpg b/assets/images/450.jpg new file mode 100644 index 00000000..3ded9f1a Binary files /dev/null and b/assets/images/450.jpg differ diff --git a/assets/images/451.jpg b/assets/images/451.jpg new file mode 100644 index 00000000..f4ed55b0 Binary files /dev/null and b/assets/images/451.jpg differ diff --git a/assets/images/452.jpg b/assets/images/452.jpg new file mode 100644 index 00000000..68927b06 Binary files /dev/null and b/assets/images/452.jpg differ diff --git a/assets/images/453.jpg b/assets/images/453.jpg new file mode 100644 index 00000000..bc949f43 Binary files /dev/null and b/assets/images/453.jpg differ diff --git a/assets/images/454.jpg b/assets/images/454.jpg new file mode 100644 index 00000000..12a694e1 Binary files /dev/null and b/assets/images/454.jpg differ diff --git a/assets/images/455.jpg b/assets/images/455.jpg new file mode 100644 index 00000000..67595e54 Binary files /dev/null and b/assets/images/455.jpg differ diff --git a/assets/images/456.jpg b/assets/images/456.jpg new file mode 100644 index 00000000..6c8d4c96 Binary files /dev/null and b/assets/images/456.jpg differ diff --git a/assets/images/457.jpg b/assets/images/457.jpg new file mode 100644 index 00000000..b9964034 Binary files /dev/null and b/assets/images/457.jpg differ diff --git a/assets/images/458.jpg b/assets/images/458.jpg new file mode 100644 index 00000000..7f24af1e Binary files /dev/null and b/assets/images/458.jpg differ diff --git a/assets/images/459.jpg b/assets/images/459.jpg new file mode 100644 index 00000000..cab01b79 Binary files /dev/null and b/assets/images/459.jpg differ diff --git a/assets/images/460.jpg b/assets/images/460.jpg new file mode 100644 index 00000000..bc2e5c5f Binary files /dev/null and b/assets/images/460.jpg differ diff --git a/assets/images/461.jpg b/assets/images/461.jpg new file mode 100644 index 00000000..4820c410 Binary files /dev/null and b/assets/images/461.jpg differ diff --git a/assets/images/462.jpg b/assets/images/462.jpg new file mode 100644 index 00000000..1ae9d84f Binary files /dev/null and b/assets/images/462.jpg differ diff --git a/assets/images/463.jpg b/assets/images/463.jpg new file mode 100644 index 00000000..38109403 Binary files /dev/null and b/assets/images/463.jpg differ diff --git a/assets/images/464.jpg b/assets/images/464.jpg new file mode 100644 index 00000000..7a7576ea Binary files /dev/null and b/assets/images/464.jpg differ diff --git a/assets/images/465.jpg b/assets/images/465.jpg new file mode 100644 index 00000000..19420002 Binary files /dev/null and b/assets/images/465.jpg differ diff --git a/assets/images/466.jpg b/assets/images/466.jpg new file mode 100644 index 00000000..09eff6a3 Binary files /dev/null and b/assets/images/466.jpg differ diff --git a/assets/images/467.jpg b/assets/images/467.jpg new file mode 100644 index 00000000..ad43767a Binary files /dev/null and b/assets/images/467.jpg differ diff --git a/assets/images/468.jpg b/assets/images/468.jpg new file mode 100644 index 00000000..e59037d0 Binary files /dev/null and b/assets/images/468.jpg differ diff --git a/assets/images/469.jpg b/assets/images/469.jpg new file mode 100644 index 00000000..85684f6e Binary files /dev/null and b/assets/images/469.jpg differ diff --git a/assets/images/87.jpg b/assets/images/87.jpg new file mode 100644 index 00000000..f0524a16 Binary files /dev/null and b/assets/images/87.jpg differ diff --git a/assets/images/88.jpg b/assets/images/88.jpg new file mode 100644 index 00000000..870e4247 Binary files /dev/null and b/assets/images/88.jpg differ diff --git a/assets/images/89.jpg b/assets/images/89.jpg new file mode 100644 index 00000000..6f795900 Binary files /dev/null and b/assets/images/89.jpg differ diff --git a/assets/images/90.jpg b/assets/images/90.jpg new file mode 100644 index 00000000..1914741b Binary files /dev/null and b/assets/images/90.jpg differ diff --git a/assets/images/91.jpg b/assets/images/91.jpg new file mode 100644 index 00000000..befc3dd2 Binary files /dev/null and b/assets/images/91.jpg differ diff --git a/assets/images/92.jpg b/assets/images/92.jpg new file mode 100644 index 00000000..d441731d Binary files /dev/null and b/assets/images/92.jpg differ diff --git a/assets/images/93.jpg b/assets/images/93.jpg new file mode 100644 index 00000000..4aa587ba Binary files /dev/null and b/assets/images/93.jpg differ diff --git a/assets/images/94.jpg b/assets/images/94.jpg new file mode 100644 index 00000000..8b227f26 Binary files /dev/null and b/assets/images/94.jpg differ diff --git a/assets/images/95.jpg b/assets/images/95.jpg new file mode 100644 index 00000000..c79cc02e Binary files /dev/null and b/assets/images/95.jpg differ diff --git a/assets/images/96.jpg b/assets/images/96.jpg new file mode 100644 index 00000000..e03716bb Binary files /dev/null and b/assets/images/96.jpg differ diff --git a/assets/images/97.jpg b/assets/images/97.jpg new file mode 100644 index 00000000..8f92f0f6 Binary files /dev/null and b/assets/images/97.jpg differ diff --git a/assets/images/98.jpg b/assets/images/98.jpg new file mode 100644 index 00000000..9fa144f0 Binary files /dev/null and b/assets/images/98.jpg differ diff --git a/assets/images/99.jpg b/assets/images/99.jpg new file mode 100644 index 00000000..c69c7e0f Binary files /dev/null and b/assets/images/99.jpg differ diff --git a/assets/images/global.png b/assets/images/global.png new file mode 100644 index 00000000..f7b2ff26 Binary files /dev/null and b/assets/images/global.png differ diff --git a/assets/src/ABT/ABT.md b/assets/src/ABT/ABT.md index d7d47252..b8c46f79 100644 --- a/assets/src/ABT/ABT.md +++ b/assets/src/ABT/ABT.md @@ -12,6 +12,7 @@ 如今的机器学习领域主要的研究工作在三个方面进行:1)面向任务的研究,研究和分析改进一组预定任务的执行性能的学习系统;2)认知模型,研究人类学习过程并进行计算模拟;3)理论的分析,从理论的层面探索可能的算法和独立的应用领域算法。 #### AdaBoost + 自适应提升(AdaBoost:Adaptive Boosting)算法是基于概率近似正确的学习模型下提出的一种提升算法。在分类问题中,AdaBoost通过修改训练样本的权值分布,学习多个弱分类器,并将这些分类器进行线性组合,构成一个强分类器,提高分类性能。其中强分类器可理解为分类精确度高的算法,弱分类器可理解为分类精度低的算法,一般AdaBoost算法是弱分类器的线性组合为:

diff --git a/assets/src/ANN/ANN.0.1.md b/assets/src/ANN/ANN.0.1.md new file mode 100644 index 00000000..063caccc --- /dev/null +++ b/assets/src/ANN/ANN.0.1.md @@ -0,0 +1,40 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! + +机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 + +(1)监督学习:从给定的训练数据集中学习出一个函数,当新的数据输入时,可以根据函数预测相应的结果。监督学习的训练集要求是包括输入和输出,也就是特征和目标。训练集中的目标是有标注的。如今机器学习已固有的监督学习算法有可以进行分类的,例如贝叶斯分类,SVM,ID3,C4.5以及分类决策树,以及现在最火热的人工神经网络,例如BP神经网络,RBF神经网络,Hopfield神经网络、深度信念网络和卷积神经网络等。人工神经网络是模拟人大脑的思考方式来进行分析,在人工神经网络中有显层,隐层以及输出层,而每一层都会有神经元,神经元的状态或开启或关闭,这取决于大数据。同样监督机器学习算法也可以作回归,最常用便是逻辑回归。 + +(2)无监督学习:与有监督学习相比,无监督学习的训练集的类标号是未知的,并且要学习的类的个数或集合可能事先不知道。常见的无监督学习算法包括聚类和关联,例如K均值法、Apriori算法。 + +(3)半监督学习:介于监督学习和无监督学习之间,例如EM算法。 + +如今的机器学习领域主要的研究工作在三个方面进行:1)面向任务的研究,研究和分析改进一组预定任务的执行性能的学习系统;2)认知模型,研究人类学习过程并进行计算模拟;3)理论的分析,从理论的层面探索可能的算法和独立的应用领域算法。 + +#### 人工神经网络(Artificial Neural Network) + +人工神经网络 (Artificial Neural Network,ANN)简称神经网络(NN),是基于生物学中神经网络的基本原理,在理解和抽象了人脑结构和外界刺激响应机制后,以网络拓扑知识为理论基础,模拟人脑的神经系统对复杂信息的处理机制的一种数学模型,根植于神经科学、数学、思维科学、人工智能、统计学、物理学、计算机科学以及工程科学的一门技术,通常用于解决分类和回归问题。具有并行分布的处理能力、高容错性、智能化和自学习等能力的特征,本质上是一个有大量简单元件相互连接而成的复杂网络,具有高度的非线性,能够进行复杂的逻辑操作和非线性关系实现的系统。 + +神经网络由大量的节点(或称神经元)之间相互联接构成,每个节点代表一种特定的输出函数,称为激活函数(activation function);每两个节点间的连接都代表一个对于通过该连接信号的加权值,称之为权重(weight),神经网络就是通过这种方式来模拟人类的记忆。网络的输出则取决于网络的结构、网络的连接方式、权重和激活函数。而网络自身通常都是对自然界某种算法或者函数的逼近,也可能是对一种逻辑策略的表达,是对传统逻辑学演算的进一步延伸。 + +

+ +

+ + +人工神经网络中,神经元处理单元可表示不同的对象,例如特征、字母、概念,或者一些有意义的抽象模式。网络中处理单元的类型分为三类:输入单元、输出单元和隐单元。输入单元接受外部世界的信号与数据;输出单元实现系统处理结果的输出;隐单元是处在输入和输出单元之间,不能由系统外部观察的单元。神经元间的连接权值反映了单元间的连接强度,信息的表示和处理体现在网络处理单元的连接关系中。 + +应用领域:神经网络克服了传统人工智能方法对于直觉的缺陷,因而在神经专家系统、模式识别、智能控制、组合优化、预测等领域有成功的应用。 + +人工神经网络(Artificial Neural Network)算法应用: + * 自动编码器(Autoencoder) + * 反向传播(Backpropagation) + * 递归神经网络(Recurrent Neural Network) + * 多层感知器(Multilayer Perceptron) + * 玻尔兹曼机(Boltzmann Machine) + * 卷积神经网络(Convolutional Neural Network) + * Hopfield网络(Hopfield Network)]() + * 径向基函数网络(Radial Basis Function Network) + * 受限玻尔兹曼机(Restricted Boltzmann Machine) + * 自组织映射(Self-Organizing Map) + * 尖峰神经网络(Spiking Neural Network) diff --git a/assets/src/ANN/ANN.0.10.md b/assets/src/ANN/ANN.0.10.md new file mode 100644 index 00000000..6e42eb57 --- /dev/null +++ b/assets/src/ANN/ANN.0.10.md @@ -0,0 +1,299 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! + +机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 + +(1)监督学习:从给定的训练数据集中学习出一个函数,当新的数据输入时,可以根据函数预测相应的结果。监督学习的训练集要求是包括输入和输出,也就是特征和目标。训练集中的目标是有标注的。如今机器学习已固有的监督学习算法有可以进行分类的,例如贝叶斯分类,SVM,ID3,C4.5以及分类决策树,以及现在最火热的人工神经网络,例如BP神经网络,RBF神经网络,Hopfield神经网络、深度信念网络和卷积神经网络等。人工神经网络是模拟人大脑的思考方式来进行分析,在人工神经网络中有显层,隐层以及输出层,而每一层都会有神经元,神经元的状态或开启或关闭,这取决于大数据。同样监督机器学习算法也可以作回归,最常用便是逻辑回归。 + +(2)无监督学习:与有监督学习相比,无监督学习的训练集的类标号是未知的,并且要学习的类的个数或集合可能事先不知道。常见的无监督学习算法包括聚类和关联,例如K均值法、Apriori算法。 + +(3)半监督学习:介于监督学习和无监督学习之间,例如EM算法。 + +如今的机器学习领域主要的研究工作在三个方面进行:1)面向任务的研究,研究和分析改进一组预定任务的执行性能的学习系统;2)认知模型,研究人类学习过程并进行计算模拟;3)理论的分析,从理论的层面探索可能的算法和独立的应用领域算法。 + +#### 受限玻尔兹曼机(Restricted Boltzmann Machine) +受限玻尔兹曼机(Restricted Boltzmann Machine,RBM)是一种可用随机神经网络(stochastic neural network)来解释的概率图模型(probabilistic graphical model)。RBM是Smolensky于1986年在波尔兹曼机(Boltzmann Machine,BM)基础上提出的,所谓“随机”是指网络中的神经元是随机神经元,输出状态只有两种(未激活和激活),状态的具体取值根据概率统计法则来决定。RBM理论是Hinton在2006年提出基于RBM的(Deep Belief Network)模型,大量学者开始研究RBM的理论及其应用。 + +受限玻尔兹曼机(Restricted Boltzmann Machine)是玻尔兹曼机(Boltzmann machine,BM)的一种特殊拓扑结构。BM的原理起源于统计物理学,是一种基于能量函数的建模方法,能够描述变量之间的高阶相互作用,BM的学习算法较复杂,但所建模型和学习算法有比较完备的物理解释和严格的数理统计理论作基础。 +BM是一种对称耦合的随机反馈型二值单元神经网络,由可见层和多个隐层组成,网络节点分为可见单元(visible unit)和隐单元(hidden unit),用可见单元和隐单元来表达随机网络与随机环境的学习模型,通过权值表达单元之间的相关性。 + +

+ +

+ +Smolensky提出的RBM由一个可见神经元层和一个隐神经元层组成,由于隐层神经元之间没有相互连接并且隐层神经元独立于给定的训练样本,这使直接计算依赖数据的期望值变得容易,可见层神经元之间也没有相互连接,通过从训练样本得到的隐层神经元状态上执行马尔可夫链抽样过程,来估计独立于数据的期望值,并行交替更新所有可见层神经元和隐层神经元的值。 + +受限玻兹曼机是一种玻兹曼机的变体,但限定模型必须为二分图。模型中包含对应输入参数的输入(可见)单元和对应训练结果的隐单元,图中的每条边必须连接一个可见单元和一个隐单元。(与此相对,“无限制”玻兹曼机包含隐单元间的边,使之成为递归神经网络。)这一限定使得相比一般玻兹曼机更高效的训练算法成为可能,特别是基于梯度的对比分歧(contrastive divergence)算法。 + +受限玻兹曼机也可被用于深度学习网络。具体地,深度信念网络可使用多个RBM堆叠而成,并可使用梯度下降法和反向传播算法进行调优 + +RBM是有两个层的浅层神经网络,它是组成深度置信网络的基础部件。RBM的第一个层称为可见层,又称输入层,而第二个层是隐藏层。 + +

+ +

+ +图中每个圆圈都是一个与神经元相似的单元,称为节点,运算在节点中进行。一个层中的节点与另一层中的所有节点分别连接,但与同一层中的其他节点并不相连。 + +也就是说,层的内部不存在通信-这就是受限玻尔兹曼机被称为受限的原因。每个节点对输入进行处理和运算,判定是否继续传输输入的数据,而这种判定一开始是随机的。(“随机”(stochastic)一词在此处指与输入相乘的初始系数是随机生成的。) + +每个可见节点负责处理网络需要学习的数据集中一个项目的一种低层次特征。举例来说,如果处理的是一个灰度图像的数据集,则每个可见节点将接收一张图像中每个像素的像素值。(MNIST图像有784个像素,所以处理这类图像的神经网络的一个可见层必须有784个输入节点。) + +接着来看单个像素值x如何通过这一双层网络。在隐藏层的节点1中x与一个权重相乘,再与所谓的偏差相加。这两步运算的结果输入激活函数,得到节点的输出,即输入为x时通过节点的信号强度。 + +```markdown +激活函数f((权重w * 输入x) + 偏差b ) = 输出a +``` +

+ +

+ +一个隐藏节点如何整合多项输入。每个x分别与各自的权重相乘,乘积之和再与偏差相加,其结果同样经过激活函数运算得到节点的输出值。 +

+ +

+ +由于每个可见节点的输入都被传递至所有的隐藏节点,所以也可将RBM定义为一种对称二分图。 + +对称指每个可见节点都与所有的隐藏节点相连接(见下图)。二分指有两个部分或层,而这里的图是指代节点网络的数学名词。 + +在每个隐藏节点中,每一个输入x都会与其相对应的权重w相乘。也就是说,每个输入x会对应三个权重,因此总共有12个权重(4个输入节点 x 3个隐藏节点)。两层之间的权重始终都是一个行数等于输入节点数、列数等于输出节点数的矩阵。 + +每个隐藏节点会接收四个与对应权重相乘后的输入值。这些乘积之和与一个偏差值相加(至少能强制让一部分节点激活),其结果再经过激活运算得到每个隐藏节点的输出a。 + +

+ +

+ +如果这两个层属于一个深度神经网络,那么第一隐藏层的输出会成为第二隐藏层的输入,随后再通过任意数量的隐藏层,直至到达最终的分类层。(简单的前馈动作仅能让RBM节点实现自动编码器的功能。) + +

+ +

+ +在重构阶段,第一隐藏层的激活值成为反向传递中的输入。这些输入值与同样的权重相乘,每两个相连的节点之间各有一个权重,就像正向传递中输入x的加权运算一样。这些乘积的和再与每个可见层的偏差相加,所得结果就是重构值,亦即原始输入的近似值。这一过程表示如下: + +

+ +

+ +由于RBM权重初始值是随机决定的,重构值与原始输入之间的差别通常很大。可以将r值与输入值之差视为重构误差,此误差值随后经由反向传播来修正RBM的权重,如此不断反复,直至误差达到最小。 + +由此可见,RBM在正向传递中使用输入值来预测节点的激活值,亦即输入为加权的x时输出的概率:p(a|x; w)。 + +但在反向传递时,激活值成为输入,而输出的是对于原始数据的重构值,或者说猜测值。此时RBM则是在尝试估计激活值为a时输入为x的概率,激活值的加权系数与正向传递中的权重相同。 第二个阶段可以表示为p(x|a; w)。 + +上述两种预测值相结合,可以得到输入 x 和激活值 a 的联合概率分布,即p(x, a)。 + +重构与回归、分类运算不同。回归运算根据许多输入值估测一个连续值,分类运算是猜测应当为一个特定的输入样例添加哪种具体的标签。 + +而重构则是在猜测原始输入的概率分布,亦即同时预测许多不同的点的值。这被称为生成学习,必须和分类器所进行的判别学习区分开来,后者是将输入值映射至标签,用直线将数据点划分为不同的组。 + +试想输入数据和重构数据是形状不同的常态曲线,两者仅有部分重叠。 + +KL散度衡量两条曲线下方不重叠(即离散)的面积,而RBM的优化算法会尝试将这些离散部分的面积最小化,使共用权重在与第一隐藏层的激活值相乘后,可以得到与原始输入高度近似的结果。下图左半边是一组原始输入的概率分布曲线p,与之并列的是重构值的概率分布曲线q;右半边的图则显示了两条曲线之间的差异。 + +

+ +

+ +RBM根据权重产生的误差反复调整权重,以此学习估计原始数据的近似值。可以说权重会慢慢开始反映出输入的结构,而这种结构被编码为第一个隐藏层的激活值。整个学习过程看上去像是两条概率分布曲线在逐步重合。 + +

+ +

+ +RBM根据第一个隐藏层的激活值学习了输入数据的结构之后,数据即在网络中继续向下传递一层。第一个隐藏层的作用现在相当于可见层。激活值实际上相当于输入,在第二个隐藏层的节点中与权重相乘,得到另一组激活值。 + +将特征分组,再将特征组分组,由此连续生成多组激活值的过程是特征层次分析的基础,神经网络用这种方法来学习更为复杂且抽象的数据表达形式。 + +每增加一个隐藏层,其权重都会反复进行调整,直到该层能较为准确地模拟出来自前一层的输入。这是无监督的逐层贪婪预训练方法,不需要标签就可以改进网络的权重,也就是说可以采用未标记、未经人工处理的数据来训练,而现实中大部分的数据都属于这一类别。一般的规律是,算法接触的数据越多,产生的结果越准确,这正是深度学习算法十分厉害的原因之一。 + +权重能够近似模拟出数据的特征后,也就为下一步的学习奠定了良好基础,比如可以在随后的有监督学习阶段使用深度置信网络来对图像进行分类。 + +RBM有许多用途,其中最强的功能之一就是对权重进行合理的初始化,为之后的学习和分类做好准备。从某种意义上来说,RBM的作用与反向传播相似:让权重能够有效地模拟数据。可以认为预训练和反向传播是实现同一个目的的不同方法,二者可以相互替代。 +

+ +

+ +这幅对称二分二向图综合显示了玻尔兹曼机的运作方式。 + +#### 应用示例 +```python + +import tensorflow as tf +import numpy as np +import sys +from .util import tf_xavier_init + + +class RBM: + def __init__(self, + n_visible, + n_hidden, + learning_rate=0.01, + momentum=0.95, + xavier_const=1.0, + err_function='mse', + use_tqdm=False, + # DEPRECATED: + tqdm=None): + if not 0.0 <= momentum <= 1.0: + raise ValueError('momentum should be in range [0, 1]') + + if err_function not in {'mse', 'cosine'}: + raise ValueError('err_function should be either \'mse\' or \'cosine\'') + + self._use_tqdm = use_tqdm + self._tqdm = None + + if use_tqdm or tqdm is not None: + from tqdm import tqdm + self._tqdm = tqdm + + self.n_visible = n_visible + self.n_hidden = n_hidden + self.learning_rate = learning_rate + self.momentum = momentum + + self.x = tf.placeholder(tf.float32, [None, self.n_visible]) + self.y = tf.placeholder(tf.float32, [None, self.n_hidden]) + + self.w = tf.Variable(tf_xavier_init(self.n_visible, self.n_hidden, const=xavier_const), dtype=tf.float32) + self.visible_bias = tf.Variable(tf.zeros([self.n_visible]), dtype=tf.float32) + self.hidden_bias = tf.Variable(tf.zeros([self.n_hidden]), dtype=tf.float32) + + self.delta_w = tf.Variable(tf.zeros([self.n_visible, self.n_hidden]), dtype=tf.float32) + self.delta_visible_bias = tf.Variable(tf.zeros([self.n_visible]), dtype=tf.float32) + self.delta_hidden_bias = tf.Variable(tf.zeros([self.n_hidden]), dtype=tf.float32) + + self.update_weights = None + self.update_deltas = None + self.compute_hidden = None + self.compute_visible = None + self.compute_visible_from_hidden = None + + self._initialize_vars() + + assert self.update_weights is not None + assert self.update_deltas is not None + assert self.compute_hidden is not None + assert self.compute_visible is not None + assert self.compute_visible_from_hidden is not None + + if err_function == 'cosine': + x1_norm = tf.nn.l2_normalize(self.x, 1) + x2_norm = tf.nn.l2_normalize(self.compute_visible, 1) + cos_val = tf.reduce_mean(tf.reduce_sum(tf.mul(x1_norm, x2_norm), 1)) + self.compute_err = tf.acos(cos_val) / tf.constant(np.pi) + else: + self.compute_err = tf.reduce_mean(tf.square(self.x - self.compute_visible)) + + init = tf.global_variables_initializer() + self.sess = tf.Session() + self.sess.run(init) + + def _initialize_vars(self): + pass + + def get_err(self, batch_x): + return self.sess.run(self.compute_err, feed_dict={self.x: batch_x}) + + def get_free_energy(self): + pass + + def transform(self, batch_x): + return self.sess.run(self.compute_hidden, feed_dict={self.x: batch_x}) + + def transform_inv(self, batch_y): + return self.sess.run(self.compute_visible_from_hidden, feed_dict={self.y: batch_y}) + + def reconstruct(self, batch_x): + return self.sess.run(self.compute_visible, feed_dict={self.x: batch_x}) + + def partial_fit(self, batch_x): + self.sess.run(self.update_weights + self.update_deltas, feed_dict={self.x: batch_x}) + + def fit(self, + data_x, + n_epoches=10, + batch_size=10, + shuffle=True, + verbose=True): + assert n_epoches > 0 + + n_data = data_x.shape[0] + + if batch_size > 0: + n_batches = n_data // batch_size + (0 if n_data % batch_size == 0 else 1) + else: + n_batches = 1 + + if shuffle: + data_x_cpy = data_x.copy() + inds = np.arange(n_data) + else: + data_x_cpy = data_x + + errs = [] + + for e in range(n_epoches): + if verbose and not self._use_tqdm: + print('Epoch: {:d}'.format(e)) + + epoch_errs = np.zeros((n_batches,)) + epoch_errs_ptr = 0 + + if shuffle: + np.random.shuffle(inds) + data_x_cpy = data_x_cpy[inds] + + r_batches = range(n_batches) + + if verbose and self._use_tqdm: + r_batches = self._tqdm(r_batches, desc='Epoch: {:d}'.format(e), ascii=True, file=sys.stdout) + + for b in r_batches: + batch_x = data_x_cpy[b * batch_size:(b + 1) * batch_size] + self.partial_fit(batch_x) + batch_err = self.get_err(batch_x) + epoch_errs[epoch_errs_ptr] = batch_err + epoch_errs_ptr += 1 + + if verbose: + err_mean = epoch_errs.mean() + if self._use_tqdm: + self._tqdm.write('Train error: {:.4f}'.format(err_mean)) + self._tqdm.write('') + else: + print('Train error: {:.4f}'.format(err_mean)) + print('') + sys.stdout.flush() + + errs = np.hstack([errs, epoch_errs]) + + return errs + + def get_weights(self): + return self.sess.run(self.w),\ + self.sess.run(self.visible_bias),\ + self.sess.run(self.hidden_bias) + + def save_weights(self, filename, name): + saver = tf.train.Saver({name + '_w': self.w, + name + '_v': self.visible_bias, + name + '_h': self.hidden_bias}) + return saver.save(self.sess, filename) + + def set_weights(self, w, visible_bias, hidden_bias): + self.sess.run(self.w.assign(w)) + self.sess.run(self.visible_bias.assign(visible_bias)) + self.sess.run(self.hidden_bias.assign(hidden_bias)) + + def load_weights(self, filename, name): + saver = tf.train.Saver({name + '_w': self.w, + name + '_v': self.visible_bias, + name + '_h': self.hidden_bias}) + saver.restore(self.sess, filename) + +``` diff --git a/assets/src/ANN/ANN.0.11.md b/assets/src/ANN/ANN.0.11.md new file mode 100644 index 00000000..774fb7fb --- /dev/null +++ b/assets/src/ANN/ANN.0.11.md @@ -0,0 +1,186 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! + +机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 + +(1)监督学习:从给定的训练数据集中学习出一个函数,当新的数据输入时,可以根据函数预测相应的结果。监督学习的训练集要求是包括输入和输出,也就是特征和目标。训练集中的目标是有标注的。如今机器学习已固有的监督学习算法有可以进行分类的,例如贝叶斯分类,SVM,ID3,C4.5以及分类决策树,以及现在最火热的人工神经网络,例如BP神经网络,RBF神经网络,Hopfield神经网络、深度信念网络和卷积神经网络等。人工神经网络是模拟人大脑的思考方式来进行分析,在人工神经网络中有显层,隐层以及输出层,而每一层都会有神经元,神经元的状态或开启或关闭,这取决于大数据。同样监督机器学习算法也可以作回归,最常用便是逻辑回归。 + +(2)无监督学习:与有监督学习相比,无监督学习的训练集的类标号是未知的,并且要学习的类的个数或集合可能事先不知道。常见的无监督学习算法包括聚类和关联,例如K均值法、Apriori算法。 + +(3)半监督学习:介于监督学习和无监督学习之间,例如EM算法。 + +如今的机器学习领域主要的研究工作在三个方面进行:1)面向任务的研究,研究和分析改进一组预定任务的执行性能的学习系统;2)认知模型,研究人类学习过程并进行计算模拟;3)理论的分析,从理论的层面探索可能的算法和独立的应用领域算法。 + +#### 自组织映射(Self-Organizing Map) + +自组织映射(Self-Organizing Maps, SOM)算法作为一种聚类和高维可视化的无监督学习算法, 是通过模拟人脑对信 号处理的特点而发展起来的一种人工神经网络。该模型由芬兰赫尔辛基大学教授 Teuvo Kohonen 于 1981 年提出后,现在 已成为应用最广泛的自组织神经网络方法,其中的 WTA(Winner Takes All)竞争机制反映了自组织学习最根本的特征。 + +自组织映射它的思想很简单,本质上是一种只有输入层--隐藏层的神经网络。隐藏层中的一个节点代表一个需要聚成的类。训练时采用“竞争学习”的方式,每个输入的样例在隐藏层中找到一个和它最匹配的节点,称为它的激活节点,也叫“winning neuron”。 紧接着用随机梯度下降法更新激活节点的参数。同时,和激活节点临近的点也根据它们距离激活节点的远近而适当地更新参数。 + +所以,SOM的一个特点是,隐藏层的节点是有拓扑关系的。这个拓扑关系需要我们确定,如果想要一维的模型,那么隐藏节点依次连成一条线;如果想要二维的拓扑关系,那么就行成一个平面,如下图所示(也叫Kohonen Network): +

+ +

+ +既然隐藏层是有拓扑关系的,所以我们也可以说,SOM可以把任意维度的输入离散化到一维或者二维(更高维度的不常见)的离散空间上。 Computation layer里面的节点与Input layer的节点是全连接的。 + +拓扑关系确定后,开始计算过程,大体分成几个部分: + +1. 初始化:每个节点随机初始化自己的参数。每个节点的参数个数与Input的维度相同。 + +2. 对于每一个输入数据,找到与它最相配的节点。假设输入时D维的, 即 X={x_i, i=1,...,D},那么判别函数可以为欧几里得距离: +

+ +

+3. 找到激活节点I(x)之后,我们也希望更新和它临近的节点。令S_ij表示节点i和j之间的距离,对于I(x)临近的节点,分配给它们一个更新权重: +

+ +

+简而言之就是临近的节点根据距离的远近,更新程度要会减弱。 + +然后就是更新节点的参数了。按照梯度下降法更新: + +

+ +

+ +迭代,直到收敛。 + +与K-Means的比较 + +同样是无监督的聚类方法,自组织映射与K-Means的不同之处: + +* K-Means需要事先定下类的个数,也就是K的值。 自组织映射则不用,隐藏层中的某些节点可以没有任何输入数据属于它。所以,K-Means受初始化的影响要比较大。 + +* K-means为每个输入数据找到一个最相似的类后,只更新这个类的参数。自组织映射则会更新临近的节点。所以K-mean受noise data的影响比较大,自组织映射的准确性可能会比k-means低(因为也更新了临近节点)。 + +* 自组织映射的可视化比较好。优雅的拓扑关系图 。 + +#### 应用示例 + +```python +import numpy +from sklearn.decomposition import RandomizedPCA + + +class SOM(): + def __init__(self, x, y): + self.map = [] + self.n_neurons = x*y + self.sigma = x + self.template = numpy.arange(x*y).reshape(self.n_neurons,1) + self.alpha = 0.6 + self.alpha_final = 0.1 + self.shape = [x,y] + self.epoch = 0 + + def train(self, X, iter, batch_size=1): + if len(self.map) == 0: + x,y = self.shape + # first we initialize the map + self.map = numpy.zeros((self.n_neurons, len(X[0]))) + + # then we the pricipal components of the input data + eigen = RandomizedPCA(10).fit_transform(X.T).T + + # then we set different point on the map equal to principal components to force diversification + self.map[0] = eigen[0] + self.map[y-1] = eigen[1] + self.map[(x-1)*y] = eigen[2] + self.map[x*y - 1] = eigen[3] + for i in range(4, 10): + self.map[numpy.random.randint(1, self.n_neurons)] = eigen[i] + + self.total = iter + + # coefficient of decay for learning rate alpha + self.alpha_decay = (self.alpha_final/self.alpha)**(1.0/self.total) + + # coefficient of decay for gaussian smoothing + self.sigma_decay = (numpy.sqrt(self.shape[0])/(4*self.sigma))**(1.0/self.total) + + samples = numpy.arange(len(X)) + numpy.random.shuffle(samples) + + for i in xrange(iter): + idx = samples[i:i + batch_size] + self.iterate(X[idx]) + + def transform(self, X): + # We simply compute the dot product of the input with the transpose of the map to get the new input vectors + res = numpy.dot(numpy.exp(X),numpy.exp(self.map.T))/numpy.sum(numpy.exp(self.map), axis=1) + res = res / (numpy.exp(numpy.max(res)) + 1e-8) + return res + + def iterate(self, vector): + x, y = self.shape + + delta = self.map - vector + + # Euclidian distance of each neurons with the example + dists = numpy.sum((delta)**2, axis=1).reshape(x,y) + + # Best maching unit + idx = numpy.argmin(dists) + print "Epoch ", self.epoch, ": ", (idx/x, idx%y), "; Sigma: ", self.sigma, "; alpha: ", self.alpha + + # Linearly reducing the width of Gaussian Kernel + self.sigma = self.sigma*self.sigma_decay + dist_map = self.template.reshape(x,y) + + # Distance of each neurons in the map from the best matching neuron + dists = numpy.sqrt((dist_map/x - idx/x)**2 + (numpy.mod(dist_map,x) - idx%y)**2).reshape(self.n_neurons, 1) + #dists = self.template - idx + + # Applying Gaussian smoothing to distances of neurons from best matching neuron + h = numpy.exp(-(dists/self.sigma)**2) + + # Updating neurons in the map + self.map -= self.alpha*h*delta + + # Decreasing alpha + self.alpha = self.alpha*self.alpha_decay + + self.epoch = self.epoch + 1 + +``` + +```python + + +from PIL import Image +from tools import make_tile +import gzip +import cPickle + +def load_mnist(): + f = gzip.open("mnist/mnist.pkl.gz", 'rb') + train, valid, test = cPickle.load(f) + f.close() + return train[0][:20000],train[1][:20000] + +def demo(): + # Get data + X, y = load_mnist() + cl = SOM(20, 20) + cl.train(X, 2000) + + # Plotting hidden units + W = cl.map + W = make_tile(W, img_shape= (28,28), tile_shape=(20,20)) + img = Image.fromarray(W) + img.save("som_results.png") + + + # creating new inputs + X = cl.transform(X) + + # we can plot "landscape" 3d to view the map in 3d + landscape = cl.transform(numpy.ones((1,28**2))) + return cl.map, X, y,landscape + + +if __name__ == '__main__': + demo() + +``` diff --git a/assets/src/ANN/ANN.0.12.md b/assets/src/ANN/ANN.0.12.md new file mode 100644 index 00000000..1abed500 --- /dev/null +++ b/assets/src/ANN/ANN.0.12.md @@ -0,0 +1,98 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! + +机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 + +(1)监督学习:从给定的训练数据集中学习出一个函数,当新的数据输入时,可以根据函数预测相应的结果。监督学习的训练集要求是包括输入和输出,也就是特征和目标。训练集中的目标是有标注的。如今机器学习已固有的监督学习算法有可以进行分类的,例如贝叶斯分类,SVM,ID3,C4.5以及分类决策树,以及现在最火热的人工神经网络,例如BP神经网络,RBF神经网络,Hopfield神经网络、深度信念网络和卷积神经网络等。人工神经网络是模拟人大脑的思考方式来进行分析,在人工神经网络中有显层,隐层以及输出层,而每一层都会有神经元,神经元的状态或开启或关闭,这取决于大数据。同样监督机器学习算法也可以作回归,最常用便是逻辑回归。 + +(2)无监督学习:与有监督学习相比,无监督学习的训练集的类标号是未知的,并且要学习的类的个数或集合可能事先不知道。常见的无监督学习算法包括聚类和关联,例如K均值法、Apriori算法。 + +(3)半监督学习:介于监督学习和无监督学习之间,例如EM算法。 + +如今的机器学习领域主要的研究工作在三个方面进行:1)面向任务的研究,研究和分析改进一组预定任务的执行性能的学习系统;2)认知模型,研究人类学习过程并进行计算模拟;3)理论的分析,从理论的层面探索可能的算法和独立的应用领域算法。 + +#### 脉冲神经网络(Spiking Neural Network) +脉冲神经网络Spiking neuralnetworks (SNNs)是第三代神经网络模型,其模拟神经元更加接近实际,除此之外,把时间信息的影响也考虑其中。思路是这样的,动态神经网络中的神经元不是在每一次迭代传播中都被激活(而在典型的多层感知机网络中却是),而是在它的膜电位达到某一个特定值才被激活。当一个神经元被激活,它会产生一个信号传递给其他神经元,提高或降低其膜电位。 + +脉冲神经网络,其模拟神经元更加接近实际,除此之外,把时间信息的影响也考虑其中。思路是这样的,动态神经网络中的神经元不是在每一次迭代传播中都被激活(而在典型的多层感知机网络中却是),而是在它的膜电位达到某一个特定值才被激活。当一个神经元被激活,它会产生一个信号传递给其他神经元,提高或降低其膜电位。 +在脉冲神经网络中,神经元的当前激活水平(被建模成某种微分方程)通常被认为是当前状态,一个输入脉冲会使当前这个值升高,持续一段时间,然后逐渐衰退。出现了很多编码方式把这些输出脉冲序列解释为一个实际的数字,这些编码方式会同时考虑到脉冲频率和脉冲间隔时间。 + +借助于神经科学的研究,人们可以精确的建立基于脉冲产生时间神经网络模型。这种新型的神经网络采用脉冲编码(spike coding),通过获得脉冲发生的精确时间,这种新型的神经网络可以进行获得更多的信息和更强的计算能力。 + +Alan Lloyd Hodgkin 和 Andrew Huxley在1952年提出了第一个脉冲神经网络模型,这个模型描述了动作电位是怎样产生并传播的。但是,脉冲并不是在神经元之间直接传播的,它需要在突触间隙间交换一种叫“神经递质”的化学物质。这种生物体的复杂性和可变性导致了许多不同的神经元模型的产生。 + +从信息论的观点来看,找到一种可以解释脉冲,也就是动作电位的模型是个问题。所以,神经科学的一个基本问题就是确定神经元是否通过时间编码来交流。时间编码表明单一的神经元可以取代上百个S型隐藏层节点。 + + +这种神经网络大体上可以和传统的人工神经网络一样被用在信息处理中,而且脉冲神经网络可以对一个虚拟昆虫寻找食物的问题建模,而不需要环境的先验知识。并且,由于它更加接近现实的性能,使它可以用来学习生物神经系统的工作,电生理学的脉冲和脉冲神经网络在电脑上的模拟输出相比,确定了拓扑学和生物神经学的假说的可能性。 + +在实践中脉冲神经网络和已被证明的理论之间还存在一个主要的不同点。脉冲神经网络已被证明在神经科学系统中有作用,而在工程学中还无建树,一些大规模的神经网络已经被设计来利用脉冲神经网络中发现的脉冲编码,这些网络根据储备池计算的原则,但是现实中,大规模的脉冲神经网络计算由于所需计算资源多而产能小,发展受限,造成了只有很少的大规模脉冲神经网络被用来解决复杂的计算问题,而这些之前都是由第二代神经网络解决的。第二代神经网络模型中难以加入时间,脉冲神经网络(特别当算法定义为离散时间时)相当容易观察其动力学特征。我们很难建立一个具有稳定行为的模型来实现一个特定功能。 + +#### 应用示例 +```python +import chainer, math +import numpy as np +from chainer import cuda +from chainer import function +from chainer.utils import type_check + +class SELU(function.Function): + def __init__(self, alpha, lam): + self.alpha = float(alpha) + self.lam = float(lam) + + def check_type_forward(self, in_types): + type_check.expect(in_types.size() == 1) + x_type, = in_types + type_check.expect(x_type.dtype.kind == 'f') + + def forward_cpu(self, x): + y = x[0].copy() + neg_indices = x[0] <= 0 + y[neg_indices] = self.alpha * (np.exp(y[neg_indices]) - 1) + y *= self.lam + return y, + + def forward_gpu(self, x): + y = cuda.elementwise( + 'T x, T alpha, T lam', 'T y', + 'y = x > 0 ? (T)(lam * x) : (T)(lam * alpha * (exp(x) - 1))', + 'elu_fwd')(x[0], self.alpha, self.lam) + return y, + + def backward_cpu(self, x, gy): + gx = gy[0].copy() + neg_indices = x[0] <= 0 + gx[neg_indices] *= self.alpha * np.exp(x[0][neg_indices]) + gx *= self.lam + return gx, + + def backward_gpu(self, x, gy): + gx = cuda.elementwise( + 'T x, T gy, T alpha, T lam', 'T gx', + 'gx = x > 0 ? (T)(lam * gy) : (T)(lam * gy * alpha * exp(x))', + 'elu_bwd')( + x[0], gy[0], self.alpha, self.lam) + return gx, + + +def selu(x, alpha=1.6732632423543772848170429916717, lam=1.0507009873554804934193349852946): + return SELU(alpha, lam)(x) + +def dropout_selu(x, ratio=0.1, alpha=-1.7580993408473766): + if chainer.config.train == False: + return x + + q = 1.0 - ratio + + xp = cuda.get_array_module(*x) + if xp == np: + d = np.random.rand(*x[0].shape) >= ratio + else: + d = xp.random.rand(*x[0].shape, dtype=np.float32) >= ratio + + a = math.pow(q + alpha ** 2 * q * (1 - q), -0.5) + b = -a * (1 - q) * alpha + + return a * (x * d + alpha * (1 - d)) + b +``` diff --git a/assets/src/ANN/ANN.0.2.md b/assets/src/ANN/ANN.0.2.md new file mode 100644 index 00000000..d96220c3 --- /dev/null +++ b/assets/src/ANN/ANN.0.2.md @@ -0,0 +1,473 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! + +机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 + +(1)监督学习:从给定的训练数据集中学习出一个函数,当新的数据输入时,可以根据函数预测相应的结果。监督学习的训练集要求是包括输入和输出,也就是特征和目标。训练集中的目标是有标注的。如今机器学习已固有的监督学习算法有可以进行分类的,例如贝叶斯分类,SVM,ID3,C4.5以及分类决策树,以及现在最火热的人工神经网络,例如BP神经网络,RBF神经网络,Hopfield神经网络、深度信念网络和卷积神经网络等。人工神经网络是模拟人大脑的思考方式来进行分析,在人工神经网络中有显层,隐层以及输出层,而每一层都会有神经元,神经元的状态或开启或关闭,这取决于大数据。同样监督机器学习算法也可以作回归,最常用便是逻辑回归。 + +(2)无监督学习:与有监督学习相比,无监督学习的训练集的类标号是未知的,并且要学习的类的个数或集合可能事先不知道。常见的无监督学习算法包括聚类和关联,例如K均值法、Apriori算法。 + +(3)半监督学习:介于监督学习和无监督学习之间,例如EM算法。 + +如今的机器学习领域主要的研究工作在三个方面进行:1)面向任务的研究,研究和分析改进一组预定任务的执行性能的学习系统;2)认知模型,研究人类学习过程并进行计算模拟;3)理论的分析,从理论的层面探索可能的算法和独立的应用领域算法。 + +#### 自动编码器(Autoencoder) +自动编码器(Autoencoder)是一种无监督的学习算法,主要用于数据的降维或者特征的抽取,在深度学习中,自动编码器(Autoencoder)可用于在训练阶段开始前,确定权重矩阵的初始值。 + +神经网络中的权重矩阵可看作是对输入的数据进行特征转换,即先将数据编码为另一种形式,然后在此基础上进行一系列学习。然而,在对权重初始化时,我们并不知道初始的权重值在训练时会起到怎样的作用,也不知道在训练过程中权重会怎样的变化。因此一种较好的思路是,利用初始化生成的权重矩阵进行编码时,我们希望编码后的数据能够较好的保留原始数据的主要特征。那么,如何衡量码后的数据是否保留了较完整的信息呢?答案是:如果编码后的数据能够较为容易地通过解码恢复成原始数据,我们则认为较好的保留了数据信息。 + +自动编码器(Autoencoder)中:原始input(设为x)经过加权(W、b)、映射(Sigmoid)之后得到y,再对y反向加权映射回来成为z。 + +通过反复迭代训练两组(W、b),使得误差函数最小,即尽可能保证z近似于x,即完美重构了x。 + +那么可以说正向第一组权(W、b)是成功的,很好的学习了input中的关键特征,不然也不会重构得如此完美. +

+ +

+ +这个过程很有趣,首先,它没有使用数据标签来计算误差update参数,所以是无监督学习。 + +其次,利用类似神经网络的双隐层的方式,简单粗暴地提取了样本的特征。 + +这个双隐层是有争议的,最初的编码器确实使用了两组(W,b),但是Vincent在2010年的论文中做了研究,发现只要单组W就可以了。 + +即W'=W^T, W和W'称为Tied Weights。实验证明,W'真的只是在打酱油,完全没有必要去做训练。 + +逆向重构矩阵让人想起了逆矩阵,若W^-1=W^T的话,W就是个正交矩阵了,即W是可以训成近似正交阵的。 + +由于W'就是个酱油,训练完之后就没它事了。正向传播用W即可,相当于为input预先编个码,再导入到下一layer去。所以叫自动编码器,而不叫自动编码解码器。 + +自动编码器相当于创建了一个隐层,一个简单想法就是加在深度网络的开头,作为原始信号的初级filter,起到降维、提取特征的效果。 +当然,这种做法就有一个问题,AutoEncoder可以看作是PCA的非线性补丁加强版,PCA的取得的效果是建立在降维基础上的。 + +仔细想想CNN这种结构,随着layer的推进,每层的神经元个数在递增,如果用了AutoEncoder去预训练,岂不是增维了?真的没问题? + +相关论文中给出的实验结果认为AutoEncoder的增维效果还不赖,原因可能是非线性网络能力很强,尽管神经元个数增多,但是每个神经元的效果在衰减。 + +同时,随机梯度算法给了后续监督学习一个良好的开端。整体上,增维是利大于弊的。 + +#### 应用示例 +```python +from __future__ import division + +import tensorflow as tf +import numpy as np +import logging +import json +import os + + +class TextAutoencoder(object): + """ + Class that encapsulates the encoder-decoder architecture to + reconstruct pieces of text. + """ + + def __init__(self, lstm_units, embeddings, go, train=True, + train_embeddings=False, bidirectional=True): + """ + Initialize the encoder/decoder and creates Tensor objects + :param lstm_units: number of LSTM units + :param embeddings: numpy array with initial embeddings + :param go: index of the GO symbol in the embedding matrix + :param train_embeddings: whether to adjust embeddings during training + :param bidirectional: whether to create a bidirectional autoencoder + (if False, a simple linear LSTM is used) + """ + # EOS and GO share the same symbol. Only GO needs to be embedded, and + # only EOS exists as a possible network output + self.go = go + self.eos = go + + self.bidirectional = bidirectional + self.vocab_size = embeddings.shape[0] + self.embedding_size = embeddings.shape[1] + self.global_step = tf.Variable(0, name='global_step', trainable=False) + + # the sentence is the object to be memorized + self.sentence = tf.placeholder(tf.int32, [None, None], 'sentence') + self.sentence_size = tf.placeholder(tf.int32, [None], + 'sentence_size') + self.l2_constant = tf.placeholder(tf.float32, name='l2_constant') + self.clip_value = tf.placeholder(tf.float32, name='clip') + self.learning_rate = tf.placeholder(tf.float32, name='learning_rate') + self.dropout_keep = tf.placeholder(tf.float32, name='dropout_keep') + + self.decoder_step_input = tf.placeholder(tf.int32, + [None], + 'prediction_step') + + name = 'decoder_fw_step_state_c' + self.decoder_fw_step_c = tf.placeholder(tf.float32, + [None, lstm_units], name) + name = 'decoder_fw_step_state_h' + self.decoder_fw_step_h = tf.placeholder(tf.float32, + [None, lstm_units], name) + self.decoder_bw_step_c = tf.placeholder(tf.float32, + [None, lstm_units], + 'decoder_bw_step_state_c') + self.decoder_bw_step_h = tf.placeholder(tf.float32, + [None, lstm_units], + 'decoder_bw_step_state_h') + + with tf.variable_scope('autoencoder') as self.scope: + self.embeddings = tf.Variable(embeddings, name='embeddings', + trainable=train_embeddings) + + initializer = tf.glorot_normal_initializer() + self.lstm_fw = tf.nn.rnn_cell.LSTMCell(lstm_units, + initializer=initializer) + self.lstm_bw = tf.nn.rnn_cell.LSTMCell(lstm_units, + initializer=initializer) + + embedded = tf.nn.embedding_lookup(self.embeddings, self.sentence) + embedded = tf.nn.dropout(embedded, self.dropout_keep) + + # encoding step + if bidirectional: + bdr = tf.nn.bidirectional_dynamic_rnn + ret = bdr(self.lstm_fw, self.lstm_bw, + embedded, dtype=tf.float32, + sequence_length=self.sentence_size, + scope=self.scope) + else: + ret = tf.nn.dynamic_rnn(self.lstm_fw, embedded, + dtype=tf.float32, + sequence_length=self.sentence_size, + scope=self.scope) + _, self.encoded_state = ret + if bidirectional: + encoded_state_fw, encoded_state_bw = self.encoded_state + + # set the scope name used inside the decoder. + # maybe there's a more elegant way to do it? + fw_scope_name = self.scope.name + '/fw' + bw_scope_name = self.scope.name + '/bw' + else: + encoded_state_fw = self.encoded_state + fw_scope_name = self.scope + + self.scope.reuse_variables() + + # generate a batch of embedded GO + # sentence_size has the batch dimension + go_batch = self._generate_batch_go(self.sentence_size) + embedded_eos = tf.nn.embedding_lookup(self.embeddings, + go_batch) + embedded_eos = tf.reshape(embedded_eos, + [-1, 1, self.embedding_size]) + decoder_input = tf.concat([embedded_eos, embedded], axis=1) + + # decoding step + + # We give the same inputs to the forward and backward LSTMs, + # but each one has its own hidden state + # their outputs are concatenated and fed to the softmax layer + if bidirectional: + outputs, _ = tf.nn.bidirectional_dynamic_rnn( + self.lstm_fw, self.lstm_bw, decoder_input, + self.sentence_size, encoded_state_fw, encoded_state_bw) + + # concat fw and bw outputs + outputs = tf.concat(outputs, -1) + else: + outputs, _ = tf.nn.dynamic_rnn( + self.lstm_fw, decoder_input, self.sentence_size, + encoded_state_fw) + + self.decoder_outputs = outputs + + # now project the outputs to the vocabulary + with tf.variable_scope('projection') as self.projection_scope: + # decoder_outputs has shape (batch, max_sentence_size, vocab_size) + self.logits = tf.layers.dense(outputs, self.vocab_size) + + # tensors for running a model + embedded_step = tf.nn.embedding_lookup(self.embeddings, + self.decoder_step_input) + state_fw = tf.nn.rnn_cell.LSTMStateTuple(self.decoder_fw_step_c, + self.decoder_fw_step_h) + state_bw = tf.nn.rnn_cell.LSTMStateTuple(self.decoder_bw_step_c, + self.decoder_bw_step_h) + with tf.variable_scope(fw_scope_name, reuse=True): + ret_fw = self.lstm_fw(embedded_step, state_fw) + step_output_fw, self.decoder_fw_step_state = ret_fw + + if bidirectional: + with tf.variable_scope(bw_scope_name, reuse=True): + ret_bw = self.lstm_bw(embedded_step, state_bw) + step_output_bw, self.decoder_bw_step_state = ret_bw + step_output = tf.concat(axis=1, values=[step_output_fw, + step_output_bw]) + else: + step_output = step_output_fw + + with tf.variable_scope(self.projection_scope, reuse=True): + self.projected_step_output = tf.layers.dense(step_output, + self.vocab_size) + + if train: + self._create_training_tensors() + + def _create_training_tensors(self): + """ + Create member variables related to training. + """ + eos_batch = self._generate_batch_go(self.sentence_size) + eos_batch = tf.reshape(eos_batch, [-1, 1]) + decoder_labels = tf.concat([self.sentence, eos_batch], -1) + + projection_vars = tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES, + scope=self.projection_scope.name) + # a bit ugly, maybe we should improve this? + projection_w = [var for var in projection_vars + if 'kernel' in var.name][0] + projection_b = [var for var in projection_vars + if 'bias' in var.name][0] + + # set the importance of each time step + # 1 if before sentence end or EOS itself; 0 otherwise + max_len = tf.shape(self.sentence)[1] + mask = tf.sequence_mask(self.sentence_size + 1, max_len + 1, tf.float32) + num_actual_labels = tf.reduce_sum(mask) + projection_w_t = tf.transpose(projection_w) + + # reshape to have batch and time steps in the same dimension + decoder_outputs2d = tf.reshape(self.decoder_outputs, + [-1, tf.shape(self.decoder_outputs)[-1]]) + labels = tf.reshape(decoder_labels, [-1, 1]) + sampled_loss = tf.nn.sampled_softmax_loss( + projection_w_t, projection_b, labels, decoder_outputs2d, 100, + self.vocab_size) + + masked_loss = tf.reshape(mask, [-1]) * sampled_loss + self.loss = tf.reduce_sum(masked_loss) / num_actual_labels + + optimizer = tf.train.AdamOptimizer(self.learning_rate) + gradients, v = zip(*optimizer.compute_gradients(self.loss)) + gradients, _ = tf.clip_by_global_norm(gradients, self.clip_value) + + self.train_op = optimizer.apply_gradients(zip(gradients, v), + global_step=self.global_step) + + def get_trainable_variables(self): + """ + Return all trainable variables inside the model + """ + return tf.get_collection(tf.GraphKeys.TRAINABLE_VARIABLES) + + def train(self, session, save_path, train_data, valid_data, + batch_size, epochs, learning_rate, dropout_keep, + clip_value, report_interval): + """ + Train the model + :param session: tensorflow session + :param train_data: Dataset object with training data + :param valid_data: Dataset object with validation data + :param batch_size: batch size + :param learning_rate: initial learning rate + :param dropout_keep: the probability that each LSTM input/output is kept + :param epochs: how many epochs to train for + :param clip_value: value to clip tensor norm during training + :param save_path: folder to save the model + :param report_interval: report after that many batches + """ + saver = tf.train.Saver(self.get_trainable_variables(), + max_to_keep=1) + + best_loss = 10000 + accumulated_loss = 0 + batch_counter = 0 + num_sents = 0 + + # get all data at once. we need all matrices with the same size, + # or else they don't fit the placeholders + # train_sents, train_sizes = train_data.join_all(self.go, + # self.num_time_steps, + # shuffle=True) + + # del train_data # save memory... + valid_sents, valid_sizes = valid_data.join_all(self.go, + shuffle=True) + train_data.reset_epoch_counter() + feeds = {self.clip_value: clip_value, + self.dropout_keep: dropout_keep, + self.learning_rate: learning_rate} + + while train_data.epoch_counter < epochs: + batch_counter += 1 + train_sents, train_sizes = train_data.next_batch(batch_size) + feeds[self.sentence] = train_sents + feeds[self.sentence_size] = train_sizes + + _, loss = session.run([self.train_op, self.loss], feeds) + + # multiply by len because some batches may be smaller + # (due to bucketing), then take the average + accumulated_loss += loss * len(train_sents) + num_sents += len(train_sents) + + if batch_counter % report_interval == 0: + avg_loss = accumulated_loss / num_sents + accumulated_loss = 0 + num_sents = 0 + + # we can't use all the validation at once, since it would + # take too much memory. running many small batches would + # instead take too much time. So let's just sample it. + sample_indices = np.random.randint(0, len(valid_data), + 5000) + validation_feeds = { + self.sentence: valid_sents[sample_indices], + self.sentence_size: valid_sizes[sample_indices], + self.dropout_keep: 1} + + loss = session.run(self.loss, validation_feeds) + msg = '%d epochs, %d batches\t' % (train_data.epoch_counter, + batch_counter) + msg += 'Avg batch loss: %f\t' % avg_loss + msg += 'Validation loss: %f' % loss + if loss < best_loss: + best_loss = loss + self.save(saver, session, save_path) + msg += '\t(saved model)' + + logging.info(msg) + + def save(self, saver, session, directory): + """ + Save the autoencoder model and metadata to the specified + directory. + """ + model_path = os.path.join(directory, 'model') + saver.save(session, model_path) + metadata = {'vocab_size': self.vocab_size, + 'embedding_size': self.embedding_size, + 'num_units': self.lstm_fw.output_size, + 'go': self.go, + 'bidirectional': self.bidirectional + } + metadata_path = os.path.join(directory, 'metadata.json') + with open(metadata_path, 'wb') as f: + json.dump(metadata, f) + + @classmethod + def load(cls, directory, session, train=False): + """ + Load an instance of this class from a previously saved one. + :param directory: directory with the model files + :param session: tensorflow session + :param train: if True, also create training tensors + :return: a TextAutoencoder instance + """ + model_path = os.path.join(directory, 'model') + metadata_path = os.path.join(directory, 'metadata.json') + with open(metadata_path, 'rb') as f: + metadata = json.load(f) + dummy_embeddings = np.empty((metadata['vocab_size'], + metadata['embedding_size'],), + dtype=np.float32) + + ae = TextAutoencoder(metadata['num_units'], dummy_embeddings, + metadata['go'], train=train, + bidirectional=metadata['bidirectional']) + vars_to_load = ae.get_trainable_variables() + if not train: + # if not flagged for training, the embeddings won't be in + # the list + vars_to_load.append(ae.embeddings) + + saver = tf.train.Saver(vars_to_load) + saver.restore(session, model_path) + return ae + + def encode(self, session, inputs, sizes): + """ + Run the encoder to obtain the encoded hidden state + :param session: tensorflow session + :param inputs: 2-d array with the word indices + :param sizes: 1-d array with size of each sentence + :return: a 2-d numpy array with the hidden state + """ + feeds = {self.sentence: inputs, + self.sentence_size: sizes, + self.dropout_keep: 1} + state = session.run(self.encoded_state, feeds) + if self.bidirectional: + state_fw, state_bw = state + return np.hstack((state_fw.c, state_bw.c)) + return state.c + + def run(self, session, inputs, sizes): + """ + Run the autoencoder with the given data + :param session: tensorflow session + :param inputs: 2-d array with the word indices + :param sizes: 1-d array with size of each sentence + :return: a 2-d array (batch, output_length) with the answer + produced by the autoencoder. The output length is not + fixed; it stops after producing EOS for all items in the + batch or reaching two times the maximum number of time + steps in the inputs. + """ + feeds = {self.sentence: inputs, + self.sentence_size: sizes, + self.dropout_keep: 1} + state = session.run(self.encoded_state, feeds) + if self.bidirectional: + state_fw, state_bw = state + else: + state_fw = state + + time_steps = 0 + max_time_steps = 2 * len(inputs[0]) + answer = [] + input_symbol = self.go * np.ones_like(sizes, dtype=np.int32) + + # this array control which sequences have already been finished by the + # decoder, i.e., for which ones it already produced the END symbol + sequences_done = np.zeros_like(sizes, dtype=np.bool) + + while True: + # we could use tensorflow's rnn_decoder, but this gives us + # finer control + + feeds = {self.decoder_fw_step_c: state_fw.c, + self.decoder_fw_step_h: state_fw.h, + self.decoder_step_input: input_symbol, + self.dropout_keep: 1} + if self.bidirectional: + feeds[self.decoder_bw_step_c] = state_bw.c + feeds[self.decoder_bw_step_h] = state_bw.h + + ops = [self.projected_step_output, + self.decoder_fw_step_state, + self.decoder_bw_step_state] + outputs, state_fw, state_bw = session.run(ops, feeds) + else: + ops = [self.projected_step_output, + self.decoder_fw_step_state] + outputs, state_fw = session.run(ops, feeds) + + input_symbol = outputs.argmax(1) + answer.append(input_symbol) + + # use an "additive" or in order to avoid infinite loops + sequences_done |= (input_symbol == self.eos) + + if sequences_done.all() or time_steps > max_time_steps: + break + else: + time_steps += 1 + + return np.hstack(answer) + + def _generate_batch_go(self, like): + """ + Generate a 1-d tensor with copies of EOS as big as the batch size, + :param like: a tensor whose shape the returned embeddings should match + :return: a tensor with shape as `like` + """ + ones = tf.ones_like(like) + return ones * self.go +``` diff --git a/assets/src/ANN/ANN.0.3.md b/assets/src/ANN/ANN.0.3.md new file mode 100644 index 00000000..e4ec1e9c --- /dev/null +++ b/assets/src/ANN/ANN.0.3.md @@ -0,0 +1,341 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! + +机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 + +(1)监督学习:从给定的训练数据集中学习出一个函数,当新的数据输入时,可以根据函数预测相应的结果。监督学习的训练集要求是包括输入和输出,也就是特征和目标。训练集中的目标是有标注的。如今机器学习已固有的监督学习算法有可以进行分类的,例如贝叶斯分类,SVM,ID3,C4.5以及分类决策树,以及现在最火热的人工神经网络,例如BP神经网络,RBF神经网络,Hopfield神经网络、深度信念网络和卷积神经网络等。人工神经网络是模拟人大脑的思考方式来进行分析,在人工神经网络中有显层,隐层以及输出层,而每一层都会有神经元,神经元的状态或开启或关闭,这取决于大数据。同样监督机器学习算法也可以作回归,最常用便是逻辑回归。 + +(2)无监督学习:与有监督学习相比,无监督学习的训练集的类标号是未知的,并且要学习的类的个数或集合可能事先不知道。常见的无监督学习算法包括聚类和关联,例如K均值法、Apriori算法。 + +(3)半监督学习:介于监督学习和无监督学习之间,例如EM算法。 + +如今的机器学习领域主要的研究工作在三个方面进行:1)面向任务的研究,研究和分析改进一组预定任务的执行性能的学习系统;2)认知模型,研究人类学习过程并进行计算模拟;3)理论的分析,从理论的层面探索可能的算法和独立的应用领域算法。 + +#### 反向传播(Backpropagation) +反向传播(Backpropagation,缩写为BP)是“误差反向传播”的简称,是一种与最优化方法(如梯度下降法)结合使用的,用来训练人工神经网络的常见方法。该方法对网络中所有权重计算损失函数(Loss Function)的梯度。这个梯度会反馈给最优化方法,用来更新权值以最小化损失函数。 +反向传播要求有对每个输入值想得到的已知输出,来计算损失函数梯度。因此,它通常被认为是一种监督式学习方法,虽然它也用在一些无监督网络(如自动编码器Autoencoder)中。它是多层前馈网络的Delta规则(Delta Rule)的推广,可以用链式法则对每层迭代计算梯度。反向传播要求人工神经元(Artificial Neuron)(或“节点”)的激励函数可微。 + +反向传播模型,是一种用于前向多层的反向传播学习算法。之所以称它是一种学习方法,是因为用它可以对组成前向多层网络的各人工神经元之间的连接权值进行不断的修改,从而使该前向多层网络能够将输入它的信息变换成所期望的输出信息。之所以将其称作为反向学习算法,是因为在修改各人工神经元的连接权值时,所依据的是该网络的实际输出与其期望的输出之差,将这一差值反向一层一层的向回传播,来决定连接权值的修改。 + +B-P算法的网络结构是一个前向多层网络,其基本思想是,学习过程由信号的正向传播与误差的反向传播两个过程组成。正向传播时,输入样本从输入层传入,经隐含层逐层处理后,传向输出层。若输出层的实际输出与期望输出不符,则转向误差的反向传播阶段。误差的反向传播是将输出误差以某种形式通过隐层向输入层逐层反传,并将误差分摊给各层的所有单元,从而获得各层单元的误差信号,此误差信号即作为修正各单元权值的依据。这种信号正向传播与误差反向传播的各层权值调整过程,是周而复始地进行。权值不断调整过程,也就是网络的学习训练过程。此过程一直进行到网络输出的误差减少到可以接受的程度,或进行到预先设定的学习次数为止。 + +BP网络的拓扑结构包括输入层、隐层和输出层,它能够在事先不知道输入输出具体数学表达式的情况下,通过学习来存储这种复杂的映射关系.其网络中参数的学习通常采用反向传播的策略,借助最速梯度信息来寻找使网络误差最小化的参数组合.常见的3层BP网络模型如图所示 + +

+ +

+ +任何监督式学习算法的目标是找到一个能把一组输入最好地映射到其正确的输出的函数。例如一个简单的分类任务,其中输入是动物的图像,正确的输出将是动物的名称。一些输入和输出模式可以很容易地通过单层神经网络(如感知器)学习。但是这些单层的感知机不能学习一些比较简单的模式,例如那些非线性可分的模式。例如,人可以通过识别动物的图像的某些特征进行分类,例如肢的数目,皮肤的纹理(无论是毛皮,羽毛,鳞片等),该动物的体型,以及种种其他特征。但是,单层神经网络必须仅仅使用图像中的像素的强度来学习一个输出一个标签函数。因为它被限制为仅具有一个层,所以没有办法从输入中学习到任何抽象特征。多层的网络克服了这一限制,因为它可以创建内部表示,并在每一层学习不同的特征。第一层可能负责从图像的单个像素的输入学习线条的走向。第二层可能就会结合第一层所学并学习识别简单形状(如圆形)。每升高一层就学习越来越多的抽象特征,如上文提到的用来图像分类。每一层都是从它下方的层中找到模式,就是这种能力创建了独立于为多层网络提供能量的外界输入的内部表达形式。 反向传播算法的发展的目标和动机是找到一种训练的多层神经网络的方法,于是它可以学习合适的内部表达来让它学习任意的输入到输出的映射。 + + +#### 反向传播算法(BP算法)主要由两个阶段:激励传播与权重更新. + +* 第1阶段:激励传播 + +每次迭代中的传播环节包含两步: +* 1.(前向传播阶段)将训练输入送入网络以获得激励响应; +* 2.(反向传播阶段)将激励响应同训练输入对应的目标输出求差,从而获得隐层和输出层的响应误差。 + +* 第2阶段:权重更新 + +对于每个突触上的权重,按照以下步骤进行更新: + +* 1.将输入激励和响应误差相乘,从而获得权重的梯度; +* 2.将这个梯度乘上一个比例并取反后加到权重上。 +这个比例(百分比)将会影响到训练过程的速度和效果,因此称为“训练因子”。梯度的方向指明了误差扩大的方向,因此在更新权重的时候需要对其取反,从而减小权重引起的误差。 + +第1和第2阶段可以反复循环迭代,直到网络的对输入的响应达到满意的预定的目标范围为止。 + +三层网络算法(只有一个隐藏层): + +* 输入x:计算输入层相应的激活函数值。 +* 正向传播:对每个计算。 +* 输出误差 :计算向量。 +* 将误差反向传播:对每个, 计算 +* 输出:代价函数的梯度为 + +这个算法的名称意味着误差会从输出结点反向传播到输入结点。严格地讲,反向传播算法对网络的可修改权值计算了网络误差的梯度。[2] 这个梯度会在简单随机梯度下降法中经常用来求最小化误差的权重。通常“反向传播”这个词使用更一般的含义,用来指涵盖了计算梯度以及在随机梯度下降法中使用的整个过程。在适用反向传播算法的网络中,它通常可以快速收敛到令人满意的极小值。 +BP网络都是多层感知机(通常都会有一个输入层、一个隐藏层及一个输出层)。为了使隐藏层能够适合所有有用的函数,多层网络必须具有用于多个层的非线性激活函数:仅用线性激活函数的多层网络会与相当于单层线性网络。常用的非线性激活函数有逻辑函数、柔性最大函数和高斯函数。 +用反向传播算法求梯度已被重新发现多次,是更加一般的自动微分技术在反向积累模式的特例。 +它也与高斯-牛顿算法密切相关,也是继续研究神经反向传播的一部分。 + +

+ +

+ +由于反向传播使用梯度下降法,需要计算平方误差函数对网络权重的导数。假设对于一个输出神经元,平方误差函数为: +

+ +

+其中E 为平方误差,t 为训练样本的目标输出,y 为输出神经元的实际输出。 + +加入系数是为了抵消微分出来的指数。之后,该表达式会乘以一个任意的学习速率,因此在这里乘上一个常系数是没有关系的。 对每个神经元j,它的输出 定义为 +

+ +

+ +通向一个神经元的输入 是之前神经元的输出 的加权和。若该神经元输出层后的第一层,输入层的输出 就是网络的输入。该神经元的输入数量是n。变表示神经元i 与j 之间的权重。 + +激活函数一般是非线性可微函数。常用作激活函数的是逻辑函数: +

+ +

+ +其导数的形式很好: +

+ +

+ +#### 求误差的导数 + +计算误差对权重的偏导数是两次使用链式法则得到的: +

+ +

+ +在右边的最后一项中,只有加权和取决于,因此: + +

+ +

+ +神经元j 的输出对其输入的导数就是激活函数的偏导数(这里假定使用逻辑函数): + +

+ +

+ +这就是为什么反向传播需要的激活函数是可微的。 +如果神经元在输出层中,因为此时以及 +

+ +

+所以第一项可以直接算出。 + +但如果j 是网络中任一内层,求E关于的导数就不太简单了。 + +考虑E为接受来自神经元j的输入的所有神经元的输入的函数, +

+ +

+ +并关于取全微分,可以得到该导数的一个递归表达式: +

+ +

+因此,若已知所有关于下一层(更接近输出神经元的一层)的输出的导数,则可以计算的导数。 + +把它们放在一起: +

+ +

+ +其中: +

+ +

+ +要使用梯度下降法更新,必须选择一个学习速率a。要加在原本的权重上的权重的变化,等于学习速率与梯度的乘积,乘以-1: +

+ +

+ +之所以要乘以-1 是因为要更新误差函数极小值而不是极大值的方向。对于单层网络,这个表达式变为Delta规则。 + +#### 应用示例 +```python + +import random +import math + +# 参数解释: +# "pd_" :偏导的前缀 +# "d_" :导数的前缀 +# "w_ho" :隐含层到输出层的权重系数索引 +# "w_ih" :输入层到隐含层的权重系数的索引 + +class NeuralNetwork: + LEARNING_RATE = 0.5 + + def __init__(self, num_inputs, num_hidden, num_outputs, hidden_layer_weights = None, hidden_layer_bias = None, output_layer_weights = None, output_layer_bias = None): + self.num_inputs = num_inputs + + self.hidden_layer = NeuronLayer(num_hidden, hidden_layer_bias) + self.output_layer = NeuronLayer(num_outputs, output_layer_bias) + + self.init_weights_from_inputs_to_hidden_layer_neurons(hidden_layer_weights) + self.init_weights_from_hidden_layer_neurons_to_output_layer_neurons(output_layer_weights) + + def init_weights_from_inputs_to_hidden_layer_neurons(self, hidden_layer_weights): + weight_num = 0 + for h in range(len(self.hidden_layer.neurons)): + for i in range(self.num_inputs): + if not hidden_layer_weights: + self.hidden_layer.neurons[h].weights.append(random.random()) + else: + self.hidden_layer.neurons[h].weights.append(hidden_layer_weights[weight_num]) + weight_num += 1 + + def init_weights_from_hidden_layer_neurons_to_output_layer_neurons(self, output_layer_weights): + weight_num = 0 + for o in range(len(self.output_layer.neurons)): + for h in range(len(self.hidden_layer.neurons)): + if not output_layer_weights: + self.output_layer.neurons[o].weights.append(random.random()) + else: + self.output_layer.neurons[o].weights.append(output_layer_weights[weight_num]) + weight_num += 1 + + def inspect(self): + print('------') + print('* Inputs: {}'.format(self.num_inputs)) + print('------') + print('Hidden Layer') + self.hidden_layer.inspect() + print('------') + print('* Output Layer') + self.output_layer.inspect() + print('------') + + def feed_forward(self, inputs): + hidden_layer_outputs = self.hidden_layer.feed_forward(inputs) + return self.output_layer.feed_forward(hidden_layer_outputs) + + def train(self, training_inputs, training_outputs): + self.feed_forward(training_inputs) + + # 1. 输出神经元的值 + pd_errors_wrt_output_neuron_total_net_input = [0] * len(self.output_layer.neurons) + for o in range(len(self.output_layer.neurons)): + + # ∂E/∂zⱼ + pd_errors_wrt_output_neuron_total_net_input[o] = self.output_layer.neurons[o].calculate_pd_error_wrt_total_net_input(training_outputs[o]) + + # 2. 隐含层神经元的值 + pd_errors_wrt_hidden_neuron_total_net_input = [0] * len(self.hidden_layer.neurons) + for h in range(len(self.hidden_layer.neurons)): + + # dE/dyⱼ = Σ ∂E/∂zⱼ * ∂z/∂yⱼ = Σ ∂E/∂zⱼ * wᵢⱼ + d_error_wrt_hidden_neuron_output = 0 + for o in range(len(self.output_layer.neurons)): + d_error_wrt_hidden_neuron_output += pd_errors_wrt_output_neuron_total_net_input[o] * self.output_layer.neurons[o].weights[h] + + # ∂E/∂zⱼ = dE/dyⱼ * ∂zⱼ/∂ + pd_errors_wrt_hidden_neuron_total_net_input[h] = d_error_wrt_hidden_neuron_output * self.hidden_layer.neurons[h].calculate_pd_total_net_input_wrt_input() + + # 3. 更新输出层权重系数 + for o in range(len(self.output_layer.neurons)): + for w_ho in range(len(self.output_layer.neurons[o].weights)): + + # ∂Eⱼ/∂wᵢⱼ = ∂E/∂zⱼ * ∂zⱼ/∂wᵢⱼ + pd_error_wrt_weight = pd_errors_wrt_output_neuron_total_net_input[o] * self.output_layer.neurons[o].calculate_pd_total_net_input_wrt_weight(w_ho) + + # Δw = α * ∂Eⱼ/∂wᵢ + self.output_layer.neurons[o].weights[w_ho] -= self.LEARNING_RATE * pd_error_wrt_weight + + # 4. 更新隐含层的权重系数 + for h in range(len(self.hidden_layer.neurons)): + for w_ih in range(len(self.hidden_layer.neurons[h].weights)): + + # ∂Eⱼ/∂wᵢ = ∂E/∂zⱼ * ∂zⱼ/∂wᵢ + pd_error_wrt_weight = pd_errors_wrt_hidden_neuron_total_net_input[h] * self.hidden_layer.neurons[h].calculate_pd_total_net_input_wrt_weight(w_ih) + + # Δw = α * ∂Eⱼ/∂wᵢ + self.hidden_layer.neurons[h].weights[w_ih] -= self.LEARNING_RATE * pd_error_wrt_weight + + def calculate_total_error(self, training_sets): + total_error = 0 + for t in range(len(training_sets)): + training_inputs, training_outputs = training_sets[t] + self.feed_forward(training_inputs) + for o in range(len(training_outputs)): + total_error += self.output_layer.neurons[o].calculate_error(training_outputs[o]) + return total_error + +class NeuronLayer: + def __init__(self, num_neurons, bias): + + # 同一层的神经元共享一个截距项b + self.bias = bias if bias else random.random() + self.neurons = [] + for i in range(num_neurons): + self.neurons.append(Neuron(self.bias)) + + def inspect(self): + print('Neurons:', len(self.neurons)) + for n in range(len(self.neurons)): + print(' Neuron', n) + for w in range(len(self.neurons[n].weights)): + print(' Weight:', self.neurons[n].weights[w]) + print(' Bias:', self.bias) + + def feed_forward(self, inputs): + outputs = [] + for neuron in self.neurons: + outputs.append(neuron.calculate_output(inputs)) + return outputs + + def get_outputs(self): + outputs = [] + for neuron in self.neurons: + outputs.append(neuron.output) + return outputs + +class Neuron: + def __init__(self, bias): + self.bias = bias + self.weights = [] + + def calculate_output(self, inputs): + self.inputs = inputs + self.output = self.squash(self.calculate_total_net_input()) + return self.output + + def calculate_total_net_input(self): + total = 0 + for i in range(len(self.inputs)): + total += self.inputs[i] * self.weights[i] + return total + self.bias + + # 激活函数sigmoid + def squash(self, total_net_input): + return 1 / (1 + math.exp(-total_net_input)) + + def calculate_pd_error_wrt_total_net_input(self, target_output): + return self.calculate_pd_error_wrt_output(target_output) * self.calculate_pd_total_net_input_wrt_input(); + + # 每一个神经元的误差是由平方差公式计算的 + def calculate_error(self, target_output): + return 0.5 * (target_output - self.output) ** 2 + + def calculate_pd_error_wrt_output(self, target_output): + return -(target_output - self.output) + + def calculate_pd_total_net_input_wrt_input(self): + return self.output * (1 - self.output) + + def calculate_pd_total_net_input_wrt_weight(self, index): + return self.inputs[index] +# 示例: + +nn = NeuralNetwork(2, 2, 2, hidden_layer_weights=[0.15, 0.2, 0.25, 0.3], hidden_layer_bias=0.35, output_layer_weights=[0.4, 0.45, 0.5, 0.55], output_layer_bias=0.6) +for i in range(10000): + nn.train([0.05, 0.1], [0.01, 0.09]) + print(i, round(nn.calculate_total_error([[[0.05, 0.1], [0.01, 0.09]]]), 9)) + + +#另外一个例子,可以把上面的例子注释掉再运行一下: + +# training_sets = [ +# [[0, 0], [0]], +# [[0, 1], [1]], +# [[1, 0], [1]], +# [[1, 1], [0]] +# ] + +# nn = NeuralNetwork(len(training_sets[0][0]), 5, len(training_sets[0][1])) +# for i in range(10000): +# training_inputs, training_outputs = random.choice(training_sets) +# nn.train(training_inputs, training_outputs) +# print(i, nn.calculate_total_error(training_sets)) +``` diff --git a/assets/src/ANN/ANN.0.4.md b/assets/src/ANN/ANN.0.4.md new file mode 100644 index 00000000..74d0df6d --- /dev/null +++ b/assets/src/ANN/ANN.0.4.md @@ -0,0 +1,300 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! + +机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 + +(1)监督学习:从给定的训练数据集中学习出一个函数,当新的数据输入时,可以根据函数预测相应的结果。监督学习的训练集要求是包括输入和输出,也就是特征和目标。训练集中的目标是有标注的。如今机器学习已固有的监督学习算法有可以进行分类的,例如贝叶斯分类,SVM,ID3,C4.5以及分类决策树,以及现在最火热的人工神经网络,例如BP神经网络,RBF神经网络,Hopfield神经网络、深度信念网络和卷积神经网络等。人工神经网络是模拟人大脑的思考方式来进行分析,在人工神经网络中有显层,隐层以及输出层,而每一层都会有神经元,神经元的状态或开启或关闭,这取决于大数据。同样监督机器学习算法也可以作回归,最常用便是逻辑回归。 + +(2)无监督学习:与有监督学习相比,无监督学习的训练集的类标号是未知的,并且要学习的类的个数或集合可能事先不知道。常见的无监督学习算法包括聚类和关联,例如K均值法、Apriori算法。 + +(3)半监督学习:介于监督学习和无监督学习之间,例如EM算法。 + +如今的机器学习领域主要的研究工作在三个方面进行:1)面向任务的研究,研究和分析改进一组预定任务的执行性能的学习系统;2)认知模型,研究人类学习过程并进行计算模拟;3)理论的分析,从理论的层面探索可能的算法和独立的应用领域算法。 + + +#### 递归神经网络(Recurrent Neural Network) + +递归神经网络(Recurrent neural networks,简称RNN)是一种通过隐藏层节点周期性的连接,来捕捉序列化数据中动态信息的神经网络, +可以对序列化的数据进行分类。和其他前向神经网络不同,RNN可以保存一种上下文的状态,甚至能够在任意长的上下文窗口中存储、学习、表达相关信息, +而且不再局限于传统神经网络在空间上的边界,可以在时间序列上有延拓,直观上讲,就是本时间的隐藏层和下一时刻的隐藏层之间的节点间有边。 +RNN广泛应用在和序列有关的场景,如如一帧帧图像组成的视频,一个个片段组成的音频,和一个个词汇组成的句子。尽管RNN有一些传统的缺点, +如难以训练,参数较多,但近些年来关于网络结构、优化手段和并行计算的深入研究使得大规模学习算法成为可能,尤其是LSTM与BRNN算法的成熟,使得图像标注、手写识别、机器翻译等应用取得了突破性进展。 + +

+ +

+ +RNN主要解决序列数据的处理,比如文本、语音、视频等等。这类数据的样本间存在顺序关系,每个样本和它之前的样本存在关联。 +比如说,在文本中,一个词和它前面的词是有关联的;在气象数据中,一天的气温和前几天的气温是有关联的。一组观察数据定义为一个序列,从分布中可以观察出多个序列。 + +一个序列的最简单模型为 +

+ +

+也就是说,序列里的每一个元素都和排在它前面的所有元素直接相关。 + +当然,这个模型存在致命的问题:它的复杂度会爆炸性增长,隐马尔科夫模型(HMM)定义每个元素只和离它最近的kk个元素相关,解决了复杂度暴增的问题,模型为: + +

+ +

+ +当k=1时,模型变为: + +

+ +

+ +只考虑观察值X的模型有时表现力不足,因此需要加入隐变量,将观察值建模成由隐变量所生成。隐变量的好处在于,它的数量可以比观察值多,取值范围可以比观察值更广,能够更好的表达有限的观察值背后的复杂分布。加入了隐变量hh的马尔科夫模型称为隐马尔科夫模型。 + +

+ +

+ +隐马尔科夫模型实际上建模的是观察值X,隐变量h和模型参数θ的联合分布,HMM的模型长度T是事先固定的,模型参数不共享,其复杂度为。 + +

+ +

+ +把序列视作时间序列,隐含层h的自连接边实际上是和上一时刻的h相连.在每一个时刻t,的取值是当前时刻的输入,和上一时刻的隐含层值的一个函数: + +

+ +

+ +将h层的自连接展开,就成为了上图右边的样子,看上去和HMM很像。两者最大的区别在于,RNN的参数是跨时刻共享的。也就是说,对任意时刻t,以及的网络参数都是相同的。 + +共享参数的思想和和卷积神经网络(CNN)是相通的,CNN在二维数据的空间位置之间共享卷积核参数,而RNN则是在序列数据的时刻之间共享参数。共享参数使得模型的复杂度大大减少,并使RNN可以适应任意长度的序列,带来了更好的可推广性。 + +* 双向RNN + +单向RNN的问题在于t时刻进行分类的时候只能利用tt时刻之前的信息, 但是在t时刻进行分类的时候可能也需要利用未来时刻的信息。双向RNN(bi-directional RNN)模型正是为了解决这个问题, 双向RNN在任意时刻tt都保持两个隐藏层,一个隐藏层用于从左往右的信息传播记作, 另一个隐藏层用于从右往左的信息传播记作。 + + +

+ +

+ +Deep(Bidirectional)RNNs与Bidirectional RNNs相似,只是对于每一步的输入有多层网络。这样,该网络便有更强大的表达与学习能力,但是复杂性也提高了,同时需要更多的训练数据。 + +

+ +

+ +* Gradient Vanishing Exploding (梯度消失和梯度爆炸) +

+ +

+ +RNN训练困难的主要原因在于隐藏层参数w的传播:由于误差传播在展开后的RNN上,无论在前向传播过程还是在反向传播过程中w都会乘上多次,这就导致: + +* 梯度消失:如果梯度很小的话(<1),乘上多次指数级下降,对输出几乎就没有影响了 +* 梯度爆炸:反过来,如果梯度很大的话,乘上多次指数级增加,又导致了梯度爆炸 + +这个问题其实存在于任何深度神经网络中,只是由于RNN的递归结构导致其尤其明显。 + +对于梯度爆炸问题,可以通过截断的方式来有效避免: + +

+ +

+ +而对梯度消失问题,则有很多不同的方案: + +* 有效初始化+ReLU激活函数能够得到较好效果 +* 算法上的优化,例如截断的BPTT算法。 +* 模型上的改进,例如LSTM、GRU单元都可以有效解决长期依赖问题。 +* 在BPTT算法中加入skip connection,此时误差可以间歇的向前传播。 +* 加入一些Leaky Units,思路类似于skip connection + +LSTM 全称叫 `Long Short-Term Memory networks`,它和传统 RNN 唯一的不同就在与其中的神经元(感知机)的构造不同。传统的 RNN 每个神经元和一般神经网络的感知机没啥区别,但在 LSTM 中,每个神经元是一个“记忆细胞”(元胞状态,Cell State),将以前的信息连接到当前的任务中来。每个LSTM细胞里面都包含: + +* 输入门(input gate): 一个Sigmoid层,观察,对于元胞状态中的每一个元素,输出一个0~1之间的数。1表示“完全保留该信息”,0表示“完全丢弃该信息”: + +

+ +

+ +* 遗忘门(forget gate): 一个Sigmoid层决定我们要更新哪些信息,并由一个tanh层创造了一个新的候选值(结果在(-1, 1)(−1,1)范围) +

+ +

+ +

+ +

+ +

+ +

+ +输出门(output gate):控制哪些信息需要输出 + +

+ +

+ +

+ +

+ +

+ +

+ +典型的工作流为:在“输入门”中,根据当前的数据流来控制接受细胞记忆的影响;接着,在 “遗忘门”里,更新这个细胞的记忆和数据流;然后在“输出门”里产生输出更新后的记忆和数据流。LSTM 模型的关键之一就在于这个“遗忘门”, 它能够控制训练时候梯度在这里的收敛性(从而避免了 RNN 中的梯度 vanishing/exploding 问题),同时也能够保持长期的记忆性。 + +如果我们把LSTM的forget gate全部置0(总是忘记之前的信息),input gate全部 置1,output gate全部置1(把cell state中的信息全部输出),这样LSTM就变成一个标准的RNN。 + +目前 LSTM 模型在实践中取得了非常好的效果, 只需要训练一个两三层的LSTM, 它就可以: + +* 模仿保罗·格雷厄姆进行写作 +* 生成维基百科的 markdown 页面 +* 手写识别 +* 写代码 + +

+ +

+ +GRU (Gated Recurrent Unit) 是LSTM的变种,把LSTM中的遗忘门和输入门合并成为单一的“更新门(Update Gate)”,同时也将元胞状态(Cell State)和隐状态(Hidden State)合并,在计算当前时刻新信息的方法和LSTM有所不同。 + +

+ +

+ +GRU与RNN对比: + +

+ +

+ +####  应用示例 +```python +import numpy as np + +def sigmoid(x): + x = (np.exp(x)+0.00000000001)/np.sum(np.exp(x)+0.00000000001) + return x + +class RNN: + def __init__(self, input_dim, hidden_nodes, output_dim): + self.Wxh = np.random.random([hidden_nodes, input_dim])*0.01 + self.Bxh = np.random.random([hidden_nodes])*0.01 + self.Whh = np.random.random([hidden_nodes, hidden_nodes])*0.01 + self.Bhh = np.random.random([hidden_nodes])*0.01 + self.Wyh = np.random.random([output_dim, hidden_nodes])*0.01 + self.Byh = np.random.random([output_dim])*0.01 + self.h = np.random.random([hidden_nodes])*0.01 + + def forward(self, x): + T = x.shape[1] + states = [] + output = [] + for i in range(T): + if i == 0: + ht = np.tanh(np.dot(self.Wxh, x[:, i]) + self.Bxh + np.dot(self.Whh, self.h)) + else: + ht = np.tanh(np.dot(self.Wxh, x[:, i]) + self.Bxh + np.dot(self.Whh, states[i-1])) + ot = sigmoid(np.dot(self.Wyh, ht) + self.Byh) + states.append(ht) + output.append(ot) + return states, output + + def backword(self, x, y, h, output, lr=0.002): + T = x.shape[1] + dL_T = np.dot( np.transpose(self.Wyh), output[-1]-y[:, -1]) + loss = np.sum(-y[:, -1]*np.log(output[-1])) + dL_ht = dL_T + D_Wyh = np.zeros_like(self.Wyh) + D_Byh = np.zeros_like(self.Byh) + D_Whh = np.zeros_like(self.Whh) + D_Bhh = np.zeros_like(self.Bhh) + D_Wxh = np.zeros_like(self.Wxh) + D_Bxh = np.zeros_like(self.Bxh) + for t in range(T-2, -1, -1): + dQ = (output[t] - y[:, t]) + DL_Qt = np.dot(np.transpose(self.Wyh), dQ) + + dy = (1 - h[t]*h[t]) + dL_ht += np.dot(np.transpose(self.Wyh), dQ) + + D_Wyh += np.outer(dQ, h[t]) + D_Byh += dQ + + D_Wxh += np.outer(dy*dL_ht, x[:, t]) + D_Bxh += dy*dL_ht + + D_Whh += np.outer(dy*dL_ht, h[t-1]) + D_Bhh += dy*dL_ht + + loss += np.sum(-y[:, t]*np.log(output[t])) + for dparam in [D_Wyh, D_Byh, D_Wxh, D_Bxh, D_Whh, D_Bhh]: + np.clip(dparam, -5, 5, out=dparam) + + self.Wyh -= lr*D_Wyh/np.sqrt(D_Wyh*D_Wyh + 0.00000001) + self.Wxh -= lr*D_Wxh/np.sqrt(D_Wxh*D_Wxh + 0.00000001) + self.Whh -= lr*D_Whh/np.sqrt(D_Whh*D_Whh + 0.00000001) + self.Byh -= lr*D_Byh/np.sqrt(D_Byh*D_Byh + 0.00000001) + self.Bhh -= lr*D_Bhh/np.sqrt(D_Bhh*D_Bhh + 0.00000001) + self.Bxh -= lr*D_Bxh/np.sqrt(D_Bxh*D_Bxh + 0.00000001) + self.h -= lr*dL_ht/np.sqrt(dL_ht*dL_ht + 0.00000001) + return loss, self.h + def sample(self, x): + h = self.h + predict = [] + for i in range(9-1): + ht = np.tanh(np.dot(self.Wxh, x) + self.Bxh + np.dot(self.Whh, h)) + ot = sigmoid(np.dot(self.Wyh, ht) + self.Byh) + ynext = np.argmax(ot) + predict.append(ynext) + x = np.zeros_like(x) + x[ynext] = 1 + return predict + +#create 2000 sequences with 10 number in each sequence +def getrandomdata(nums): + x = np.zeros([nums, 10, 9], dtype=float) + y = np.zeros([nums, 10, 9], dtype=float) + for i in range(nums): + tmpi = np.random.randint(0, 9) + for j in range(9): + if tmpi < 8: + x[i, tmpi, j], y[i, tmpi+1, j] = 1.0, 1.0 + tmpi = tmpi+1 + else: + x[i, tmpi, j], y[i, 0, j] = 1.0, 1.0 + tmpi = 0 + return x, y + +def test(nums): + testx = np.zeros([nums, 10], dtype=float) + for i in range(nums): + tmpi = np.random.randint(0, 9) + testx[i, tmpi] = 1 + for i in range(nums): + print('the given start number:', np.argmax(testx[i])) + print('the created numbers: ', model.sample(testx[i]) ) + +if __name__ == '__main__': + #x0 = [0, 1, 2, 3, 4, 5, 6, 7, 8]--> y0 = [1, 2, 3, 4, 5, 6, 7, 8, 0], + #x1 = [5, 6, 7, 8, 0, 1, 2, 3, 4]--> y1 = [6, 7, 8, 0, 1, 2, 3, 4, 5] + model = RNN(10, 200, 10) + state = np.random.random(100) + epoches = 5; + smooth_loss = 0 + for ll in range(epoches): + print('epoch i:', ll) + x, y = getrandomdata(2000) + for i in range(x.shape[0]): + h, output = model.forward(x[i]) + loss, state = model.backword(x[i], y[i], h, output, lr=0.001) + if i == 1: + smooth_loss = loss + else: + smooth_loss = smooth_loss * 0.999 + loss * 0.001 + #print('loss ---- ', smooth_loss) + #if you want to see the cost, you can uncomment this line to observe the cost + test(7) +``` diff --git a/assets/src/ANN/ANN.0.5.md b/assets/src/ANN/ANN.0.5.md new file mode 100644 index 00000000..af25f655 --- /dev/null +++ b/assets/src/ANN/ANN.0.5.md @@ -0,0 +1,502 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! + +机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 + +(1)监督学习:从给定的训练数据集中学习出一个函数,当新的数据输入时,可以根据函数预测相应的结果。监督学习的训练集要求是包括输入和输出,也就是特征和目标。训练集中的目标是有标注的。如今机器学习已固有的监督学习算法有可以进行分类的,例如贝叶斯分类,SVM,ID3,C4.5以及分类决策树,以及现在最火热的人工神经网络,例如BP神经网络,RBF神经网络,Hopfield神经网络、深度信念网络和卷积神经网络等。人工神经网络是模拟人大脑的思考方式来进行分析,在人工神经网络中有显层,隐层以及输出层,而每一层都会有神经元,神经元的状态或开启或关闭,这取决于大数据。同样监督机器学习算法也可以作回归,最常用便是逻辑回归。 + +(2)无监督学习:与有监督学习相比,无监督学习的训练集的类标号是未知的,并且要学习的类的个数或集合可能事先不知道。常见的无监督学习算法包括聚类和关联,例如K均值法、Apriori算法。 + +(3)半监督学习:介于监督学习和无监督学习之间,例如EM算法。 + +如今的机器学习领域主要的研究工作在三个方面进行:1)面向任务的研究,研究和分析改进一组预定任务的执行性能的学习系统;2)认知模型,研究人类学习过程并进行计算模拟;3)理论的分析,从理论的层面探索可能的算法和独立的应用领域算法。 + +#### 多层感知器(Multilayer Perceptron) + +多层感知器(Multilayer Perceptron,缩写MLP)是一种前向结构的人工神经网络,映射一组输入向量到一组输出向量。MLP可以被看作是一个有向图,由多个的节点层所组成,每一层都全连接到下一层。除了输入节点,每个节点都是一个带有非线性激活函数的神经元(或称处理单元)。一种被称为反向传播算法的监督学习方法常被用来训练MLP。MLP是感知器的推广,克服了感知器不能对线性不可分数据进行识别的弱点 + +若每个神经元的激活函数都是线性函数,那么,任意层数的MLP都可被约简成一个等价的单层感知器。 + +实际上,MLP本身可以使用任何形式的激活函数,譬如阶梯函数或逻辑乙形函数(logistic sigmoid function),但为了使用反向传播算法进行有效学习,激活函数必须限制为可微函数。由于具有良好可微性,很多S函数,尤其是双曲正切函数(Hyperbolic tangent)及逻辑函数,被采用为激活函数。 + +通常MLP用来进行学习的反向传播算法,在模式识别的领域中算是标准监督学习算法,并在计算神经学及并行分布式处理领域中,持续成为被研究的课题。MLP已被证明是一种通用的函数近似方法,可以被用来拟合复杂的函数,或解决分类问题。 + +MLP在80年代的时候曾是相当流行的机器学习方法,拥有广泛的应用场景,譬如语音识别、图像识别、机器翻译等等,但自90年代以来,MLP遇到来自更为简单的支持向量机的强劲竞争。近来,由于深度学习的成功,MLP又重新得到了关注。 + +通常一个单一隐藏层的多层感知机(或人工神经网络—ANN)可以用图表现为: + +

+ +

+ + +正式的单一隐藏层的MLP可以表现为:,其中D是输入向量x的大小,L是输出向量f(x)的大小,矩阵表现为:, b是偏差向量,W是权重矩阵,G和s是激活函数。 + +向量构成隐藏层。是连接输入向量和隐藏层的权重矩阵。Wi代表输入单元到第i个隐藏单元的权重。一般选择tanh作为s的激活函数,使用或者使用逻辑sigmoid函数,。 + +这里我们使用Tanh因为一般它训练速度更快(有时也有利于解决局部最优)。tanh和sigmoid都是标量到标量函数,但通过点积运算向量和张量自然延伸(将向量分解成元素,生成同样大小的向量)。 + +输出向量通过以下公式得到。 + +我们此前在使用逻辑回归区分MNIST数字时提到过这一公式。如前,在多类区分中,通过使用softmax作为G的函数,可以获得类成员的概率。 + +训练一个MLP,我们学习模型所有的参数,这里我们使用随机梯度下降和批处理。要学习的参数为:。 + +梯度可以使用反向传播算法获得(连续微分的特殊形式),Theano可以自动计算这一微分过程。 + +从逻辑回归到多层感知机我们将聚焦单隐藏层的多层感知机。 我们从构建一个单隐藏层的类开始。之后只要在此基础之上加一个逻辑回归层就构建了MLP。 + +```python +class HiddenLayer(object): + def __init__(self, rng, input, n_in, n_out, W=None, b=None, + activation=T.tanh): + """ + Typical hidden layer of a MLP: units are fully-connected and have + sigmoidal activation function. Weight matrix W is of shape (n_in,n_out) + and the bias vector b is of shape (n_out,). + + NOTE : The nonlinearity used here is tanh + + Hidden unit activation is given by: tanh(dot(input,W) + b) + + :type rng: numpy.random.RandomState + :param rng: a random number generator used to initialize weights + + :type input: theano.tensor.dmatrix + :param input: a symbolic tensor of shape (n_examples, n_in) + + :type n_in: int + :param n_in: dimensionality of input + + :type n_out: int + :param n_out: number of hidden units + + :type activation: theano.Op or function + :param activation: Non linearity to be applied in the hidden + layer + """ + self.input = input +``` +隐藏层i权重的初始值应当根据激活函数以对称间断的方式取得样本。 + +对于tanh函数,区间在 + +对于sigmoid函数,区间在 + +这种初始化方式保证了在训练早期,每一个神经元在它的激活函数内操作,信息可以便利的向上(输入到输出)或反向(输出到输入)传播。 + +#### 应用示例 + +```python +""" +This tutorial introduces the multilayer perceptron using Theano. + + A multilayer perceptron is a logistic regressor where +instead of feeding the input to the logistic regression you insert a +intermediate layer, called the hidden layer, that has a nonlinear +activation function (usually tanh or sigmoid) . One can use many such +hidden layers making the architecture deep. The tutorial will also tackle +the problem of MNIST digit classification. + +.. math:: + + f(x) = G( b^{(2)} + W^{(2)}( s( b^{(1)} + W^{(1)} x))), + +References: + + - textbooks: "Pattern Recognition and Machine Learning" - + Christopher M. Bishop, section 5 + +""" + +from __future__ import print_function + +__docformat__ = 'restructedtext en' + + +import os +import sys +import timeit + +import numpy + +import theano +import theano.tensor as T + + +from logistic_sgd import LogisticRegression, load_data + + +# start-snippet-1 +class HiddenLayer(object): + def __init__(self, rng, input, n_in, n_out, W=None, b=None, + activation=T.tanh): + """ + Typical hidden layer of a MLP: units are fully-connected and have + sigmoidal activation function. Weight matrix W is of shape (n_in,n_out) + and the bias vector b is of shape (n_out,). + + NOTE : The nonlinearity used here is tanh + + Hidden unit activation is given by: tanh(dot(input,W) + b) + + :type rng: numpy.random.RandomState + :param rng: a random number generator used to initialize weights + + :type input: theano.tensor.dmatrix + :param input: a symbolic tensor of shape (n_examples, n_in) + + :type n_in: int + :param n_in: dimensionality of input + + :type n_out: int + :param n_out: number of hidden units + + :type activation: theano.Op or function + :param activation: Non linearity to be applied in the hidden + layer + """ + self.input = input + # end-snippet-1 + + # `W` is initialized with `W_values` which is uniformely sampled + # from sqrt(-6./(n_in+n_hidden)) and sqrt(6./(n_in+n_hidden)) + # for tanh activation function + # the output of uniform if converted using asarray to dtype + # theano.config.floatX so that the code is runable on GPU + # Note : optimal initialization of weights is dependent on the + # activation function used (among other things). + # For example, results presented in [Xavier10] suggest that you + # should use 4 times larger initial weights for sigmoid + # compared to tanh + # We have no info for other function, so we use the same as + # tanh. + if W is None: + W_values = numpy.asarray( + rng.uniform( + low=-numpy.sqrt(6. / (n_in + n_out)), + high=numpy.sqrt(6. / (n_in + n_out)), + size=(n_in, n_out) + ), + dtype=theano.config.floatX + ) + if activation == theano.tensor.nnet.sigmoid: + W_values *= 4 + + W = theano.shared(value=W_values, name='W', borrow=True) + + if b is None: + b_values = numpy.zeros((n_out,), dtype=theano.config.floatX) + b = theano.shared(value=b_values, name='b', borrow=True) + + self.W = W + self.b = b + + lin_output = T.dot(input, self.W) + self.b + self.output = ( + lin_output if activation is None + else activation(lin_output) + ) + # parameters of the model + self.params = [self.W, self.b] + + +# start-snippet-2 +class MLP(object): + """Multi-Layer Perceptron Class + + A multilayer perceptron is a feedforward artificial neural network model + that has one layer or more of hidden units and nonlinear activations. + Intermediate layers usually have as activation function tanh or the + sigmoid function (defined here by a ``HiddenLayer`` class) while the + top layer is a softmax layer (defined here by a ``LogisticRegression`` + class). + """ + + def __init__(self, rng, input, n_in, n_hidden, n_out): + """Initialize the parameters for the multilayer perceptron + + :type rng: numpy.random.RandomState + :param rng: a random number generator used to initialize weights + + :type input: theano.tensor.TensorType + :param input: symbolic variable that describes the input of the + architecture (one minibatch) + + :type n_in: int + :param n_in: number of input units, the dimension of the space in + which the datapoints lie + + :type n_hidden: int + :param n_hidden: number of hidden units + + :type n_out: int + :param n_out: number of output units, the dimension of the space in + which the labels lie + + """ + + # Since we are dealing with a one hidden layer MLP, this will translate + # into a HiddenLayer with a tanh activation function connected to the + # LogisticRegression layer; the activation function can be replaced by + # sigmoid or any other nonlinear function + self.hiddenLayer = HiddenLayer( + rng=rng, + input=input, + n_in=n_in, + n_out=n_hidden, + activation=T.tanh + ) + + # The logistic regression layer gets as input the hidden units + # of the hidden layer + self.logRegressionLayer = LogisticRegression( + input=self.hiddenLayer.output, + n_in=n_hidden, + n_out=n_out + ) + # end-snippet-2 start-snippet-3 + # L1 norm ; one regularization option is to enforce L1 norm to + # be small + self.L1 = ( + abs(self.hiddenLayer.W).sum() + + abs(self.logRegressionLayer.W).sum() + ) + + # square of L2 norm ; one regularization option is to enforce + # square of L2 norm to be small + self.L2_sqr = ( + (self.hiddenLayer.W ** 2).sum() + + (self.logRegressionLayer.W ** 2).sum() + ) + + # negative log likelihood of the MLP is given by the negative + # log likelihood of the output of the model, computed in the + # logistic regression layer + self.negative_log_likelihood = ( + self.logRegressionLayer.negative_log_likelihood + ) + # same holds for the function computing the number of errors + self.errors = self.logRegressionLayer.errors + + # the parameters of the model are the parameters of the two layer it is + # made out of + self.params = self.hiddenLayer.params + self.logRegressionLayer.params + # end-snippet-3 + + # keep track of model input + self.input = input + + +def test_mlp(learning_rate=0.01, L1_reg=0.00, L2_reg=0.0001, n_epochs=1000, + dataset='mnist.pkl.gz', batch_size=20, n_hidden=500): + """ + Demonstrate stochastic gradient descent optimization for a multilayer + perceptron + + This is demonstrated on MNIST. + + :type learning_rate: float + :param learning_rate: learning rate used (factor for the stochastic + gradient + + :type L1_reg: float + :param L1_reg: L1-norm's weight when added to the cost (see + regularization) + + :type L2_reg: float + :param L2_reg: L2-norm's weight when added to the cost (see + regularization) + + :type n_epochs: int + :param n_epochs: maximal number of epochs to run the optimizer + + :type dataset: string + :param dataset: the path of the MNIST dataset file from + http://www.iro.umontreal.ca/~lisa/deep/data/mnist/mnist.pkl.gz + + + """ + datasets = load_data(dataset) + + train_set_x, train_set_y = datasets[0] + valid_set_x, valid_set_y = datasets[1] + test_set_x, test_set_y = datasets[2] + + # compute number of minibatches for training, validation and testing + n_train_batches = train_set_x.get_value(borrow=True).shape[0] // batch_size + n_valid_batches = valid_set_x.get_value(borrow=True).shape[0] // batch_size + n_test_batches = test_set_x.get_value(borrow=True).shape[0] // batch_size + + ###################### + # BUILD ACTUAL MODEL # + ###################### + print('... building the model') + + # allocate symbolic variables for the data + index = T.lscalar() # index to a [mini]batch + x = T.matrix('x') # the data is presented as rasterized images + y = T.ivector('y') # the labels are presented as 1D vector of + # [int] labels + + rng = numpy.random.RandomState(1234) + + # construct the MLP class + classifier = MLP( + rng=rng, + input=x, + n_in=28 * 28, + n_hidden=n_hidden, + n_out=10 + ) + + # start-snippet-4 + # the cost we minimize during training is the negative log likelihood of + # the model plus the regularization terms (L1 and L2); cost is expressed + # here symbolically + cost = ( + classifier.negative_log_likelihood(y) + + L1_reg * classifier.L1 + + L2_reg * classifier.L2_sqr + ) + # end-snippet-4 + + # compiling a Theano function that computes the mistakes that are made + # by the model on a minibatch + test_model = theano.function( + inputs=[index], + outputs=classifier.errors(y), + givens={ + x: test_set_x[index * batch_size:(index + 1) * batch_size], + y: test_set_y[index * batch_size:(index + 1) * batch_size] + } + ) + + validate_model = theano.function( + inputs=[index], + outputs=classifier.errors(y), + givens={ + x: valid_set_x[index * batch_size:(index + 1) * batch_size], + y: valid_set_y[index * batch_size:(index + 1) * batch_size] + } + ) + + # start-snippet-5 + # compute the gradient of cost with respect to theta (sorted in params) + # the resulting gradients will be stored in a list gparams + gparams = [T.grad(cost, param) for param in classifier.params] + + # specify how to update the parameters of the model as a list of + # (variable, update expression) pairs + + # given two lists of the same length, A = [a1, a2, a3, a4] and + # B = [b1, b2, b3, b4], zip generates a list C of same size, where each + # element is a pair formed from the two lists : + # C = [(a1, b1), (a2, b2), (a3, b3), (a4, b4)] + updates = [ + (param, param - learning_rate * gparam) + for param, gparam in zip(classifier.params, gparams) + ] + + # compiling a Theano function `train_model` that returns the cost, but + # in the same time updates the parameter of the model based on the rules + # defined in `updates` + train_model = theano.function( + inputs=[index], + outputs=cost, + updates=updates, + givens={ + x: train_set_x[index * batch_size: (index + 1) * batch_size], + y: train_set_y[index * batch_size: (index + 1) * batch_size] + } + ) + # end-snippet-5 + + ############### + # TRAIN MODEL # + ############### + print('... training') + + # early-stopping parameters + patience = 10000 # look as this many examples regardless + patience_increase = 2 # wait this much longer when a new best is + # found + improvement_threshold = 0.995 # a relative improvement of this much is + # considered significant + validation_frequency = min(n_train_batches, patience // 2) + # go through this many + # minibatche before checking the network + # on the validation set; in this case we + # check every epoch + + best_validation_loss = numpy.inf + best_iter = 0 + test_score = 0. + start_time = timeit.default_timer() + + epoch = 0 + done_looping = False + + while (epoch < n_epochs) and (not done_looping): + epoch = epoch + 1 + for minibatch_index in range(n_train_batches): + + minibatch_avg_cost = train_model(minibatch_index) + # iteration number + iter = (epoch - 1) * n_train_batches + minibatch_index + + if (iter + 1) % validation_frequency == 0: + # compute zero-one loss on validation set + validation_losses = [validate_model(i) for i + in range(n_valid_batches)] + this_validation_loss = numpy.mean(validation_losses) + + print( + 'epoch %i, minibatch %i/%i, validation error %f %%' % + ( + epoch, + minibatch_index + 1, + n_train_batches, + this_validation_loss * 100. + ) + ) + + # if we got the best validation score until now + if this_validation_loss < best_validation_loss: + #improve patience if loss improvement is good enough + if ( + this_validation_loss < best_validation_loss * + improvement_threshold + ): + patience = max(patience, iter * patience_increase) + + best_validation_loss = this_validation_loss + best_iter = iter + + # test it on the test set + test_losses = [test_model(i) for i + in range(n_test_batches)] + test_score = numpy.mean(test_losses) + + print((' epoch %i, minibatch %i/%i, test error of ' + 'best model %f %%') % + (epoch, minibatch_index + 1, n_train_batches, + test_score * 100.)) + + if patience <= iter: + done_looping = True + break + + end_time = timeit.default_timer() + print(('Optimization complete. Best validation score of %f %% ' + 'obtained at iteration %i, with test performance %f %%') % + (best_validation_loss * 100., best_iter + 1, test_score * 100.)) + print(('The code for file ' + + os.path.split(__file__)[1] + + ' ran for %.2fm' % ((end_time - start_time) / 60.)), file=sys.stderr) + + +if __name__ == '__main__': + test_mlp() + +``` diff --git a/assets/src/ANN/ANN.0.6.md b/assets/src/ANN/ANN.0.6.md new file mode 100644 index 00000000..eb3ad5f5 --- /dev/null +++ b/assets/src/ANN/ANN.0.6.md @@ -0,0 +1,237 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! + +机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 + +(1)监督学习:从给定的训练数据集中学习出一个函数,当新的数据输入时,可以根据函数预测相应的结果。监督学习的训练集要求是包括输入和输出,也就是特征和目标。训练集中的目标是有标注的。如今机器学习已固有的监督学习算法有可以进行分类的,例如贝叶斯分类,SVM,ID3,C4.5以及分类决策树,以及现在最火热的人工神经网络,例如BP神经网络,RBF神经网络,Hopfield神经网络、深度信念网络和卷积神经网络等。人工神经网络是模拟人大脑的思考方式来进行分析,在人工神经网络中有显层,隐层以及输出层,而每一层都会有神经元,神经元的状态或开启或关闭,这取决于大数据。同样监督机器学习算法也可以作回归,最常用便是逻辑回归。 + +(2)无监督学习:与有监督学习相比,无监督学习的训练集的类标号是未知的,并且要学习的类的个数或集合可能事先不知道。常见的无监督学习算法包括聚类和关联,例如K均值法、Apriori算法。 + +(3)半监督学习:介于监督学习和无监督学习之间,例如EM算法。 + +如今的机器学习领域主要的研究工作在三个方面进行:1)面向任务的研究,研究和分析改进一组预定任务的执行性能的学习系统;2)认知模型,研究人类学习过程并进行计算模拟;3)理论的分析,从理论的层面探索可能的算法和独立的应用领域算法。 + +#### 玻尔兹曼机(Boltzmann Machine) +玻尔兹曼机(Boltzmann machine)是随机神经网络和递归神经网络的一种,由杰弗里·辛顿(Geoffrey Hinton)和特里·谢泽诺斯基(Terry Sejnowski)在1985年发明。 + +玻尔兹曼机是一种特殊形式的对数线性的马尔科夫随机场(Markov Random Field,MRF),即能量函数是自由变量的线性函数。 通过引入隐含单元,我们可以提升模型的表达能力,表示非常复杂的概率分布。 + +玻尔兹曼机可被视作随机过程的,可生成的相应的Hopfield神经网络。它是最早能够学习内部表达,并能表达和(给定充足的时间)解决复杂的组合优化问题的神经网络。但是,没有特定限制连接方式的玻尔兹曼机目前为止并未被证明对机器学习的实际问题有什么用。所以它目前只在理论上显得有趣。然而,由于局部性和训练算法的赫布性质(Hebbian nature),以及它们和简单物理过程相似的并行性,如果连接方式是受约束的(即受限玻尔兹曼机),学习方式在解决实际问题上将会足够高效。 + +它由玻尔兹曼分布得名。该分布用于玻尔兹曼机的抽样函数。 + +

+ +

+ +玻尔兹曼机的图像表示. 每条无向边都表示一对依赖关系. 在这个例子中有三个隐藏节点和四个可见节点,它并不是一个约束玻尔兹曼机(restricted Boltzmann machine) + + +#### 应用示例 +```python +from unittest import TestCase +from matplotlib import pyplot + +__author__ = 'riri' +import numpy as np +epsilon = 0.000001 +def sigmoid(v): + return 1/(1+np.exp(-v)) + +def hidden_activation_probability(v,W,c): + # x is size k*v + # W is size h*v + # W.T is size v*h + # c is length h + # result is size k*h + return sigmoid(c + np.dot(v, W.T)) + +def hidden_activation_probability_naive(v,W,c): + activations = np.zeros(W.shape[0]) + if v.size != W.shape[1]: + #print v.size + #print v.shape + #print W.shape + pass + assert(v.size == W.shape[1]) + for i in range(W.shape[0]): + activations[i] = sigmoid(c[i] + sum([W[i,j]*v[j] for j in range(W.shape[1])])) + return activations + +def visible_activation_probability(h,W,b): + # h is length k*h + # W is size h*v + # b is length v + # result is size k*v + return sigmoid(b + np.dot(h,W)) + +def visible_activation_probability_naive(h,W,b): + activations = np.zeros(W.shape[1]) + assert(h.size == W.shape[0]) + for j in range(W.shape[1]): + activations[j] = sigmoid(b[j] + sum([W[i,j]*h[i] for i in range(W.shape[0])])) + return activations + +def sample_hidden_units(v,W,c): + hidden_probabilities = hidden_activation_probability(v,W,c) + return np.random.uniform(size=hidden_probabilities.shape) < hidden_probabilities + +def sample_hidden_units_naive(v,W,c): + hidden_probabilities = hidden_activation_probability_naive(v,W,c) + return np.random.uniform(size=hidden_probabilities.shape) < hidden_probabilities + +def sample_visible_units(h,W,b): + visible_probabilities = visible_activation_probability(h,W,b) + return np.random.uniform(size=visible_probabilities.shape) < visible_activation_probability(h,W,b) + +def sample_visible_units_naive(h,W,b): + visible_probabilities = visible_activation_probability_naive(h,W,b) + return np.random.uniform(size=visible_probabilities.shape) < visible_activation_probability(h,W,b) + +def rbmUpdate_naive(x, W, b, c, lr=0.1): + h1 = sample_hidden_units_naive(x,W,c) + v2 = sample_visible_units_naive(h1,W,b) + q_v2 = visible_activation_probability_naive(h1,W,b) + q_h2 = hidden_activation_probability_naive(v2,W,c) + new_b = b + lr*(x-v2) + new_c = c + lr*(h1-q_h2) + a = np.outer(h1,x) + b = np.outer(q_h2,v2.T) + new_W = W + lr*(a-b) + error = np.sum((x-q_v2)**2) + return new_W,new_b,new_c,error + +def rbmUpdate(x,W,b,c,lr=0.1): + h1 = sample_hidden_units(x,W,c) + v2 = sample_visible_units(h1,W,b) + q_v2 = visible_activation_probability(h1,W,b) + q_h2 = hidden_activation_probability(v2,W,c) + new_b = b + lr*(x-v2) + new_c = c + lr*(h1-q_h2) + a = np.outer(h1,x) + b = np.outer(q_h2,v2.T) + new_W = W + lr*(a-b) + error = np.sum(np.sum((x-q_v2)**2)) + return new_W,new_b,new_c,error + +class RBM(object): + def __init__(self, visible_units, hidden_units): + self.v = visible_units + self.h = hidden_units + self.W = np.random.random(size=(hidden_units, visible_units)) + self.b = np.random.random(visible_units) + self.c = np.random.random(hidden_units) + + def train(self, data, lr=0.05, max_iterations=1000, eps=0.1): + iteration = 0 + last_error = eps+1 + while iteration < max_iterations and last_error > eps: + for item in data: + self.W,self.b,self.c,last_error = rbmUpdate(item, self.W,self.b,self.c,lr) + iteration += 1 + if iteration % 10 == 0: + print last_error + + def train_naive(self,data,lr=0.05,max_iterations=1000,eps=0.1): + iteration = 0 + last_error = eps+1 + while iteration < max_iterations and last_error > eps: + for item in data: + self.W,self.b,self.c,last_error = rbmUpdate_naive(item, self.W,self.b,self.c,lr) + iteration += 1 + if iteration % 10 == 0: + print last_error +class TestAgainstNaive(object): + def __init__(self, h_size, v_size): + self.h_size = h_size + self.v_size = v_size + def test_hidden(self): + h_size = self.h_size + v_size = self.v_size + ww = np.random.uniform(size=(h_size,v_size)) + bb = np.random.uniform(size=v_size) + cc = np.random.uniform(size=h_size) + vv = np.random.uniform(size=v_size) + h1 = hidden_activation_probability_naive(vv,ww,cc) + h2 = hidden_activation_probability(vv,ww,cc) + assert(h1.shape == h2.shape) + assert(h1.size == h_size) + assert(all(np.abs(h1 - h2) < epsilon)) + def test_visible(self): + h_size = self.h_size + v_size = self.v_size + ww = np.random.uniform(size=(h_size,v_size)) + bb = np.random.uniform(size=v_size) + hh = np.random.uniform(size=h_size) + v1 = visible_activation_probability_naive(hh,ww,bb) + v2 = visible_activation_probability(hh,ww,bb) + assert(v1.shape == v2.shape) + assert(v1.size == v_size) + assert(all(np.abs(v1 - v2) < epsilon)) + def test_update(self): + h_size = self.h_size + v_size = self.v_size + ww = np.random.uniform(size=(h_size,v_size)) + bb = np.random.uniform(size=v_size) + cc = np.random.uniform(size=h_size) + vv = np.random.uniform(size=v_size) + (nw1,nb1,nc1,e1) = rbmUpdate(vv,ww,bb,cc) + (nw2,nb2,nc2,e2) = rbmUpdate_naive(vv,ww,bb,cc) + + # The bounds for this are a bit larger, because + # more goes one, so there are more chances for + # divergence. + assert(np.all(np.abs(nw1-nw2) < epsilon*5)) + assert(np.all(np.abs(nb1-nb2) < epsilon*5)) + assert(np.all(np.abs(nc1-nc2) < epsilon*5)) + assert(np.all(np.abs(e1-e2) < epsilon*5)) + +def chunkfiles(files): + splitwords = [] + vocab = set() + for f in files: + for line in f.readlines(): + splitwords.append(set(line.split())) + vocab = vocab.union(line.split()) + entries = [] + vocablist = list(vocab) + for entry in splitwords: + entries.append([1 if word in entry else 0 for word in vocablist]) + return entries + +def splitfiles(files): + splitwords = [] + vocab = set() + for f in files: + for line in f.readlines(): + splitwords.append(set(line.split())) + vocab = vocab.union(line.split()) + return splitwords + + +def go(): + tests = 1 + magnitude_mat = np.zeros((7,4*tests)) + with open('./movies.txt') as movies: + with open('./matrices.txt') as matrices: + terms = chunkfiles([movies, matrices]) + for i in range(tests): + training_data = np.array(terms[1:-1]) + print training_data.shape + r = RBM(399, 2) + r.train(training_data ,max_iterations=500,lr=0.1) + movterm = np.array([terms[1]]) + matterm = np.array([terms[-1]]) + print hidden_activation_probability(movterm,r.W,r.c) + print hidden_activation_probability(matterm,r.W,r.c) + pyplot.imshow(magnitude_mat, interpolation='nearest') + +if __name__=='__main__': + h_size = np.floor(np.random.rand()*100) + v_size = np.floor(np.random.rand()*100) + test = TestAgainstNaive(h_size,v_size) + test.test_visible() + test.test_hidden() + test.test_update() + go() +``` diff --git a/assets/src/ANN/ANN.0.7.md b/assets/src/ANN/ANN.0.7.md new file mode 100644 index 00000000..bcc81d07 --- /dev/null +++ b/assets/src/ANN/ANN.0.7.md @@ -0,0 +1,390 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! + +机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 + +(1)监督学习:从给定的训练数据集中学习出一个函数,当新的数据输入时,可以根据函数预测相应的结果。监督学习的训练集要求是包括输入和输出,也就是特征和目标。训练集中的目标是有标注的。如今机器学习已固有的监督学习算法有可以进行分类的,例如贝叶斯分类,SVM,ID3,C4.5以及分类决策树,以及现在最火热的人工神经网络,例如BP神经网络,RBF神经网络,Hopfield神经网络、深度信念网络和卷积神经网络等。人工神经网络是模拟人大脑的思考方式来进行分析,在人工神经网络中有显层,隐层以及输出层,而每一层都会有神经元,神经元的状态或开启或关闭,这取决于大数据。同样监督机器学习算法也可以作回归,最常用便是逻辑回归。 + +(2)无监督学习:与有监督学习相比,无监督学习的训练集的类标号是未知的,并且要学习的类的个数或集合可能事先不知道。常见的无监督学习算法包括聚类和关联,例如K均值法、Apriori算法。 + +(3)半监督学习:介于监督学习和无监督学习之间,例如EM算法。 + +如今的机器学习领域主要的研究工作在三个方面进行:1)面向任务的研究,研究和分析改进一组预定任务的执行性能的学习系统;2)认知模型,研究人类学习过程并进行计算模拟;3)理论的分析,从理论的层面探索可能的算法和独立的应用领域算法。 + +#### 卷积神经网络(Convolutional Neural Network) + +卷积神经网络(Convolutional Neural Network,CNN)是一种前馈神经网络,它的人工神经元可以响应一部分覆盖范围内的周围单元,对于大型图像处理有出色表现。 它包括卷积层(convolutional layer)和池化层(pooling layer)。 + +卷积神经网络是近年发展起来,并引起广泛重视的一种高效识别方法。20世纪60年代,Hubel和Wiesel在研究猫脑皮层中用于局部敏感和方向选择的神经元时发现其独特的网络结构可以有效地降低反馈神经网络的复杂性,继而提出了卷积神经网络(Convolutional Neural Networks-简称CNN)。现在,CNN已经成为众多科学领域的研究热点之一,特别是在模式分类领域,由于该网络避免了对图像的复杂前期预处理,可以直接输入原始图像,因而得到了更为广泛的应用。 K.Fukushima在1980年提出的新识别机是卷积神经网络的第一个实现网络。随后,更多的科研工作者对该网络进行了改进。其中,具有代表性的研究成果是Alexander和Taylor提出的“改进认知机”,该方法综合了各种改进方法的优点并避免了耗时的误差反向传播。 + +CNN的基本结构包括两层,其一为特征提取层,每个神经元的输入与前一层的局部接受域相连,并提取该局部的特征。一旦该局部特征被提取后,它与其它特征间的位置关系也随之确定下来;其二是特征映射层,网络的每个计算层由多个特征映射组成,每个特征映射是一个平面,平面上所有神经元的权值相等。特征映射结构采用影响函数核小的sigmoid函数作为卷积网络的激活函数,使得特征映射具有位移不变性。此外,由于一个映射面上的神经元共享权值,因而减少了网络自由参数的个数。卷积神经网络中的每一个卷积层都紧跟着一个用来求局部平均与二次提取的计算层,这种特有的两次特征提取结构减小了特征分辨率。 + +CNN主要用来识别位移、缩放及其他形式扭曲不变性的二维图形。由于CNN的特征检测层通过训练数据进行学习,所以在使用CNN时,避免了显式的特征抽取,而隐式地从训练数据中进行学习;再者由于同一特征映射面上的神经元权值相同,所以网络可以并行学习,这也是卷积网络相对于神经元彼此相连网络的一大优势。卷积神经网络以其局部权值共享的特殊结构在语音识别和图像处理方面有着独特的优越性,其布局更接近于实际的生物神经网络,权值共享降低了网络的复杂性,特别是多维输入向量的图像可以直接输入网络这一特点避免了特征提取和分类过程中数据重建的复杂度。 + +

+ +

+#### 应用示例 +```python +import numpy as np +import scipy.signal as signal +import cPickle +import gzip +import gc +import scipy +#import objgraph +def sigmoid(input): + '激励函数' + out=1.7159*scipy.tanh(2.0/3.0*input) + return out +def dsigmoid(input): + 'sigmoid的导函数已知input=sigmod(out)' + out=2.0/3.0/1.7159*(1.7159+input)*(1.7159-input) + return out +def convolutional(fm,ct,kernel,bias): + '卷积函数' + "fm 特征图 三维" + "ct 连接权矩阵" + "kernel 卷积核 三维" + "bias 偏置 向量" + map_width=fm.shape[2] + map_height=fm.shape[1] + kernel_width=kernel.shape[2] + kernel_height=kernel.shape[1] + '计算特征图的尺寸' + dst_height=map_height-kernel_height+1 + dst_width=map_width-kernel_width+1 + '计算输出特征图的数量' + cfmDims=np.max(ct[1])+1 + n_kernels=kernel.shape[0] + #print("ct's shape%d:%d"%(ct.shape[0],ct.shape[1])) + ' 初始化结果特征图' + cfm=np.zeros((cfmDims,dst_height,dst_width)) + for index in xrange(0,cfmDims): + "首先加上偏置值" + cfm[index]+=bias[index] + for index in xrange(0,n_kernels): + #print(index) + this_fm=fm[ct[0,index]] + this_kernel=kernel[index] + "计算卷积" + this_conv=signal.convolve2d(this_fm, this_kernel, mode='valid') + cfm_index=ct[1,index] + cfm[cfm_index]+=this_conv + "使用sigmoid压制" + return sigmoid(cfm) +def subsampling(fm,sW,sb,pool_size,pool_stride): + "重采样函数" + "fm 特征图" + "sW 重采样权值 向量" + "sb 重采样偏置 向量" + "pool_size 重采样窗口大小 二维矩阵" + "pool_stride 步长 int" + sfm_width=int((fm.shape[2]-pool_size[1])/pool_stride)+1 + sfm_height=int((fm.shape[1]-pool_size[0])/pool_stride)+1 + sfmDims=fm.shape[0] + sfm=np.zeros((sfmDims,sfm_width,sfm_height)) + #sfm=[] + "使用权值为1的核进行采样" + kernel=np.ones(pool_size) + for index in xrange(0,sfmDims): + this_fm=fm[index] + this_kernel=kernel*sW[index] + "采样实际就是一次卷积过程" + this_sfm=signal.convolve2d(this_fm, this_kernel, mode='valid') + sfm[index]=copy_fm(this_sfm,pool_stride) + sfm[index]=sfm[index]+sb[index] + sfm=sigmoid(sfm) + return sfm +def copy_fm(fm,stride): + height=fm.shape[0] + width=fm.shape[1] + result=[] + for y in xrange(0,height,stride): + y_result=[] + y_data=fm[y] + for x in xrange(0,width,stride): + y_result.append(y_data[x]) + result.append(y_result) + return np.array(result) +def max_with_index(value): + "返回最大值,及最大值的下标" + "结果 [下标,最大值]" + d=np.max(value) + i=np.argmax(value) + return [i,d] +def grade(dout,out,input,w): + dout=dout*dsigmoid(out) + db=dout + dw=np.zeros(w.shape) + out=out*dsigmoid(out) + for i in xrange(w.shape[1]): + dw[:,i]=dout[i]*input + din=np.zeros(input.shape) + for i in xrange(db.shape[0]): + this_kernel=w[:,i] + #print("this kernrl:%s\n"%(this_kernel)) + this_dout=dout[i]*this_kernel + #print("this dout: %s"%(this_dout)) + din+=this_dout + return [din,dw,db] +def dconv2_in(dout,input,kernel): + return signal.convolve2d(dout,kernel,mode='full') +def dconv2_kernel(dout,input,kernel): + return signal.convolve2d(input,dout,mode='valid') +def initWeight(ct,kernel_shape): + kernel_num=ct[0].shape[0] + kernel_height=kernel_shape[0] + kernel_width=kernel_shape[1] + weights=np.zeros((kernel_num,kernel_height,kernel_width)) + for i in xrange(kernel_num): + connected=np.array((ct[1]==ct[0,i]),dtype='int') + connected=np.array(np.nonzero(connected)) + connected=connected.shape[0] + fanin=connected*kernel_height*kernel_width + sd=1.0/np.sqrt(fanin) + weights[i]=-1.0*sd+2*sd*np.random.random_sample((kernel_height,kernel_width)) + return weights +class convlayer: + def __init__(self,cw,cb,sw,sb,ct,stride): + self.sw=sw + self.sb=sb + self.cw=cw + self.cb=cb + self.ct=ct + self.stride=stride +class bplayer: + def __init__(self,n_in,n_out): + sd=1.0/np.sqrt(n_in) + self.w=-sd+2*sd*np.random.random_sample((n_in,n_out)) + self.b=np.zeros(n_out) + self.n_in=n_in + self.n_out=n_out +class convnet: + def __init__(self,image_shape): + self.eta=0.01 + self.decay=0.8 + self.step=2 + ct1=np.array([[1,1,1,1]]) + ct2=np.array([[1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0], + [0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1], + [0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1], + [1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,0]]) + ct1=np.transpose(ct1) + ct2=np.transpose(ct2) + conv_ct1=np.nonzero(ct1) + conv_ct1=np.array((conv_ct1[1],conv_ct1[0])) + conv_ct2=np.nonzero(ct2) + conv_ct2=np.array((conv_ct2[1],conv_ct2[0])) + image_height=image_shape[0] + image_width=image_shape[1] + self.image_shape=image_shape + self.kernel_shape=[5,5] + self.pool_shape=[2,2] + self.stride=2 + stride=self.stride + kernel_height=self.kernel_shape[0] + kernel_width=self.kernel_shape[1] + pool_height=self.pool_shape[0] + pool_width=self.pool_shape[1] + nofms1=ct1.shape[0] + "初始化卷积层1" + cmfHeight1=image_height-kernel_height+1 + cfmWidth1=image_width-kernel_width+1 + conv_layer1_cw=initWeight(conv_ct1, self.kernel_shape) + conv_layer2_cb=np.zeros(nofms1) + sfmHeight1=((cmfHeight1-pool_height)/stride)+1 + sfmWidth1=((cfmWidth1-pool_width)/stride)+1 + fanin=pool_height*pool_width + sd=1.0/np.sqrt(fanin) + conv_layer1_sw=-sd+2*sd*np.random.random_sample(nofms1) + conv_layer1_sb=np.zeros(nofms1) + self.conv1=convlayer(conv_layer1_cw,conv_layer2_cb,conv_layer1_sw,conv_layer1_sb,conv_ct1,stride) + "初始化卷基层2" + nofms2=ct2.shape[0] + conv_layer2_cw=initWeight(conv_ct2, self.kernel_shape) + conv_layer2_cb=np.zeros(nofms2) + cfmHeight2=sfmHeight1-kernel_height+1 + cfmWidth2=sfmWidth1-kernel_width+1 + sfmHeight2=((cfmHeight2-pool_height)/stride)+1 + sfmWidth2=((cfmWidth2-pool_width)/stride)+1 + fanin=pool_width*pool_height + sd=1.0/np.sqrt(fanin) + conv_layer2_sw=-sd+2*sd*np.random.random_sample(nofms2) + conv_layer2_sb=np.zeros(nofms2) + self.conv2=convlayer(conv_layer2_cw,conv_layer2_cb,conv_layer2_sw,conv_layer2_sb,conv_ct2,stride) + "BP分类器第一层" + self.bp1=bplayer(nofms2*sfmHeight2*sfmWidth2,20) + self.bp2=bplayer(20,10) + self.noErrors=0 + def forwardPropConv(self,input): + "开始第一层的卷积操作" + ct=self.conv1.ct + cw=self.conv1.cw + cb=self.conv1.cb + cfm1=convolutional(input, ct, cw, cb) + sw=self.conv1.sw + sb=self.conv1.sb + sfm1=subsampling(cfm1, sw, sb, self.pool_shape, self.stride) + "开始第二层的卷积操作" + ct=self.conv2.ct + cw=self.conv2.cw + cb=self.conv2.cb + cfm2=convolutional(sfm1, ct, cw, cb) + sw=self.conv2.sw + sb=self.conv2.sb + sfm2=subsampling(cfm2, sw, sb, self.pool_shape, self.stride) + return [cfm1,sfm1,cfm2,sfm2] + def forwradPropBp(self,input): + "开始第一层分类器的操作" + w=self.bp1.w + b=self.bp1.b + out1=np.dot(input,w) + for i in xrange(b.shape[0]): + out1[i]+=b[i] + out1=sigmoid(out1) + "开始第二层的操作" + w=self.bp2.w + b=self.bp2.b + out2=np.dot(out1,w) + for i in xrange(b.shape[0]): + out2[i]+=b[i] + out2=sigmoid(out2) + return [out1,out2] + def backPropBp(self,sfm,tartget,fm1,fm2,w1,w2,b1,b2): + "对BP层进行反向传播" + "sfm 卷积层的S神经元的输出" + "target 目标值" + "fm1 BP层第一层输出" + "fm2 BP层第二层输出" + "w1 b1 第一层参数" + "w2 b2 第二层参数" + dtarget=-np.ones(self.bp2.n_out)*0.8 + dtarget[target]=0.8 + dfm2=np.zeros(self.bp2.n_out) + dfm2=dfm2-dtarget + dmf2=dfm2*dsigmoid(dfm2) + dfm1,dw2,db2=grade(dfm2,fm2,fm1,w2) + dsfm,dw1,db1=grade(dfm1,fm1,sfm,w1) + return [dsfm,dw1,db1,dw2,db2] + def backPropSubsampling(self,dsfm,sfm,cfm,sw,sb,pool_shape,stride): + "对S神经元进行反向传播" + "dsfm s神经元的输出的偏导数" + "sfm s神经元的输出" + "cfm 上层c神经元的输出" + "sw sb 神经元参数" + "pool_shape 采样窗口" + "stride 采样步长" + dims,height,width=cfm.shape + dfm=np.zeros(cfm.shape) + dsw=np.zeros(sw.shape) + dsb=np.zeros(sb.shape) + dsfm=dsfm*dsigmoid(sfm) + kernel=np.ones(pool_shape) + for i in xrange(dims): + this_dsfm=dsfm[i] + dthis_kernel=kernel*sw[i] + dsb[i]=np.sum(this_dsfm) + cfm_height=height-pool_shape[0]+1 + cfm_width=width-pool_shape[1]+1 + #print("height:%d,width:%d\n"%(cfm_height,cfm_width)) + dsfm_beforeSubsampling=np.zeros((cfm_height, cfm_width)) + y=0 + x=0 + for dy in xrange(0,dsfm_beforeSubsampling.shape[0],stride): + x=0 + for dx in xrange(0,dsfm_beforeSubsampling.shape[1],stride): + dsfm_beforeSubsampling[dy,dx]=this_dsfm[y,x] + x+=1 + y+=1 + dfm[i]=dconv2_in(dsfm_beforeSubsampling,cfm[i],dthis_kernel) + dsw[i]=np.sum(dthis_kernel) + return [dfm,dsw,dsb] + def backPropConvulution(self,dcfm,cfm,fm,ct,w,b): + dfm=np.zeros(fm.shape) + dw=np.zeros(w.shape) + db=np.zeros(b.shape) + dcfm=dcfm*dsigmoid(cfm) + for i in xrange(b.shape[0]): + this_dcfm=dcfm[i] + db[i]=np.sum(this_dcfm) + for i in xrange(w.shape[0]): + this_fm=fm[ct[0,i]] + this_w=w[i] + this_dcfm=dcfm[ct[1,i]] + this_dfm=dconv2_in(this_dcfm,this_fm,this_w) + dfm[ct[0,i]]=dfm[ct[0,i]]+this_dfm + dw[i]=dconv2_kernel(this_dcfm,this_fm,this_w) + return [dfm,dw,db] + def trian(self,input,target): + cfm1,sfm1,cfm2,sfm2=self.forwardPropConv(input) + bp_input=sfm2.reshape(self.bp1.n_in) + bp1_out,bp2_out=self.forwradPropBp(bp_input) + out=max_with_index(bp2_out) + if out[0]==target: + self.noErrors+=1 + eta=self.eta + w1=self.bp1.w + b1=self.bp1.b + w2=self.bp2.w + b2=self.bp2.b + dsfm,dw1,db1,dw2,db2=self.backPropBp(bp_input, target, bp1_out, bp2_out, w1, w2, b1, b2) + self.bp1.w=self.bp1.w-dw1*eta + self.bp1.b=self.bp1.b-db1*eta + self.bp2.w=self.bp2.w-dw2*eta + self.bp2.b=self.bp2.b-db2*eta + dsfm=dsfm.reshape(sfm2.shape) + sw2=self.conv2.sw + sb2=self.conv2.sb + ct2=self.conv2.ct + cw2=self.conv2.cw + cb2=self.conv2.cb + pool_shape=self.pool_shape + stride=self.stride + dcfm2,dsw2,dsb2=self.backPropSubsampling(dsfm, sfm2,cfm2, sw2, sb2, pool_shape, stride) + dsfm1,dcw2,dcb2=self.backPropConvulution(dcfm2, cfm2, sfm1, ct2, cw2, cb2) + self.conv2.sw=self.conv2.sw-dsw2*eta + self.conv2.sb=self.conv2.sb-dsb2*eta + self.conv2.cw=self.conv2.cw-dcw2*eta + self.conv2.cb=self.conv2.cb-dcb2*eta + sw1=self.conv1.sw + sb1=self.conv1.sb + ct1=self.conv1.ct + cw1=self.conv1.cw + cb1=self.conv1.cb + dcfm1,dsw1,dsb1=self.backPropSubsampling(dsfm1, sfm1,cfm1, sw1, sb1, pool_shape, stride) + dfm,dcw1,dcb1=self.backPropConvulution(dcfm1, cfm1, input, ct1, cw1, cb1) + self.conv1.sw=sw1-dsw1*eta + self.conv1.sb=sb1-dsb1*eta + self.conv1.cw=cw1-dcw1*eta + self.conv1.cb=cb1-dcb1*eta + #print(out) +def load_data(path): + f=gzip.open(path,'rb') + train_set,valid_set,test_set=cPickle.load(f) + del f.f + return [train_set,valid_set,test_set] +if __name__=='__main__': + gc.enable() + gc.set_debug(gc.DEBUG_COLLECTABLE | gc.DEBUG_UNCOLLECTABLE | gc.DEBUG_INSTANCES | gc.DEBUG_OBJECTS) + train_set,valid_set,test_set=load_data('d:/data/mnist.pkl.gz') + num=train_set[0].shape[0] + cnn=convnet([28,28]) + for train in xrange(1,21): + cnn.noErrors=0 + print("第%d次训练"%(train)) + for i in xrange(1,num+1): + image=train_set[0][i-1] + data=image.reshape([1,28,28]) + target=train_set[1][i-1] + cnn.trian(data, target) + if i%1000==0: + print("train %d,noErrors %d\n"%(i,cnn.noErrors)) + _unreachable = gc.collect() + print("unreachable %d\n"%(_unreachable)) + if train%cnn.step==0: + cnn.eta=cnn.eta*cnn.decay + del data + del image +``` + diff --git a/assets/src/ANN/ANN.0.8.md b/assets/src/ANN/ANN.0.8.md new file mode 100644 index 00000000..dd265ac0 --- /dev/null +++ b/assets/src/ANN/ANN.0.8.md @@ -0,0 +1,131 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! + +机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 + +(1)监督学习:从给定的训练数据集中学习出一个函数,当新的数据输入时,可以根据函数预测相应的结果。监督学习的训练集要求是包括输入和输出,也就是特征和目标。训练集中的目标是有标注的。如今机器学习已固有的监督学习算法有可以进行分类的,例如贝叶斯分类,SVM,ID3,C4.5以及分类决策树,以及现在最火热的人工神经网络,例如BP神经网络,RBF神经网络,Hopfield神经网络、深度信念网络和卷积神经网络等。人工神经网络是模拟人大脑的思考方式来进行分析,在人工神经网络中有显层,隐层以及输出层,而每一层都会有神经元,神经元的状态或开启或关闭,这取决于大数据。同样监督机器学习算法也可以作回归,最常用便是逻辑回归。 + +(2)无监督学习:与有监督学习相比,无监督学习的训练集的类标号是未知的,并且要学习的类的个数或集合可能事先不知道。常见的无监督学习算法包括聚类和关联,例如K均值法、Apriori算法。 + +(3)半监督学习:介于监督学习和无监督学习之间,例如EM算法。 + +如今的机器学习领域主要的研究工作在三个方面进行:1)面向任务的研究,研究和分析改进一组预定任务的执行性能的学习系统;2)认知模型,研究人类学习过程并进行计算模拟;3)理论的分析,从理论的层面探索可能的算法和独立的应用领域算法。 + +#### Hopfield网络(Hopfield Network) + +Hopfield神经网络是一种递归神经网络,由约翰·霍普菲尔德在1982年发明。Hopfield网络是一种结合存储系统和二元系统的神经网络。它保证了向局部极小的收敛,但收敛到错误的局部极小值(local minimum),而非全局极小(global minimum)的情况也可能发生。Hopfield网络也提供了模拟人类记忆的模型。 + +Hopfield提出了连续和离散的Hopfield神经网络模型,并采用全互联型神经网络尝试对非多项式复杂度的旅行商问题(Travelling Salesman Problem,TSP)进行了求解,促进神经网络的研究再次进入了蓬勃发展的时期。 + +Hopfield强调工程实践的重要性,他利用电阻、电容和运算放大器等元件组成的模拟电路实现了对网络神经元的描述,把最优化问题的目标函数转换成Hopfield神经网络的能量函数,通过网络能量函数最小化来寻找对应问题的最优解.Hopfield网络是一种循环神经网络,从输出到输入有反馈连接,典型的Hopfield神经网络模型如图所示. +

+ +

+在图中每组运算放大器及其相关的电阻、电容组成的网络代表一个神经元。每个神经元有两组输入,一组是恒定的外部电流,另一组是来自其他运算放大器输出的正向或反向的反馈连接。假设第i个神经元的内部膜电位为Ui(i=1,2,…,n),细胞膜的输入电容和传递电阻分别为Ci和Ri,神经元的输出电位为Vi,外部输入电流为Ii,并用电阻Rij(i,j=1,2,…,n)来模拟第i个和第j个神经元之间的突触特性。由基尔霍夫电流定律(Kirchhoff’s Cureent Law ,KCL)可知,放大器输入节点处的流入电流和流出电流保持平衡,亦即有下式成立: +

+ +

+同时,每一个运算放大器模拟了神经元输入和输出之间的非线性特性,即有 +

+ +

+ +其中,fi代表了第i个神经元的传递函数,并定义W=Rij-1 (i,j=1,2,…,n)为网络的权系数矩阵.为证明连续型网络的稳定性,Hopfield定义了如下的能量函数: +

+ +

+ +其中,f-1为神经元传递函数的反函数.经过推导后得出以下两点结论:一是对于具有单调递增传递函数且对称权系数矩阵的网络来说,其能量会随着时间的变化而趋于稳定;二是当且仅当网络中所有神经元的输出不再随时间变化时,则可以认为网络的能量保持不变。在将网络用于求解诸如旅行商的组合优化问题时,Hopfield将优化的目标函数转化为网络的能量函数,对应地将待求解问题的变量用网络中神经元的状态来表示。由这样的表示方式可知当网络的能量衰减到稳定值时,问题的最优解也随之求出。 + +Hopfield网络按网络输入和输出的数字形式不同可分为离散型和连续型两种网络,即:离散型Hopfield神经网络----DHNN(Discrete Hopfield Neural Network);连续型Hopfield神经网络----CHNN(ContinuesHopfield Neural Network)。 + +DHNN结构:它是一种单层全反馈网络,共有n个神经元。每个神经元都通过连接权接收所有其它神经元输出反馈来的信息,其目的是为了让任一神经元的输出能接受所有神经元输出的控制,从而使各神经元能相互制约。 + +DHNN的设计原则:吸引子的分布是由网络的权值(包括阀值)决定的,设计吸引子的核心就是如何设计一组合适的权值。为了使所设计的权值满足要求,权值矩阵应符合以下要求:(1)为保证异步方式工作时网络收敛,W应为对称阵;(2)为保证同步方式工作时网络收敛,W应为非负定对称阵;(3)保证给定的样本是网络的吸引子,并且要有一定的吸引域。 + +具体设计时,可以采用不同的方法:(1)联立方程法;(2)外积和法。 + +CHNN:在连续型Hopfield神经网络中,所有神经元都随时间t并行更新,网络状态随时间连续改变。 + +#### 优缺点 + +Hopfield网络是一种非线性的动力网络,可通过反复的网络动态迭代来求解问题,这是符号逻辑方法所不具有的特性。在求解某些问题时,其求解问题的方法与人类求解问题的方法很相似,虽然所求得的解不是最佳解,但其求解速度快,更符合人们日常解决问题的策略。 + +Hopfield神经网络的提出就是与其实际应用密切相关。具有联系记忆的功能,具体为: + +联想记忆:输入--输出模式的各元素之间,并不存在一对一的映射关系,输入--输出模式的维数也不要求相同;联想记忆时,只给出输入模式部分信息,就能联想出完整的输出模式。即具有容错性。 + +#### 应用领域 +```python +import numpy as np +from random import randint, shuffle + +class InvalidWeightsException(Exception): + pass + + +class InvalidNetworkInputException(Exception): + pass + +class HopfieldNetwork(object): + def __init__(self, num_inputs): + self._num_inputs = num_inputs + self._weights = np.random.uniform(-1.0, 1.0, (num_inputs, num_inputs)) + + def set_weights(self, weights): + """Update the weights array""" + if weights.shape != (self._num_inputs, self._num_inputs): + raise InvalidWeightsException() + + self._weights = weights + + def get_weights(self): + """Return the weights array""" + return self._weights + + def calculate_neuron_output(self, neuron, input_pattern): + """Calculate the output of the given neuron""" + num_neurons = len(input_pattern) + + s = 0.0 + + for j in range(num_neurons): + s += self._weights[neuron][j] * input_pattern[j] + + return 1.0 if s > 0.0 else -1.0 + + def run_once(self, update_list, input_pattern): + """Iterate over every neuron and update it's output""" + result = input_pattern.copy() + + changed = False + for neuron in update_list: + neuron_output = self.calculate_neuron_output(neuron, result) + + if neuron_output != result[neuron]: + result[neuron] = neuron_output + changed = True + + return changed, result + + def run(self, input_pattern, max_iterations=10): + """Run the network using the input data until the output state doesn't change + or a maximum number of iteration has been reached.""" + iteration_count = 0 + + result = input_pattern.copy() + + while True: + update_list = range(self._num_inputs) + shuffle(update_list) + + changed, result = self.run_once(update_list, result) + + iteration_count += 1 + + if not changed or iteration_count == max_iterations: + return result +``` + + + diff --git a/assets/src/ANN/ANN.0.9.md b/assets/src/ANN/ANN.0.9.md new file mode 100644 index 00000000..4702774a --- /dev/null +++ b/assets/src/ANN/ANN.0.9.md @@ -0,0 +1,433 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! + +机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 + +(1)监督学习:从给定的训练数据集中学习出一个函数,当新的数据输入时,可以根据函数预测相应的结果。监督学习的训练集要求是包括输入和输出,也就是特征和目标。训练集中的目标是有标注的。如今机器学习已固有的监督学习算法有可以进行分类的,例如贝叶斯分类,SVM,ID3,C4.5以及分类决策树,以及现在最火热的人工神经网络,例如BP神经网络,RBF神经网络,Hopfield神经网络、深度信念网络和卷积神经网络等。人工神经网络是模拟人大脑的思考方式来进行分析,在人工神经网络中有显层,隐层以及输出层,而每一层都会有神经元,神经元的状态或开启或关闭,这取决于大数据。同样监督机器学习算法也可以作回归,最常用便是逻辑回归。 + +(2)无监督学习:与有监督学习相比,无监督学习的训练集的类标号是未知的,并且要学习的类的个数或集合可能事先不知道。常见的无监督学习算法包括聚类和关联,例如K均值法、Apriori算法。 + +(3)半监督学习:介于监督学习和无监督学习之间,例如EM算法。 + +如今的机器学习领域主要的研究工作在三个方面进行:1)面向任务的研究,研究和分析改进一组预定任务的执行性能的学习系统;2)认知模型,研究人类学习过程并进行计算模拟;3)理论的分析,从理论的层面探索可能的算法和独立的应用领域算法。 + +#### 径向基函数网络(Radial Basis Function Network) + +在数学建模领域,径向基函数网络(Radial basis function network,缩写 RBF network)是一种使用径向基函数作为激活函数的人工神经网络。 +RBF神经网络是基于人脑的神经元细胞对外界反应的局部性而提出的新颖的、有效的前馈式神经网络,具有良好的局部逼近特性。它的数学理论基础成形于1985年由Powell首先提出的多变量插值的径向基函数,1988年被Broomhead和Lowe应用到神经网络设计领域,最终形成了RBF神经网络。 +径向基函数网络的输出是输入的径向基函数和神经元参数的线性组合。径向基函数网络具有多种用途,包括包括函数近似法、时间序列预测、分类和系统控制。他们最早由布鲁姆赫德(Broomhead)和洛维(Lowe)在1988年建立。 + +RBF神经网络是一种三层前馈神经网络。第一层为输入层,由信号源节点构成,将网络与外界环境连结起来,节点数由输入信号的维数确定;第二层为隐含层(径向基层),其节点由径向基函数构成,实现输入空间到隐层空间的非线性变换;第三层为输出层(线性层),对输入模式做出响应,其节点由隐含层节点给出的基函数的线性组合来计算。 + +

+ +

+ +径向基神经网络的激活函数采用径向基函数,通常定义为空间任一点到某一中心之间欧氏距离的单调函数。径向基神经网络的激活函数是以输入向量和权值向量之间的距离 为自变量的。径向神经网络的激活函数一般表达式为 +

+ +

+ +随着权值和输入向量之间距离的减少,网络输出是递增的,当输入向量和权值向量一致时,神经元输出1。b为阈值,用于调整神经元的灵敏度。利用径向基神经元和线性神经元可以建立广义回归神经网络,该种神经网络适用于函数逼近方面的应用;径向基神经元和竞争神经元可以组件概率神经网络,此种神经网络适用于解决分类问题。输出层和隐含层所完成的任务是不同的,因而它们的学习策略也不相同。输出层是对线性权进行调整,采用的是线性优化策略,因而学习速度较快。而隐函数是对激活函数(格林函数或高斯函数,一般为高斯函数)的参数进行调整,采用的是非线性优化策略,因而学习速度较慢。 + +尽管RBF网络的输出是隐单元输出的线性加权和,学习速度加快,但并不等于径向基神经网络就可以取代其他前馈网络。这是因为径向神经网络很可能需要比BP网络多得多的隐含层神经元来完成工作。 + +径向基神经网络中需要求解的参数有三个基函数的中心、方差以及隐含层到输出层的权值。根据径向基函数中心选取方法的不同,RBF网络有多种学习方法。下面介绍自组织选取中心的RBF神经网络学习法。此方法由两个阶段组成: + +* 自组织学习阶段,此阶段为无监督学习过程,求解隐含层基函数的中心与方差。 + +* 监督学习阶段,此阶段求解隐含层到输出层之间的权值。 + +径向基神经网络中常用的径向基函数是高斯函数,因此径向基神经网络的激活函数可表示为: +

+ +

+ +由此可得,径向基神经网络的结构可得到网络的输出为: + +

+ +

+ +其中为第p个输入样本。h为隐含层的结点数。 + +如果d是样本的期望输出值,那么基函数的方差可表示为: +

+ +

+ +基于K-均值聚类方法求取基函数中心c: + +* 网络初始化 随机选取h个训练样本作为聚类中心 +* 将输入的训练样本集合按最近邻规则分组,按照 与中心为之间的欧式距离将分配到输入样本的各个聚类集合之中。 +* 重新调整聚类中心 计算各个聚类集合 中训练样本的平均值,即新的聚类中心, 如果新的聚类中心不再发生变化,所得到的就是RBF神经网络最终的基函数中心,否则返回上一步进行下一轮求解. + +求解方差: + +* 该RBF神经网络的基函数为高斯函数,因此方差可由下式求解得出: +

+ +

+ +其中是所选取中心之间的最大距离. + +计算隐含层和输出层之间的权值: + +* 用最小二乘法直接计算得到: +

+ +

+ + +#### 应用示例 +```python +from __future__ import division + +import random +import pylab +import math + + +SAMPLES = 75 +EPOCHS = 100 + +TESTS = 12 +RUNS = 3 +MOD = 12 + + +def h(x): + """Function to approximate: y = 0.5 + 0.4sin(2πx).""" + # note: pylab.sin can accept a numpy.ndarray, but math.sin cannot + return 0.5 + 0.4*pylab.sin(pylab.pi*2*x) + +def noise(x): + """Add uniform noise in intervale [-0.1, 0.1].""" + return x + random.uniform(-0.1, 0.1) + +def sample(n): + """Return sample of n random points uniformly distributed in [0, 1].""" + a = [random.random() for x in range(n)] + a.sort() + return a + +def gaussian(radial, x): + """Return gaussian radial function. + Args: + radial: (num, num) of gaussian (base, width^2) pair + x: num of input + Returns: + num of gaussian output + """ + base, width2 = radial + power = -1 / width2 / 2 * (x-base)**2 + y = pylab.exp(power) + return y + + +def output(radials, weights, x): + """Return set of linearly combined gaussian functions. + Args: + radials: [(num, num) of (base, width^2) pairs + weights: [num] of radial weights, |weights| -1 = |radials| + x: num of input + Returns: + num of linear combination of radial functions. + """ + y = 0 + for radial, weight in zip(radials, weights[:-1]): + y += gaussian(radial, x) * weight + # add bias + y += weights[-1] + return y + + +def update_weights(eta, weights, radials, x, y, d): + """Update weight vector. + Returns: + [num] of updated weight vector, len = |weights| + """ + new_weights = [] + err = d-y + for radial, weight in zip(radials, weights[:-1]): + w = weight + (eta * err * gaussian(radial, x)) + new_weights.append(w) + # update bias + w = weights[-1] + (eta * err) + new_weights.append(w) + return new_weights + + +def k_means(input, k): + """Return n Gaussian centers computed by K-means algorithm from sample x. + Args: + input: [num] of input vector + k: int number of bases, <= |set(input)| + Returns: + [(num, [num])] k-size list of (center, input cluster) pairs. + """ + # initialize k bases as randomly selected unique elements from input + bases = random.sample(set(input), k) + + # place all inputs in the first cluster to initialize + clusters = [ (x, 0) for x in input ] + updated = True + + while(updated): + updated=False + for i in range(0, len(clusters)): + x, m = clusters[i] + distances = [(abs(b-x), j) for j, b in enumerate(bases)] + d, j = min(distances) + # update to move x to a new base cluster + if m != j: + updated = True + clusters[i] = (x, j) + + # update bases + if updated: + base_sums = [ [0,0] for s in range(k)] + for x, m in clusters: + base_sums[m][0] += x + base_sums[m][1] += 1 + # check for divide by zero errors + new_bases = [] + for s, n in base_sums: + # avoid rare edge case, <1% @ n=25 + # division by zero: select a new base from input + if n == 0: + base = random.sample(set(input), 1)[0] + else: + base = s / n + new_bases.append(base) + bases = new_bases + + # generate returned value + response = [ (b, []) for b in bases ] + for x, m in clusters: + response[m][1].append(x) + + return response + + +def variance_width(k_meaned_x): + """Return mean, variance pairs computed from k_means(x, k). + Args: + k_meaned_x: [(num, [num])] of (base, input cluster) pairs + Returns: + [(num, num)] of (center, width^2) pairs. + """ + response = [] + for base, cluster in k_meaned_x: + if len(cluster) > 1: + var = sum([(base-x)**2 for x in cluster]) / len(cluster) + # this actually produces excellent approximations + # var = sum([(base-x)**2 for x in cluster]) + else: + var = None + response.append((base, var)) + + # set |cluster| widths to mean variance of other clusters + vars = [v for b, v in response if v] + if len(vars) == 0: + raise Exception("No variance: cannot compute mean variance") + else: + var_mean = sum(vars) / len(vars) + + for i in range(len(response)): + base, var = response[i] + if not var: + response[i] = (base, var_mean) + + return response + + +def shared_width(k_meaned_x): + """Return shared gaussian widths computed from k_means(x, k). + Args: + k_meaned_x: [(num, [num])] of (base, input cluster) pairs + Returns: + [(num, num)] of (center, width^2) pairs. + """ + assert(len(k_meaned_x) > 1) + # ignore clusters + bases = [b for b, cluster in k_meaned_x] + # compute distances between adjancent bases + s_bases = bases[:] + s_bases.sort() + distances = map(lambda p: abs(p[0]-p[1]), zip(s_bases, s_bases[1:])) + max_d = max(distances) + sigma_sq = (max_d / 2**0.5)**2 + # map to outputs + response = [(b, sigma_sq) for b in bases] + return response + + +def plot_instance(name, x, ideal_y, measured_y, trained_y, new_x, estimated_y): + """Plot function graph, save to file. + Effect: saves png file of plot to currect directory. + NOTE: use local graph variable + Args: + name: str of plot name, used in file name like "name.png" + x: [num] input vector + ideal_y: [num] ideal output vector + measured_y: [num] noisy output vector + trained_y: [num] trained output vector + new_x: [num] new input sample not used in training + estimated_y: [num] estimated output from trained RBN + """ + # plot graph + pylab.rc('text', usetex=True) + pylab.rc('font', family='serif') + pylab.xlabel('$x$') + pylab.ylabel('$y = 0.5 + 0.4\sin(2 \pi x)$') + pylab.title('RBF Network: %s' % name) + pylab.plot(x, ideal_y, 'g', label="Ideal") + pylab.plot(x, measured_y, 'bo', label="Measured") + pylab.plot(x, trained_y, 'y', label="Trained") + pylab.plot(new_x, estimated_y, 'r', label="Generalized") + pylab.legend() + # pylab.grid(True) + filename = name + filename = filename.replace(' ', '_').replace('\\', '').replace('$', '') + filename = filename.replace(',', '') + # save figure + pylab.savefig("%s.png" % filename) + # clear this figure + # note: use http://matplotlib.sourceforge.net/users/artists.html#artist-tutorial + # in the future + pylab.clf() + pylab.cla() + + +def error(actual, expected): + """Return error from actual to expected. + Args + actual: [num] of sampled output + expected: [num] of expected ouput, ||expected|| = ||actual|| + Returns: + num of average distance between actual and expected + """ + sum_d = 0 + for a, e in zip(actual, expected): + sum_d += abs(a-e) + err = sum_d / len(expected) + return err + + +def run_test(eta, k, tests=TESTS, runs=RUNS, f_width=variance_width, graph_mod=MOD): + """Run an RBF training test set; plot, return errors from results. + Args: + eta: num of training rate + k: num of bases + tests: num of sample set iterations + runs: num of network generation iterations + f_width: function to generate radial widths + graph_mod: num of after how many iterations to plot a graph + Returns: + {str: [num]} such that n = (tests*runs) and: + "sample_err": [num] of n sampling errors + "train_err": [num] of n training errors + "gen_err": [num] of n estimation errors + """ + + results = { + "sample_err": [], + "train_err": [], + "gen_err": [], + } + + f_name = f_width.__name__.capitalize().split('_')[0] + for test in range(1,tests+1): + + print "## K=%d, eta=%.2f, Test=%d" % (k, eta, test) + + # compute input samples + input = sample(SAMPLES) + test_input = sample(SAMPLES) + # compute desired and ideal outputs + ideal_y = map(h, input) + test_ideal_y = map(h, test_input) + measured_y = map(noise, ideal_y) + + # estimate each sample three times + for run in range(1,runs+1): + # initialize K radials + radials = f_width(k_means(input, k)) + # k+1 weights, last weight is bias + weights = [random.uniform(-0.5, 0.5) for x in range(k+1)] + # train all epochs + for i in range(EPOCHS): + # train one epoch + for x, d in zip(input, measured_y): + y = output(radials, weights, x) + weights = update_weights(eta, weights, radials, x, y, d) + + # examine results + trained_y = map(lambda x: output(radials, weights, x), input) + estimated_y = map(lambda x: output(radials, weights, x), test_input) + sample_err = error(measured_y, ideal_y) + train_err = error(trained_y, measured_y) + gen_err = error(estimated_y, test_ideal_y) + + # save results + results["sample_err"].append(sample_err) + results["train_err"].append(train_err) + results["gen_err"].append(gen_err) + +# print "Run: %d, Sample: %.4f, Train: %.4f, General: %.4f" \ +# % (run, sample_err, train_err, gen_err) + + # graph some set of results + iteration = (test-1)*runs + run + if (iteration % graph_mod) == 0: +# print "Graphing Test=%d, Run=%d" % (test, run) + name = "%s $K=%d, \eta =%.2f, E=%.3f$ (%d-%d)" % \ + (f_name, k, eta, gen_err, test, run) + plot_instance( \ + name, input, ideal_y, measured_y, trained_y, test_input, estimated_y) + return results + + +def stats(values): + """Return tuple of common statistical measures. + Returns: + (num, num, num, num) as (mean, std, min, max) + """ + mean = sum(values) / len(values) + sum_sqs = reduce(lambda x, y: x + y*y, values) + var = sum([(mean-x)**2 for x in values]) / len(values) + var = (sum_sqs - len(values)*mean**2) / len(values) + std = var**0.5 + min_var, max_var = min(values), max(values) + return (mean, std, min_var, max_var) + + +def main(): + random.seed() + + # need final report + for f_width in (variance_width, shared_width): + for eta in (0.01, 0.02): + for k in (5, 10, 15, 20, 25): + + print "" + print "BEGIN PARAMETER TEST SUITE" + print "K=%d, eta=%.2f, f_width=%s, Tests=%d, Runs=%d" % \ + (k, eta, f_width.__name__, TESTS, RUNS) + print "+++++++++++++++++++++++++++++++++++" + r = run_test(k=k, eta=eta, f_width=f_width) + print "+++++++++++++++++++++++++++++++++++" + print "RESULTS" + print "K=%d, eta=%.2f, f_width=%s, Tests=%d, Runs=%d" % \ + (k, eta, f_width.__name__, TESTS, RUNS) + for name, values in r.items(): + print name + print "mean=%.4f, std=%.4f, min=%.4f, max=%.4f" % \ + stats(values) + print "+++++++++++++++++++++++++++++++++++" + + +if __name__ == "__main__": + main() +``` diff --git a/assets/src/ARL/ARL.0.1.md b/assets/src/ARL/ARL.0.1.md new file mode 100644 index 00000000..fcc97fd9 --- /dev/null +++ b/assets/src/ARL/ARL.0.1.md @@ -0,0 +1,26 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 关联规则学习(Association Rule Learning) + +关联规则学习(英语:Association rule learning)是一种在大型数据库中发现变量之间的有趣性关系的方法。它的目的是利用一些有趣性的量度来识别数据库中发现的强规则。基于强规则的概念,Rakesh Agrawal等人引入了关联规则以发现由超市的POS系统记录的大批交易数据中产品之间的规律性。例如,从销售数据中发现的规则 {洋葱, 土豆}→{汉堡} 会表明如果顾客一起买洋葱和土豆,他们也有可能买汉堡的肉。此类信息可以作为做出促销定价或产品植入等营销活动决定的根据。除了上面购物篮分析中的例子以外, 关联规则如今还被用在许多应用领域中,包括网络用法挖掘、入侵检测、连续生产及生物信息学中。与序列挖掘相比,关联规则学习通常不考虑在事务中、或事务间的项目的顺序。 + + +根据关联规则所处理的值的类型 + +如果考虑关联规则中的数据项是否出现,则这种关联规则是布尔关联规则(Boolean association rules)。例如上面的例子。 +如果关联规则中的数据项是数量型的,这种关联规则是数量关联规则(quantitative association rules)。例如年龄("20-25")=>购买("网球拍"),年龄是一个数量型的数据项。在这种关联规则中,一般将数量离散化(discretize)为区间。 +根据关联规则所涉及的数据维数 + +如果关联规则各项只涉及一个维,则它是单维关联规则(single-dimensional association rules),例如购买("网球拍")=>购买("网球")只涉及“购买”一个维度。 +如果关联规则涉及两个或两个以上维度,则它是多维关联规则(multi-dimensional association rules),例如年龄("20-25")=>购买("网球拍")涉及“年龄”和“购买”两个维度。 +根据关联规则所涉及的抽象层次 + +如果不涉及不同层次的数据项,得到的是单层关联规则(single-level association rules)。 +在不同抽象层次中挖掘出的关联规则称为广义关联规则(generalized association rules)。例如年龄("20-25")=>购买("HEAD网球拍")和年龄("20-25") =>购买("网球拍")是广义关联规则,因为"HEAD网球拍"和"网球拍"属于不同的抽象层次。 + +关联规则学习(Association Rule Learning) 的应用算法: +* 先验算法(Apriori Algorithm) +* Eclat算法(Eclat Algorithm) +* FP-growth算法(FP-Growth Algorithm) diff --git a/assets/src/ARL/ARL.0.2.md b/assets/src/ARL/ARL.0.2.md new file mode 100644 index 00000000..d5a50cf1 --- /dev/null +++ b/assets/src/ARL/ARL.0.2.md @@ -0,0 +1,146 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 先验算法(Apriori Algorithm) +Apriori算法是一种挖掘关联规则的频繁项集算法,其核心思想是通过候选集生成和情节的向下封闭检测两个阶段来挖掘频繁项集。 Apriori(先验的,推测的)算法应用广泛,可用于消费市场价格分析,猜测顾客的消费习惯;网络安全领域中的入侵检测技术;可用在用于高校管理中,根据挖掘规则可以有效地辅助学校管理部门有针对性的开展贫困助学工作;也可用在移动通信领域中,指导运营商的业务运营和辅助业务提供商的决策制定。 + +在计算机科学以及数据挖掘领域中, 先验算法是关联式规则中的经典算法之一。先验算法的设计目的是为了处理包含交易信息内容的数据库(例如,顾客购买的商品清单,或者网页常访清单。)而其他的算法则是设计用来寻找无交易信息(如Winepi算法和Minepi算法)或无时间标记(如DNA测序)的数据之间的联系规则。 + +在关联式规则中,一般对于给定的项目集合(例如,零售交易集合,每个集合都列出的单个商品的购买信息),算法通常尝试在项目集合中找出至少有C个相同的子集。先验算法采用自底向上的处理方法,即频繁子集每次只扩展一个对象(该步骤被称为候选集产生),并且候选集由数据进行检验。当不再产生符合条件的扩展对象时,算法终止。 + +先验算法采用广度优先搜索算法进行搜索并采用树结构来对候选项目集进行高效计数。它通过长度为k-1的候选项目集来产生长度为k的候选项目集,然后从中删除包含不常见子模式的候选项。根据向下封闭性引理,该候选项目集包含所有长度为k的频繁项目集。之后,就可以通过扫描交易数据库来决定候选项目集中的频繁项目集。 + +虽然先验算法具有显著的历史地位,但是其中的一些低效与权衡弊端也进而引致了许多其他的算法的产生。候选集产生过程生成了大量的子集(先验算法在每次对数据库进行扫描之前总是尝试加载尽可能多的候选集)。并且自底而上的子集浏览过程(本质上为宽度优先的子集格遍历)也直到遍历完所有个可能的子集之后才寻找任意最大子集S。 + +Apriori算法中的一些低效与权衡弊端也进而引致了许多其他的算法的产生,例如FP-growth算法。候选集产生过程生成了大量的子集(先验算法在每次对数据库进行扫描之前总是尝试加载尽可能多的候选集)。并且自底而上的子集浏览过程(本质上为宽度优先的子集格遍历)也直到遍历完所有 个可能的子集之后才寻找任意最大子集S。 + + +#### 应用示例 +```python + +class Apriori(): + def __init__(self): + pass + ''' + 关联分析的目标包括两项:发现频繁项集和发现关联规则 + ''' + + ''' + 频繁项集: + 对于包含N种物品的数据集共有2^N-1种项集组合。 + 支持度(support) + 一个项集的支持度被定义为数据集中包含该项集的记录所占的比例。 + Apriori算法:如果某个项集是频繁的,那么它的所有子集也是频繁的。 + 如果一个项集是非频繁集,那么它的所有超集也是非频繁集。 + ''' + def _createC1(self, dataSet): + C1 = [] + for transaction in dataSet: + for item in transaction: + if [item] not in C1: + C1.append([item]) + C1.sort() + return map(frozenset, C1) # use frozen set so we can use it as a key in a dict + + def _scanD(self, D, Ck, minSupport=0.5): + ssCnt = {} + for tid in D: + for can in Ck: + if can.issubset(tid): + if can in ssCnt: + ssCnt[can] += 1 + else: + ssCnt[can] = 1 + # if can not in ssCnt: + # ssCnt[can] = 0 + # ssCnt[can] += 1 + # print ssCnt + numItems = len(D) + retList = [] + supportK = {} + for key in ssCnt: + support = ssCnt[key]/float(numItems) # 计算支持度 + if support >= minSupport: + retList.append(key) + supportK[key] = support + return retList, supportK + + def aprioriGen(self, Lk, k): # k>=2 + retList = [] + lenLk = len(Lk) + for i in range(lenLk): + for j in range(i+1, lenLk): + L1 = list(Lk[i])[:k-2] + L2 = list(Lk[j])[:k-2] + L1.sort() + L2.sort() + if L1 == L2: # if first k-2 elements are equal. when k is 3, {0,1},{0,2},{1,2}→{0,1}U{0,2}→{0,1,2} + retList.append(Lk[i] | Lk[j]) + return retList + + def apriori(self, dataSet, minSupport=0.5): # minSupport 最小支持度 + D = map(set, dataSet) # 转换为集合set + C1 = self._createC1(dataSet) # 创建C1,转换为集合frozenset + L1, supp1 = self._scanD(D, C1, minSupport) # 基于C1和minSupport创建L1 + L = [] + supportData = {} + L.append(L1) + supportData.update(supp1) + k = 2 + while len(L[k-2]) > 1: + Ck = self.aprioriGen(L[k-2], k) # 创建Ck + Lk, suppK = self._scanD(D, Ck, minSupport) # 基于Ck和minSupport创建Lk + L.append(Lk) + supportData.update(suppK) + k += 1 + return L, supportData + + ''' + 关联规则:→ + 可信度(confidence):也称置信度 + 可信度(尿布→葡萄酒) = 支持度({尿布,葡萄酒})/支持度({尿布}) + 如果某条规则并不满足最小可信度要求,那么该规则的所有子集也不会满足最小可信度要求。 + ''' + + def _calcConf(self, freqSet, H, supportData, brl, minConf=0.7): # H为出现在右部的规则列表,如{0},{1} + prunedH = [] + for conseq in H: + conf = supportData[freqSet]/supportData[freqSet-conseq] # 计算可信度 + if conf >= minConf: + print freqSet-conseq, '-->', conseq, 'conf:', conf + brl.append((freqSet-conseq, conseq, conf)) + prunedH.append(conseq) + return prunedH + + def _rulesFromConseq(self, freqSet, H, supportData, brl, minConf=0.7): # H为出现在右部的规则列表,如{0},{1} + m = len(H[0]) + if len(freqSet) > (m+1): + Hmp1 = self.aprioriGen(H, m+1) # 合并规则 + Hmp = self._calcConf(freqSet, Hmp1, supportData, brl, minConf) # Hmp为出现在右部的合并规则列表,如{0,1} + if len(Hmp) > 1: # 如果规则列表长度大于1,则进一步合并 + self._rulesFromConseq(freqSet, Hmp, supportData, brl, minConf) + + def generateRules(self, L, supportData, minConf=0.7): # minConf 最小可信度 + bigRuleList = [] + for i in range(1, len(L)): # 从包含两个或者更多元素的项集开始规则构建过程 + for freqSet in L[i]: + H1 = [frozenset([item]) for item in freqSet] # 构建只包含单个元素的列表,即出现在规则右部的规则列表,如{0},{1} + if i > 1: + self._rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf) # 生成候选规则 + else: + self._calcConf(freqSet, H1, supportData, bigRuleList, minConf) # 对规则进行评估 + return bigRuleList + +def loadDataSet(): + return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]] + +if __name__ == '__main__': + dataSet = loadDataSet() + ap = Apriori() + L, suppData = ap.apriori(dataSet, minSupport=0.5) + print L + print suppData + rules = ap.generateRules(L, suppData, minConf=0.6) + print rules +``` diff --git a/assets/src/ARL/ARL.0.3.md b/assets/src/ARL/ARL.0.3.md new file mode 100644 index 00000000..9ab36594 --- /dev/null +++ b/assets/src/ARL/ARL.0.3.md @@ -0,0 +1,138 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### Eclat算法(Eclat Algorithm) +Eclat算法是一种深度优先算法,采用垂直数据表示形式,在概念格理论的基础上利用基于前缀的等价关系将搜索空间(概念格)划分为较小的子空间(子概念格)。 + +#### Eclat算法原理 +* 垂直数据表示 + +支持度的计算需要访问数据库。在大多数算法中,考虑数据库中事务(即记录)的表示形式。从概念上讲,这样的数据库可以用一个二进制的二维矩阵来表示,矩阵的每一行代表数据库的一条事务,每一列代表项目。 +传统的数据挖掘算法多采用水平数据表示,在水平数据表示中,数据库的一条事务由事务标识符(TID)和项目组成。事务由TID唯一标识,一条事务可以包含一个项目或多个项目。Apriori、FP?Growth等算法都是采用此种表示方法。 +定义1(Tidset)?设有项目X,包含项目X的所有事务的标识符的集合称为项目X的Tidset。在这种数据表示方法中,数据库的事务由项目和该项目的Tidset组成,该事务由项目唯一标识。Tidset垂直数据表示:数据库中的每一条记录由一个项目及其所出现过的所有事务记录的列表(即Tidset表)构成。这样使得任何一个频繁项集的支持度计数都可以通过对Tidset交集运算求得。 + +* 支持度计数方法 + +Eclat算法采用方法二计算支持度。对候选k项集进行支持度计算时,不需再次扫描数据库,仅在一次扫描数据库后得到每个1项集的支持度,而候选k项集的支持度就是在对k-1项集进行交集操作后得到的该k项集Tidset中元素的个数。 + +* 概念格理论 + +Eclat算法在概念格理论的基础上,利用基于前缀的等价关系将搜索空间(概念格)划分为较小的子空间(子概念格),各子概念格采用自底向上的搜索方法独立产生频繁项集。 + +#### eclat算法不足 +在Eclat算法中,它由2个集合的并集产生新的候选集,通过计算这2个项集的Tidset的交集快速得到候选集的支持度,因此,当Tidset的规模庞大时将出现以下问题: +* 1.求Tidset的交集的操作将消耗大量时间,影响了算法的效率; +* 2.Tidset的规模相当庞大,消耗系统大量的内存。 + + +#### 应用案例 +```python +import sys +import itertools +import math + +tidlists = {1: {}}; +min_sup = float(sys.argv[1]) +min_conf = float(sys.argv[2]) + +print('Reading dataset.') +dataset = open(sys.argv[3]) +tid = 0 +for line in dataset: + line = line.strip() + if len(line) == 0: + continue + + items = line.split(' ') + + for item in items: + item = (item,) + if item not in tidlists[1]: + tidlists[1][item] = set() + tidlists[1][item].add(tid) + + tid += 1 +dataset.close() +print('Dataset reading done.') +transactions = tid +min_sup_count = min_sup * transactions + +n_items = len(tidlists[1]) +print('Number of items: {}.'.format(n_items)) + +tidlists[1] = {k:v for k,v in tidlists[1].items() if len(v) >= min_sup_count} + +n_frequent_items = len(tidlists[1]) +print('Number of requent items: {}. Removed {}.'.format(n_frequent_items, n_items - n_frequent_items)) + +def has_same_prefix(itemset1, itemset2, n): + for i in range(0, min(len(itemset1), len(itemset2))): + if n == 0: + return True + + if itemset1[i] != itemset2[i]: + return False + n -= 1 + return n == 0 + +def eclat(): + k = 2 + while True: + print('Searching for {}-itemsets.'.format(k)) + tidlists[k] = {} + combination_counter = 0 + #n_combinations = math.factorial(len(tidlists[k-1]))/(2 * math.factorial(len(tidlists[k-1])-2)) + #print('Possible number of combinations: {}.'.format(n_combinations)) + for itemset1, itemset2 in itertools.combinations(tidlists[k-1].keys(), r=2): + combination_counter += 1 + if not has_same_prefix(itemset1, itemset2, k-2): + continue + + tidlist1, tidlist2 = tidlists[k-1][itemset1], tidlists[k-1][itemset2] + intersection = tidlist1.intersection(tidlist2) + if len(intersection) < min_sup_count: + continue + + tidlists[k][tuple(list(itemset1) + [itemset2[len(itemset2)-1]])] = intersection + + + if len(tidlists[k]) == 0: + del tidlists[k] + break + + + print('Number of frequent {}-itemsets: {}.'.format(k, len(tidlists[k]))) + k += 1 + + out = open(sys.argv[4], 'w') + # Print results + out.write('itemsets\n') + for i in range(1, k): + #print('Frequent {}-itemsets'.format(i)) + for (itemset, tidlist) in tidlists[i].items(): + out.write(' '.join(itemset1) + '\n') + out.write(str(len(tidlist)/transactions) + '\n') + + out.write('rules\n') + for i in range(1, k): + #print('Frequent {}-itemsets'.format(i)) + for (itemset, tidlist) in tidlists[i].items(): + subsets = [] + for j in range(1, len(itemset)): + subsets = subsets + list(itertools.combinations(itemset, j)) + + for subset in subsets: + difference = set(itemset).difference(subset) + confidence = len(tidlist)/len(tidlists[len(subset)][tuple(subset)]) + if confidence < min_conf: + continue + out.write(' '.join(subset) + '\n') + out.write(' '.join(difference) + '\n') + out.write(str(confidence) + '\n') + + out.close() + +eclat() + +`` diff --git a/assets/src/ARL/ARL.0.4.md b/assets/src/ARL/ARL.0.4.md new file mode 100644 index 00000000..c711da74 --- /dev/null +++ b/assets/src/ARL/ARL.0.4.md @@ -0,0 +1,370 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### FP-growth算法(FP-Growth Algorithm) +FP-growth算法是基于Apriori原理的,通过将数据集存储在FP(Frequent Pattern)树上发现频繁项集,但不能发现数据之间的关联规则。FP-growth算法只需要对数据库进行两次扫描,而Apriori算法在求每个潜在的频繁项集时都需要扫描一次数据集,所以说Apriori算法是高效的。其中算法发现频繁项集的过程是: +* 1.构建FP树; +* 2.从FP树中挖掘频繁项集。 + +#### 构建FP树 +FP表示的是频繁模式,其通过链接来连接相似元素,被连起来的元素可以看成是一个链表。将事务数据表中的各个事务对应的数据项按照支持度排序后,把每个事务中的数据项按降序依次插入到一棵以 NULL为根节点的树中,同时在每个结点处记录该结点出现的支持度。 + +FP-growth算法的流程为:首先构造FP树,然后利用它来挖掘频繁项集。在构造FP树时,需要对数据集扫描两边,第一遍扫描用来统计频率,第二遍扫描至考虑频繁项集。下面举例对FP树加以说明。 + +假设存在的一个事务数据样例为,构建FP树的步骤如下: + +| 事务ID | 事务中的元素 | +| ------ | --- | +| 001 | r,z,h,j,p | +| 002 |z,y,x,w,v,u,t,s| +| 003 | z | +| 004 | r,x,n,o,s | +| 005 | y,r,x,z,q,t,p | +| 006 | y,z,x,e,q,s,t,m| + + 结合Apriori算法中最小支持度的阈值,在此将最小支持度定义为3,结合上表中的数据,那些不满足最小支持度要求的将不会出现在最后的FP树中,据此构建FP树,并采用一个头指针表来指向给定类型的第一个实例,快速访问FP树中的所有元素,构建的带头指针的FP树如下: +

+ +

+ +结合绘制的带头指针表的FP树,对表中数据进行过滤,排序如下: + +| 事务ID | 事务ID | 过滤和重排序后的事务 | +| --- | --- | --- | +| 001 | r,z,h,j,p | z,r| +| 002 |z,y,x,w,v,u,t,s|z,x,y,s,t| +| 003 | z |z| +| 004 | r,x,n,o,s |x,s,r| +| 005 | y,r,x,z,q,t,p |z,x,y,r,t| +| 006 | y,z,x,e,q,s,t,m|z,x,y,s,t| + + + +在对数据项过滤排序了之后,就可以构建FP树了,从NULL开始,向其中不断添加过滤排序后的频繁项集。过程可表示为: +

+ +

+ +因而我们可以实现FP树的构建,我们知道,在第二次扫描数据集时会构建一棵FP树,并采用一个容器来保存树。首先创建一个类来保存树的每一个节点: +```python +from numpy import * + +class treeNode: + def __init__(self, nameValue, numOccur, parentNode): + self.name = nameValue + self.count = numOccur + self.nodeLink = None + self.parent = parentNode #needs to be updated + self.children = {} + + def inc(self,numOccur): + self.count += numOccur + + def disp(self,ind = 1): + print ' '*ind,self.name,' ',self.count + for child in self.children.values(): + child.disp(ind+1) +''' +#test +rootNode = treeNode('pyramid',9,None) +rootNode.children['eye'] = treeNode('eye',13,None) +a = rootNode.disp() +print a +''' +``` + +

+ +

+ +这样,FP树对应的数据结构就建好了,现在就可以构建FP树了,FP树的构建函数如下: + +```python +#FP构建函数 +def createTree(dataSet,minSup = 1): + headerTable = {} + for trans in dataSet: + for item in trans: + headerTable[item] = headerTable.get(item,0) + dataSet[trans]#记录每个元素项出现的频度 + for k in headerTable.keys(): + if headerTable[k] < minSup: + del(headerTable[k]) + freqItemSet = set(headerTable.keys()) + if len(freqItemSet) == 0:#不满足最小值支持度要求的除去 + return None,None + for k in headerTable: + headerTable[k] = [headerTable[k],None] + retTree = treeNode('Null Set',1,None) + for tranSet,count in dataSet.items(): + localD = {} + for item in tranSet: + if item in freqItemSet: + localD[item] = headerTable[item][0] + if len(localD) > 0: + orderedItems = [v[0] for v in sorted(localD.items(),key = lambda p:p[1],reverse = True)] + updateTree(orderedItems,retTree,headerTable,count) + return retTree,headerTable + +def updateTree(items, inTree, headerTable, count): + if items[0] in inTree.children: + inTree.children[items[0]].inc(count) + else: + inTree.children[items[0]] = treeNode(items[0], count, inTree) + if headerTable[items[0]][1] == None: + headerTable[items[0]][1] = inTree.children[items[0]] + else: + updateHeader(headerTable[items[0]][1], inTree.children[items[0]]) + if len(items) > 1: + updateTree(items[1::], inTree.children[items[0]], headerTable, count) + +def updateHeader(nodeToTest, targetNode): + while (nodeToTest.nodeLink != None): + nodeToTest = nodeToTest.nodeLink + nodeToTest.nodeLink = targetNode +``` + +在应用示例之前还需要一个真正的数据集,结合之前的数据自定义数据集: +```python +def loadSimpDat(): + simpDat = [['r', 'z', 'h', 'j', 'p'], + ['z', 'y', 'x', 'w', 'v', 'u', 't', 's'], + ['z'], + ['r', 'x', 'n', 'o', 's'], + ['y', 'r', 'x', 'z', 'q', 't', 'p'], + ['y', 'z', 'x', 'e', 'q', 's', 't', 'm']] + return simpDat + +def createInitSet(dataSet): + retDict = {} + for trans in dataSet: + retDict[frozenset(trans)] = 1 + return retDict +``` +结果: +```python +simpDat = loadSimpDat() +initSet = createInitSet(simpDat) +myFPtree,myHeaderTab = createTree(initSet,3) +a = myFPtree.disp() +print a +``` +这样就构建了FP树,接下来就是使用它来进行频繁项集的挖掘。 + +#### 从FP树中挖掘频繁项集 +在构建了FP树之后,就可以抽取频繁项集了,这里的思想和Apriori算法大致类似,首先从氮元素项集合开始,然后在此基础上逐步构建更大的集合。大致分为三个步骤: + +* 1.从FP树中获得条件模式基; +* 2.利用条件模式基,构建一个条件FP树; +* 3.迭代重复1和2,直到树包含一个元素项为止。 +首先,获取条件模式基。条件模式基是以所查找元素项为结尾的路径集合,表示的是所查找的元素项与树根节点之间的所有内容。结合构建FP树绘制的图,r的前缀路径就是{x,s}、{z,x,y}和{z},其中的每条前缀路径都与一个计数值有关,该计数值表示的是每条路径上r的数目。 +为了得到这些前缀路径,结合之前所得到的头指针表,头指针表中包含相同类型元素链表的起始指针,根据每一个元素项都可以上溯到这棵树直到根节点为止。该过程对应的如下: + +

+ +

+ +```python +def ascendTree(leafNode, prefixPath): #ascends from leaf node to root + if leafNode.parent != None: + prefixPath.append(leafNode.name) + ascendTree(leafNode.parent, prefixPath) + +def findPrefixPath(basePat, treeNode): #treeNode comes from header table + condPats = {} + while treeNode != None: + prefixPath = [] + ascendTree(treeNode, prefixPath) + if len(prefixPath) > 1: + condPats[frozenset(prefixPath[1:])] = treeNode.count + treeNode = treeNode.nodeLink + return condPats + +#test +simpDat = loadSimpDat() +initSet = createInitSet(simpDat) +myFPtree,myHeaderTab = createTree(initSet,3) +a = myFPtree.disp() +b = findPrefixPath('x',myHeaderTab['x'][1]) +print b +``` +运行示例,与所给数据一致。接下来就可以创建条件FP树了。对于每一个频繁项,都需要创建一棵条件FP树,使用刚才创建的条件模式基作为输入,采用相同的建树代码来构建树,相应的递归发现频繁项、发现条件模式基和另外的条件树。对应的递归查找频繁项集的函数如下: +```python +def mineTree(inTree, headerTable, minSup, preFix, freqItemList): + bigL = [v[0] for v in sorted(headerTable.items(), key=lambda p: p[1])]#(sort header table) + for basePat in bigL: + newFreqSet = preFix.copy() + newFreqSet.add(basePat) + freqItemList.append(newFreqSet) + condPattBases = findPrefixPath(basePat, headerTable[basePat][1]) + myCondTree, myHead = createTree(condPattBases, minSup) + if myHead != None: + mineTree(myCondTree, myHead, minSup, newFreqSet, freqItemList) +``` +结合之前的数据验证发现没有错误。 + +#### 应用示例 +```python +# -*- coding: utf-8 -* +# 树节点 +class treeNode: + def __init__(self, nameValue, numOccur, parentNode): + self.name = nameValue + self.count = numOccur # 计数值 + self.nodeLink = None # 连接相似变量 + self.parent = parentNode #needs to be updated + self.children = {} + + def inc(self, numOccur): + self.count += numOccur + + # 递归输出树节点 + def disp(self, ind=1): + print ' '*ind, self.name, ' ', self.count + for child in self.children.values(): + child.disp(ind+1) + + +# 根据 dataSet 创建 FP-growth 树 +# 参数 minSup 指的是最小支持度 +def createTree(dataSet, minSup=1): + headerTable = {} + + # 遍历所有元素项, 记录其出现次数 + # 内容类似为 {'t': 3, 'w': 1, 'v': 1, 'y': 3, 'x': 4, 'z': 5} + for trans in dataSet: + for item in trans: + headerTable[item] = headerTable.get(item, 0) + dataSet[trans] + + # 移除未达到最小支持度的元素项 + for k in headerTable.keys(): + if headerTable[k] < minSup: + del(headerTable[k]) + + freqItemSet = set(headerTable.keys()) + if len(freqItemSet) == 0: return None, None # 没有达到最小支持度的元素项, 返回 + + # 格式化后格式为: + # {'t': [3, None], 'y': [3, None], 'x': [4, None], 'z': [5, None]} + for k in headerTable: + headerTable[k] = [headerTable[k], None] + + retTree = treeNode('Null Set', 1, None) # 只包含空值的根节点 + + for tranSet, count in dataSet.items(): # count 都初始化为 1 + localD = {} + for item in tranSet: # 取满足最小支持度的元素项 + if item in freqItemSet: + localD[item] = headerTable[item][0] + + # 对每个项集中的元素项, 按支持度从大到小排序 + if len(localD) > 0: + orderedItems = [v[0] for v in sorted(localD.items(), + key=lambda p: p[1], reverse=True)] + updateTree(orderedItems, retTree, headerTable, count) # 填充树 + return retTree, headerTable # 返回树与各个元素的头指针 + + +# 使用 items 使树生长, FP-growth 的来历 +# inTree 为树的根节点 +def updateTree(items, inTree, headerTable, count): + # 如果 items 的第一个元素是 树的第一层子节点, 则将此子节点对应的计算 加1 + if items[0] in inTree.children: + inTree.children[items[0]].inc(count) + else: # 如果此节点不存在, 则给树添加新子节点 + inTree.children[items[0]] = treeNode(items[0], count, inTree) + # 更新头指针表 + if headerTable[items[0]][1] == None: + headerTable[items[0]][1] = inTree.children[items[0]] + else: + updateHeader(headerTable[items[0]][1], inTree.children[items[0]]) + + # 对除去第一个元素之外的 items 递归建树 + if len(items) > 1: + updateTree(items[1::], inTree.children[items[0]], headerTable, count) + + +# 更新头指针链表, targetNode 接到 nodeToTest 所指链表的最后 +# 这里不用递归, 因为递归在链表长度过长时, 可能会栈溢出 +def updateHeader(nodeToTest, targetNode): + while (nodeToTest.nodeLink != None): + nodeToTest = nodeToTest.nodeLink + nodeToTest.nodeLink = targetNode + + +# 迭代上溯整棵树 +# 即将叶节点到根节点的所有元素都存到 prefixPath 中 +def ascendTree(leafNode, prefixPath): + if leafNode.parent != None: + prefixPath.append(leafNode.name) + ascendTree(leafNode.parent, prefixPath) + + +# 按给定元素项生成一个条件模式基 +# 遍历头指针链表, 对每一个元素都向根节点上溯, 记录找到的前缀式及元素出现次数 +def findPrefixPath(basePat, treeNode): #treeNode comes from header table + condPats = {} + # 遍历以 treeNode 为头节点的头指针链表 + while treeNode != None: + prefixPath = [] + ascendTree(treeNode, prefixPath) + # 保存前缀及其次数 + if len(prefixPath) > 1: + condPats[frozenset(prefixPath[1:])] = treeNode.count + treeNode = treeNode.nodeLink + return condPats + + +# 递归查找频繁项集 +# 参 freqItemList 返回频繁项集列表 +def mineTree(inTree, headerTable, minSup, preFix, freqItemList): + # 头指针按其元素项出现的频率从小到大进行排序 + bigL = [v[0] for v in sorted(headerTable.items(), key=lambda p: p[1])] + + for basePat in bigL: #start from bottom of header table + newFreqSet = preFix.copy() # 生成一个频繁项集 + newFreqSet.add(basePat) + + # 创造条件基 + freqItemList.append(newFreqSet) # 繁频项集添加到参数中, 以待最后返回 + condPattBases = findPrefixPath(basePat, headerTable[basePat][1]) + + # 创建条件 FP 树 + myCondTree, myHead = createTree(condPattBases, minSup) + + # 递归挖掘条件 FP 树 + if myHead != None: + mineTree(myCondTree, myHead, minSup, newFreqSet, freqItemList) + + +# 载入数据 +def loadSimpDat(): + simpDat = [['r', 'z', 'h', 'j', 'p'], + ['z', 'y', 'x', 'w', 'v', 'u', 't', 's'], + ['z'], + ['r', 'x', 'n', 'o', 's'], + ['y', 'r', 'x', 'z', 'q', 't', 'p'], + ['y', 'z', 'x', 'e', 'q', 's', 't', 'm']] + return simpDat + + +# 初始化每个项集的次数为 1 +def createInitSet(dataSet): + retDict = {} + for trans in dataSet: + retDict[frozenset(trans)] = 1 + return retDict + + +if __name__ == "__main__": + # 建树 + simpDat = loadSimpDat() + initSet = createInitSet(simpDat) + myFPtree, myHeaderTab = createTree(initSet, 3) # 3 为最小支持度 + myFPtree.disp() # 显示树 + + # 根据树挖掘 频繁项集 + freqItems = [] + mineTree(myFPtree, myHeaderTab, 3, set([]), freqItems) # 3 为最小支持度 + print freqItems +``` diff --git a/assets/src/ARS/ARS.md b/assets/src/ARS/ARS.md new file mode 100644 index 00000000..7e2bce45 --- /dev/null +++ b/assets/src/ARS/ARS.md @@ -0,0 +1,64 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! + +机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 + +(1)监督学习:从给定的训练数据集中学习出一个函数,当新的数据输入时,可以根据函数预测相应的结果。监督学习的训练集要求是包括输入和输出,也就是特征和目标。训练集中的目标是有标注的。如今机器学习已固有的监督学习算法有可以进行分类的,例如贝叶斯分类,SVM,ID3,C4.5以及分类决策树,以及现在最火热的人工神经网络,例如BP神经网络,RBF神经网络,Hopfield神经网络、深度信念网络和卷积神经网络等。人工神经网络是模拟人大脑的思考方式来进行分析,在人工神经网络中有显层,隐层以及输出层,而每一层都会有神经元,神经元的状态或开启或关闭,这取决于大数据。同样监督机器学习算法也可以作回归,最常用便是逻辑回归。 + +(2)无监督学习:与有监督学习相比,无监督学习的训练集的类标号是未知的,并且要学习的类的个数或集合可能事先不知道。常见的无监督学习算法包括聚类和关联,例如K均值法、Apriori算法。 + +(3)半监督学习:介于监督学习和无监督学习之间,例如EM算法。 + +如今的机器学习领域主要的研究工作在三个方面进行:1)面向任务的研究,研究和分析改进一组预定任务的执行性能的学习系统;2)认知模型,研究人类学习过程并进行计算模拟;3)理论的分析,从理论的层面探索可能的算法和独立的应用领域算法。 + + +#### 关联规则 +“关联规则”(Association Rules)是数据挖掘的主要技术之一,用于从庞大的数据库中寻找有用或有趣的模式和规则。关联规则最初产生于购物篮分析,它通过发现顾客放入其购物篮中不同商品之间的联系,分析顾客购买行为中隐含的有趣模式,从而指导销售商制订营销策略。单维关联规则特指只涉及单个属性项的关联规则。 + +设 I = { i1 , i2 ,..., im }是项的集合。设任务相关的数据D 是数据库事务的集合,其中每个事务T是项的集合,使得T ⊆ I。每一个事务有一个标识符,称作TID。设A 是一个项集,事务T 包含A当且仅当A ⊆ T。关联规则是形如A ⇒ B 的蕴涵式,其中A ⊂ I,B ⊂ I,并且A ∩ B =∅。规则A ⇒B 在事务集D 中成立,具有支持度s,其中s 是D 中事务包含A ∪ B(即A 和B 二者)的百分比。它是概率P(A ∪ B)。规则A ⇒ B 在事务集D 中具有置信度c,如果D 中包含A 的事务同时也包含B的百分比是c。这是条件概率P(B |A)。即 support (A ⇒ B ) = P(A ∪ B) confidence (A ⇒ B ) = P(B |A) + +同时满足最小支持度阈值(min_sup)和最小置信度阈值(min_conf)的规则称作强规则。为方便计,我们用0%和100%之间的值,而不是用0 到1 之间的值表示支持度和置信度。项的集合称为项集。包含k 个项的项集称为k-项集。集合{computer, financial_management_software}是一个2-项集。项集的出现频率是包含项集的事务数,简称为项集的频率、支持计数或计数。项集满足最小支持度min_sup,如果项集的出现频率大于或等于min_sup 与D 中事务总数的乘积。如果项集满足最小支持度,则称它为频繁项集。频繁k -项集的集合通常记作Lk。关联规则的挖掘是一个两步的过程: + +1. 找出所有频繁项集:根据定义,这些项集出现的频繁性至少和预定义的最小支持计数一样。 + +2. 由频繁项集产生强关联规则:根据定义,这些规则必须满足最小支持度和最小置信度。 + +如果愿意,也可以使用附加的兴趣度度量。这两步中,第二步最容易。挖掘关联规则的总体性能由第一步决定。 + + +#### 算法背景 +关联规则挖掘发现大量数据中项集之间有趣的关联或相关联系。随着大量数据不停地收集和存储,许多业界人士对于从他们的数据库中挖掘关联规则越来越感兴趣。从大量商务事务记录中发现有趣的关联关系,可以帮助许多商务决策的制定,如分类设计、交叉购物和贱卖分析。关联规则挖掘的一个典型例子是购物篮分析。该过程通过发现顾客放入其购物篮中不同商品之间联系,分析顾客的购买习惯。通过了解哪些商品频繁地被顾客同时购买,这种关联的发现可以帮助零售商制定营销策略。例如,在同一次去超级市场,如果顾客购买牛奶,他也购买面包(和什么类型的面包)的可能性有多大?通过帮助零售商有选择地经销和安排货架,这种信息可以引导销售。例如,将牛奶和面包尽可能放近一些,可以进一步刺激一次去商店同时购买这些商品。 +

+ +

+ +#### 应用领域 +关联分类算法是继贝叶斯( Bayes) 、支持向量机( SVM) 等机器学习方法之后的又一重要分类技术,广泛应用于文本分类、Web文档分类、医学图像分类。经典的关联分类算法有CBA、CMAR、CPAR; + +网络入侵检测技术作为防火墙技术强有力的助手,有效弥补了防火墙策略处理黑客攻击、信息窃取问题时出现的不足,成为网络安全监控系统可靠的保障。传统的入侵检测系统(IDS) 运用关联规则生成入侵检测标准规则库,通过判断网络数据与规则库的匹配度产生告警数据流。 + +隐私保护数据挖掘是指在数据挖掘的过程中通过采用数据干扰和查询限制的基本策略对原始数据进行保护,避免商业敏感数据、个人隐私数据泄露。 + +利用关联规则进行蛋白质结构预测,根据蛋白质序列的特点可以对这些序列数据进行量化和处理,再将关联规则算法用于序列数据集上寻找蛋白质序列中的关联关系。 + +随着遥感导航定位、地球物理等卫星数量的增加,空间地球大数据为地球科学研究带来新机遇。传统数据分析方法以统计分析、非线性拟合为主,其在处理多维、海量数据时存在明显不足。基于关联规则的挖掘模式可以揭示海洋、陆地、大气等地球数据之间的关系,从而推动全球变化、灾害科学领域的发展。 + +#### 优缺点 + +优点: + +1. 可以产生清晰有用的结果; + +2. 支持间接数据挖掘; + +3. 可以处理变长的数据; + +4. 它的计算的消耗量是可以预见的。 + +缺点: + +1. 当问题变大时,计算量增长得厉害; + +2. 难以决定正确的数据; + +3. 容易忽略稀有的数据。 diff --git a/assets/src/BA/BA.0.1.md b/assets/src/BA/BA.0.1.md new file mode 100644 index 00000000..d3ce0c98 --- /dev/null +++ b/assets/src/BA/BA.0.1.md @@ -0,0 +1,11 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 基于实例的学习算法 + +常用的基于实例的学习算法包括: +* K-邻近算法(KNN) +* 学习矢量化(LVQ) +* 自组织映射算法(SOM) +* 局部加权学习算法(LWL) diff --git a/assets/src/BA/BA.0.2.md b/assets/src/BA/BA.0.2.md new file mode 100644 index 00000000..96b068dd --- /dev/null +++ b/assets/src/BA/BA.0.2.md @@ -0,0 +1,109 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### K-近邻算法(KNN) + +K近邻算法是一种基于类比的分类方法,主要通过给定的检验组与和它相似的训练组进行比较来学习。训练组用n个属性来描述,每个元组代表n维空间上的点。当给定一个未知元组时,K最近邻分类法搜索该模式空间,找出最接近未知元组的k个训练组,并将未知元组指派到模式空间中它的k个最近邻中的多数类中。 + +k近邻(k-Nearest Neighbors)采用向量空间模型来分类,是一种常用的监督学习方法。它的工作原理为:给定测试样本,基于某种距离度量找出训练集中与其最靠近的k个训练样本,然后基于这k个“邻居”的信息来进行预测。通常,在分类任务中可使用“投票法”,即选择这k个样本中出现最多的类别标记作为预测结果;在回归任务中可使用“平均法”,即将这k个样本的实值输出标记的平均值作为预测结果;还可基于距离远近进行加权平均或加权投票,距离越近的样本权重越大。 + +k近邻没有显式的训练过程,是“懒惰学习”的代表。此类学习技术在训练阶段仅仅是把样本保存起来,训练时间开销为零,待收到测试样本后再进行处理。 + +最近邻分类器虽然简单,但它的泛化错误率不超过贝叶斯最优分类器的错误率的两倍。 + + +其中“最近邻”主要是以距离来度量的,一般使用欧几里得距离度量两个点或元组的距离,也可以使用曼哈顿距离或其他距离;欧几里得距离的主要计算公式如下: +

+ +

+ +注意:为了防止具有较大初始值域的属性比较小初始值域的属性的权重过大,在计算距离之前,需对每个属性值进行规范化。一般的规划方法有最小-最大规范化,零均值规范化,小数定标规范化等。 + +最小-最大规范化:将原始数据值映射到[0,1]空间中,假定minA和maxA分别是属性A的最小值和最大值,则规范化的公式为: +

+ +

+零均值规范化:基于属性A的均值和标准差上的规范化方法,具体计算如下: +

+ +

+ +小数定标规范化:通过移动属性A的小数点位置进行规范化,小数点的移动位数依赖于A的最大绝对值。具体计算如下:(其中j是使得MAX( v’ )<1的最小整数) +

+ +

+ +最近邻数K的确定,主要原理是选取产生最小误差率的k值。每次从k=1开始,使用检验集估计分类器的误差率;每次都允许增加一个近邻,重复该过程,选择误差率最小的k值。 + + + +#### 应用案例 + + +```python + + %matplotlib inline + import time + import numpy as np + import tensorflow as tf + import matplotlib.pyplot as plt + from sklearn.datasets.samples_generator import make_circles + + N=210 + K=2 + MAX_ITERS = 1000 + cut=int(N*0.7) + + # 生成训练和测试数据集 + data, features = make_circles(n_samples=N, shuffle=True, noise= 0.12, factor=0.4) + tr_data, tr_features= data[:cut], features[:cut] + te_data,te_features=data[cut:], features[cut:] + + fig, ax = plt.subplots() + ax.scatter(tr_data.transpose()[0], tr_data.transpose()[1], marker = 'o', s = 100, c = tr_features, cmap=plt.cm.coolwarm ) + ax.set_title('Train data') + plt.show() + + start = time.time() + + points=tf.Variable(data) + cluster_assignments = tf.Variable(tf.zeros([N], dtype=tf.int64)) + + sess = tf.Session() + sess.run(tf.initialize_all_variables()) + + te_learned_features=[] + for i, j in zip(te_data, te_features): + distances = tf.reduce_sum(tf.square(tf.sub(i , tr_data)),reduction_indices=1) + neighbor = tf.arg_min(distances,0) + + #print tr_features[sess.run(neighbor)] + te_learned_features.append(tr_features[sess.run(neighbor)]) + + accuracy = tf.reduce_mean(tf.cast(tf.equal(te_learned_features, te_features), "float")) + + fig, ax = plt.subplots() + ax.scatter(te_data.transpose()[0], te_data.transpose()[1], marker = 'o', s = 100, c = te_learned_features, cmap=plt.cm.coolwarm ) + ax.set_title('Test result') + plt.show() + + end = time.time() + print ("Found in %.2f seconds" % (end-start)) + print "Cluster assignments:", test + print "Accuracy:", sess.run(accuracy) +``` + +

+ +

+ +

+ +

+ +```python +Found in 6.73 seconds +Cluster assignments: [0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0] +Accuracy: 1.0 +``` diff --git a/assets/src/BA/BA.0.3.md b/assets/src/BA/BA.0.3.md new file mode 100644 index 00000000..758d9c33 --- /dev/null +++ b/assets/src/BA/BA.0.3.md @@ -0,0 +1,225 @@ +### Deeplearning Algorithms tutorial + +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 学习矢量化 + +学习矢量量化(Learning Vector Quantization,简称LVQ),与1988年提出的一种用于模式分类的有监督学习算法,是一种结构简单、功能强大的有监督式神经网络分类算法。典型的学习矢量量化算法有:LVQ1、LVQ2、LVQ3,其中,前两种算法应用较为广泛,尤其以LVQ2应用最为广泛和有效。 + +学习矢量量化是一种结构简单、功能强大的有监督式神经网络分类方法。作为一种最近邻原型分类器,LVQ在训练过程中通过对神经元权向量(原型向量)的不断更新,对其学习率的不断调整,能够使不同类别权向量之间的边界逐步收敛至贝叶斯分类边界。算法中,对获胜神经元(最近邻权向量)的选取是通过计算输入样本和权向量之间的距离的大小来判断的。与矢量量化(VQ)相比,LVQ最突出的特点就是其具有自适应性 + +1.向量量化 + +向量量化的思路是,将高维输入空间分成若干不同的区域,对每个区域确定一个中心向量作为聚类的中心,与其处于同一区域的输入向量可用该中心向量来代表,从而形成了以各中心向量为聚类中心的点集。在图像处理领域常用各区域中心点(向量)的编码代替区域内的点来存储或传输,从而提出了各种基于向量量化的有损压缩技术,在二维输入平面上表示的中心向量分布称为Voronoi图,如图所示: +

+ +

+ + +自组织映射可以起到聚类作用,但无法直接分类或识别,因此它只是自适应解决模式分类问题两步中的第一步。第二步:学习向量量化,采用监督机制,在训练中加入信号作为分类信息对权值进行细调,并对输出神经元预先指定其类别。 + +2.学习矢量量化网络结构与工作原理 + +学习矢量量化神经网络有三层组成:输入层,竞争层,线性输出层。 + +

+ +

+ +竞争层有m个神经元,输入层有n个神经元,两层之间完全连接。输出层每个神经元只与竞争层中的一组神经元连接,连接权重固定为1,训练过程中输入层和竞争层之间的权值逐渐被调整为聚类中心。当一个样本输入LVQ网络时,竞争层的神经元通过胜者为王学习规则产生获胜神经元,容许其输出为1,其它神经元输出为0。与获胜神经元所在组相连的输出神经元输出为1,而其它输出神经元为0,从而给出当前输入样本的模式类。将竞争层学习得到的类成为子类,而将输出层学习得到的类成为目标类。 + +3.学习矢量量化网络学习算法 + +学习矢量量化学习规则结合了竞争学习规则和有导师学习规则,所以样本集应当为{(xi,di)}。其中di为l维,对应输出层的l个神经元,它只有一个分量为1,其他分量均为0。通常把竞争层的每个神经元指定给一个输出神经元,相应的权值为1,从而得到输出层的权值。比如某LVQ网络竞争层6个神经元,输出层3个神经元,代表3类。若将竞争层的1,3指定为第一个输出神经元,2,5指定为第二个输出神经元,3,6指定为第三个输出神经元。则竞争层到输出层的权值矩阵为: + +

+ +

+ +训练前预先定义好竞争层到输出层权重,从而指定了输出神经元类别,训练中不再改变。网络的学习通过改变输入层到竞争层的权重来进行。根据输入样本类别和获胜神经元所属类别,可判断当前分类是否正确。若分类正确,则将获胜神经元的权向量向输入向量方向调整,分类错误则向相反方向调整。 + +

+ +

+ +学习矢量量化网络学习算法的步骤如下: + +* 初始化。竞争层各神经元权值向量随机赋值小随机数,确定初始学习速率和训练次数。 +* 输入样本向量。 +* 寻找激活神经元。 +* 根据分类是否正确按照不同规则调整获胜神经元的权值,当网络分类结果与教师信号一致时,向输入样本方向调整权值: + +

+ +

+ +当网络分类结果与教师信号不一致时,向输入样本反方向调整权值: + +

+ +

+ +其他非激活神经元权值保持不变。 + +* 更新学习速率 +

+ +

+* 当训练次数未达到设定的次数时,转到步骤输入样本向量输入下一个样本,重复各步骤直到达到设定训练次数为止。上述训练过程中,要保证η(t)为单调下降函数。 + +学习矢量量化网络是SOFM网络一种有监督形式的扩展,两者有效结合可更好地发挥竞争学习和有监督学习的优点。 + +连接方式: + +输入层与竞争层之间采用全连接的方式,竞争层与线性输出层之间采用部分连接的方式。竞争层神经元个数总是大于线性输出层神经元个数,每个竞争层神经元只与一个线性输出层神经元相连接且连接权值恒为1。但是,每个线性输出层神经元可以与多个竞争层神经元相连接。竞争层神经元与线性输出层神经元的值只能是1或0。 +当某个输入模式被送至网络时,与输入模式距离最近的竞争层神经元被激活,神经元的状态为“1”,而其他竞争层神经元的状态均为“0”。因此,与被激活神经元相连接的线性输出层神经元状态也为“1”,而其他线性输出层神经元的状态均为“0” + +基本步骤为: + +初始化输入层与竞争层之间的权值W_ij及学习率η(η>0)。 +将输入向量送入到输入层,并计算竞争层神经元与输入向量的距离: +。 + +#### 应用案例 + +```python + +function [dw,ls] = learnlv3(w,p,z,n,a,t,e,gW,gA,d,lp,ls) + LEARNLV2 LVQ2 weight learning function. + + Syntax + + [dW,LS] = learnlv3(w,p,n,a,T,lp,ls,Ttrain,C) + info = learnlv2(code) + + Description + + LEARNLV3 is the OLVQ weight learning function. + + LEARNLV2(W,P,Z,N,A,T,E,gW,gA,D,LP,LS) takes several inputs, + W - SxR weight matrix (or Sx1 bias vector). + P - RxQ input vectors (or ones(1,Q)). + Z - SxQ weighted input vectors. + N - SxQ net input vectors. + A - SxQ output vectors. + T - SxQ layer target vectors. + E - SxQ layer error vectors. + gW - SxR weight gradient with respect to performance. + gA - SxQ output gradient with respect to performance. + D - SxS neuron distances. + LP - Learning parameters, none, LP = []. + LS - Learning state, initially should be = []. + and returns, + dW - SxR weight (or bias) change matrix. + LS - New learning state. + + Learning occurs according to LEARNLV1's learning parameter, + shown here with its default value. + LP.lr - 0.01 - Learning rate + + LEARNLV2(CODE) returns useful information for each CODE string: + 'pnames' - Returns names of learning parameters. + 'pdefaults' - Returns default learning parameters. + 'needg' - Returns 1 if this function uses gW or gA. + +# Examples + +# Here we define a sample input P, output A, weight matrix W, and +# output gradient gA for a layer with a 2-element input and 3 neurons. +# We also define the learning rate LR. + + p = rand(2,1); + w = rand(3,2); + n = negdist(w,p); + a = compet(n); + gA = [-1;1; 1]; + lp.lr = 0.5; + +# Since LEARNLV2 only needs these values to calculate a weight +# change (see Algorithm below), we will use them to do so. + + dW = learnlv3(w,p,n,a,lp,Ttrain,C) + +# Network Use + + dw(i,:) = +lr*(p-w(i,:)) if C(:,i) = Ttrain + = -lr*(p-w(i,:)) if C(:,i) ~= Ttrain + +# if C(:,i) ~= Ttrain then the index j is found of the neuron with the +# greatest net input n(k), from the neurons whose C(:,k)=Ttrain. This +# neuron's weights are updated as follows: + + dw(j,:) = +lr*(p-w(i,:)) + +# See also LEARNLV1, ADAPTWB, TRAINWB, ADAPT, TRAIN. + +# Mark Beale, 11-31-97 +# Copyright (c) 1992-1998 by The MathWorks, Inc. +# Revision: 1.1.1.1 $ + +# FUNCTION INFO +if isstr(w) + switch lower(w) + case 'name' + dw = 'Learning Vector Quantization 3'; + case 'pnames' + dw = {'lr';'window'}; + case 'pdefaults' + lp.lr = 0.01; + lp.window = 0.25; + dw = lp; + case 'needg' + dw = 1; + otherwise + error('NNET:Arguments','Unrecognized code.') + end + return +end + +[S,R] = size(w); +Q = size(p,2); +pt = p'; +dw = zeros(S,R); + For each q... +for q=1:Q + + Find closest neuron k1 + nq = n(:,q); + k1 = find(nq == max(nq)); + k1 = k1(1); + + Find next closest neuron k2 + nq(k1) = -inf; + k2 = find(nq == max(nq)); + k2 = k2(1); + + + and if x falls into the window... + d1 = abs(n(k1,q)); Shorter distance + d2 = abs(n(k2,q)); Greater distance + + if d2/d1 > ((1-lp.window)/(1+lp.window)) + + then move incorrect neuron away from input, + and the correct neuron towards the input + ptq = pt(q,:); + if gA(k1,q) ~= gA(k2,q) + indicate the incorrect neuron with i, the other with j + if gA(k1,q) ~= 0 + i = k1; + j = k2; + else + i = k2; + j = k1; + end + dw(i,:) = dw(i,:) - lp.lr*(ptq - w(i,:)); + dw(j,:) = dw(j,:) + lp.lr*(ptq - w(j,:)); + else + dw(k1,:) = dw(k1,:) + 0.11*lp.window*(ptq-w(k1,:)); + dw(k2,:) = dw(k2,:) + 0.11*lp.window*(ptq-w(k2,:)); + end + end +end + +``` diff --git a/assets/src/BA/BA.0.4.md b/assets/src/BA/BA.0.4.md new file mode 100644 index 00000000..9f7c74e7 --- /dev/null +++ b/assets/src/BA/BA.0.4.md @@ -0,0 +1,39 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 自组织映射算法(SOM) + +自组织映射(SOM)或自组织特征映射(SOFM)是一种使用非监督式学习来产生训练样本的输入空间的一个低维(通常是二维)离散化的表示的人工神经网络(ANN)。自组织映射与其他人工神经网络的不同之处在于它使用一个邻近函数来保持输入控件的拓扑性质。 + +自组织映射(SOM)是一种非监督学习,一个常见的非监督式学习是数据聚类。在人工神经网络中,自组织映射(SOM)和适应性共振理论(ART)则是最常用的非监督式学习。 + +非监督式学习是一种机器学习的方式,并不需要人力来输入标签。它是监督式学习和强化学习等策略之外的一种选择。在监督式学习中,典型的任务是分类和回归分析,且需要使用到人工预先准备好的范例(base)。 + +自组织映射中学习的目标是使网络的不同部分对输入模式有相似的响应。这部分的灵感是来自于人类大脑皮层的不同部分处理视觉、听觉或其他感官信息的方式。 + +

+ +

+ +自组织映射的训练实例。蓝色斑点是训练数据的分布,而小白斑点是从该分布走出的目前的训练数据。起初SOM节点处在数据空间的任意位置。选择离训练数据最近的(用黄色高亮的)节点。它会向着训练数据移动,网格上它的邻居节点也会(在较小程度上)如此移动。经过多次迭代后的网格会趋于近似的数据分布。 + + + +神经元的权重初始化为小随机值或均匀采样自两个最大的主成分特征向量范围。用后一种方法初始化,学习的速率就会更快,因为初始的权重已经是SOM权重的一个很好的近似了。 + +必须提供给网络大量的能够实例向量来尽可能近地表示映射中期望的那些类型的向量。这些例子通常在迭代中数次使用。 + +训练采用竞争性学习。当训练样本提供给网络的时候,就会计算它与每个权重之间的欧氏距离。权重向量与输入最相似的神经元称作最佳匹配单元(BMU)。SOM栅格中BMU的权重以及与其邻近的神经元会向着输入向量调整。从BMU变化的量会随着(栅格中)时间和距离而降低。拥有权值 Wv(s) 的神经元v的更新公式为 + +Wv(s + 1) = Wv(s) + Θ(u, v, s) α(s)(D(t) - Wv(s)), + +其中 s 为步长指数,t 是训练样本的指数,D(t) 是输入向量,u 是 D(t) 的BMU指数,α(s) 是一个单调递减的学习系数;Θ(u, v, s) 是在步长为 s 下给出神经元 u 和神经元 v 之间距离的邻近函数。 根据实现的不同,t 可以系统地( 0, 1, 2...T-1,然后重复,T 为训练样本的大小),也可以随机从数据集中取出(Bootstrap抽样),或采用其他一些抽样方法(如jackknifing)。 + +邻近函数Θ(u, v, s)取决于BMU(神经元u)与神经元v之间的栅格距离。在最简单的形式中,对所有足够接近BMU的神经元都是1,其余都是0,但高斯函数也是一种常见的选择。不管函数形式如何,邻近函数都会随着时间收缩。 在起初邻域范围很大的时候,自组织发生在全局范围内。当邻域范围缩小到仅有两个神经元时,权值会收敛于局部估计值。在一些实现中,学习系数α会随着增加s而平稳减小,另一些实现(特别是t扫描训练数据集的情况)中步进式地下降,每 T 步一次。 + +对每个输入向量这个过程都会重复(通常很多次)循环λ。该网络把输入数据集中的类别或模式与相关联的输出节点拉近。如果可以重命名这些模式,这些名称就会附加到已训练的网络中的相关节点中。 + +在映射中,会有一个单一“获胜”神经元:该神经元的权重向量与输入向量最接近。这可以很容易由计算输入向量和权值向量的欧氏距离确定。 + + diff --git a/assets/src/BA/BA.0.5.md b/assets/src/BA/BA.0.5.md new file mode 100644 index 00000000..9ad2127c --- /dev/null +++ b/assets/src/BA/BA.0.5.md @@ -0,0 +1,158 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 局部加权学习算法(LWR) + +局部加权回归(LWR)是非参数学习方法。 首先参数学习方法是这样一种方法:在训练完成所有数据后得到一系列训练参数,然后根据训练参数来预测新样本的值,这时不再依赖之前的训练数据了,参数值是确定的。而非参数学习方法是这样一种算法:在预测新样本值时候每次都会重新训练数据得到新的参数值,也就是说每次预测新样本都会依赖训练数据集合,所以每次得到的参数值是不确定的。 +局部加权回归(LWR)是我们遇到的第一个non-parametric(非参数)学习算法,而线性回归则是我们遇到的以一个parametric(参数)学习算法。因为参数学习算法它有固定的明确的参数,所以参数一旦确定,就不会改变了,我们不需要在保留训练集中的训练样本。而非参数学习算法,每进行一次预测,就需要重新学习一组,是变化的,所以需要一直保留训练样本。因而,当训练集的容量较大时,非参数学习算法需要占用更多的存储空间,计算速度也较慢。所以有得必有失,效果好了,计算速度却降下来了。 + + + +#### 应用案例 + +```python +# coding: utf-8 +# linear_regression/regression.py + +def JLwr(theta, X, y, x, c): + """局部加权线性回归的代价函数计算式 + + Args: + theta: 相关系数矩阵 + X: 样本集矩阵 + y: 标签集矩阵 + x: 待预测输入 + c: tau + Returns: + 预测代价 + """ + m,n = X.shape + summerize = 0 + for i in range(m): + diff = (X[i]-x)*(X[i]-x).T + w = np.exp(-diff/(2*c*c)) + predictDiff = np.power(y[i] - X[i]*theta,2) + summerize = summerize + w*predictDiff + return summerize + +@exeTime +def lwr(rate, maxLoop, epsilon, X, y, x, c=1): + """局部加权线性回归 + + Args: + rate: 学习率 + maxLoop: 最大迭代次数 + epsilon: 预测精度 + X: 输入样本 + y: 标签向量 + x: 待预测向量 + c: tau + """ + m,n = X.shape + # 初始化theta + theta = np.zeros((n,1)) + count = 0 + converged = False + error = float('inf') + errors = [] + thetas = {} + for j in range(n): + thetas[j] = [theta[j,0]] + # 执行批量梯度下降 + while count<=maxLoop: + if(converged): + break + count = count + 1 + for j in range(n): + deriv = (y-X*theta).T*X[:, j]/m + theta[j,0] = theta[j,0]+rate*deriv + thetas[j].append(theta[j,0]) + error = JLwr(theta, X, y, x, c) + errors.append(error[0,0]) + # 如果已经收敛 + if(error < epsilon): + converged = True + return theta,errors,thetas + +``` + +#### 结果 + +```python +# coding: utf-8 +# linear_regression/test_lwr.py +import regression +import matplotlib.pyplot as plt +import matplotlib.ticker as mtick +import numpy as np + +if __name__ == "__main__": + srcX, y = regression.loadDataSet('data/lwr.txt'); + + m,n = srcX.shape + srcX = np.concatenate((srcX[:, 0], np.power(srcX[:, 0],2)), axis=1) + # 特征缩放 + X = regression.standardize(srcX.copy()) + X = np.concatenate((np.ones((m,1)), X), axis=1) + + rate = 0.1 + maxLoop = 1000 + epsilon = 0.01 + + predicateX = regression.standardize(np.matrix([[8, 64]])) + + predicateX = np.concatenate((np.ones((1,1)), predicateX), axis=1) + + result, t = regression.lwr(rate, maxLoop, epsilon, X, y, predicateX, 1) + theta, errors, thetas = result + + result2, t = regression.lwr(rate, maxLoop, epsilon, X, y, predicateX, 0.1) + theta2, errors2, thetas2 = result2 + + + # 打印特征点 + fittingFig = plt.figure() + title = 'polynomial with bgd: rate=%.2f, maxLoop=%d, epsilon=%.3f'%(rate,maxLoop,epsilon) + ax = fittingFig.add_subplot(111, title=title) + trainingSet = ax.scatter(srcX[:, 0].flatten().A[0], y[:,0].flatten().A[0]) + + print theta + print theta2 + + # 打印拟合曲线 + xx = np.linspace(1, 7, 50) + xx2 = np.power(xx,2) + yHat1 = [] + yHat2 = [] + for i in range(50): + normalizedSize = (xx[i]-xx.mean())/xx.std(0) + normalizedSize2 = (xx2[i]-xx2.mean())/xx2.std(0) + x = np.matrix([[1,normalizedSize, normalizedSize2]]) + yHat1.append(regression.h(theta, x.T)) + yHat2.append(regression.h(theta2, x.T)) + fittingLine1, = ax.plot(xx, yHat1, color='g') + fittingLine2, = ax.plot(xx, yHat2, color='r') + + ax.set_xlabel('temperature') + ax.set_ylabel('yield') + + plt.legend([trainingSet, fittingLine1, fittingLine2], ['Training Set', r'LWR with $\tau$=1', r'LWR with $\tau$=0.1']) + plt.show() + + # 打印误差曲线 + errorsFig = plt.figure() + ax = errorsFig.add_subplot(111) + ax.yaxis.set_major_formatter(mtick.FormatStrFormatter('%.2e')) + + ax.plot(range(len(errors)), errors) + ax.set_xlabel('Number of iterations') + ax.set_ylabel('Cost J') + + plt.show() +``` +最后,我们分别对ττ取值 0.10.1 和 11 ,得到了不同的拟合曲线: +

+ +

+ diff --git a/assets/src/BIR/BIR.md b/assets/src/BIR/BIR.md index 370d12f5..4365c431 100644 --- a/assets/src/BIR/BIR.md +++ b/assets/src/BIR/BIR.md @@ -11,7 +11,6 @@ 如今的机器学习领域主要的研究工作在三个方面进行:1)面向任务的研究,研究和分析改进一组预定任务的执行性能的学习系统;2)认知模型,研究人类学习过程并进行计算模拟;3)理论的分析,从理论的层面探索可能的算法和独立的应用领域算法。 - #### BIRCH 1 算法摘要 diff --git a/assets/src/BNS/BNS.0.1.md b/assets/src/BNS/BNS.0.1.md new file mode 100644 index 00000000..1cb4e79e --- /dev/null +++ b/assets/src/BNS/BNS.0.1.md @@ -0,0 +1,22 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 贝叶斯算法 + +贝叶斯网络(Bayesian networks or Bayesnets)也称为因果概率网络(CPNs,Causal Probabilistic Networks)、贝叶斯信念网络(BNS,Bayesian belief Networks)或信念网络,是用来对那些带有不确定性问题的问题域进行建模的系统。 + +从形式上说,贝叶斯网络是由一组以单向箭头相连的节点以及与每个节点相对应的概率函数所构成的网络。对于离散变量的贝叶斯网络,概率函数便具有了概率表的形式。这个网络必须是一个有向无环图,即其中不存在一条起始和终止于同一节点的通路。用图形的方法描述数据间的相互(因果)关系,语义清晰、可理解性强,有助于利用数据间的因果关系进行诊断、预测、分类等分析。因而贝叶斯方法具有独特的不确定性知识表达形式、丰富的概率表达能力、综合先验知识的增量学习特性等优点。 + +在贝叶斯网络中,每个节点代表一个有限状态数的离散随机变量,节点之间的单向箭头代表其间的因果关系。如果某个节点不具有父节点(即没有箭头指向它),那么这个节点就具有一个边缘概率表,其中记录了该节点取不同状态值的概率分布;反之,若某节点有父节点(即存在一条或多条有向箭头指向它),则它就拥有一个条件概率表。条件概率表中的每个元素对应该节点在其父节点处于某种状态组合下,其本身状态值的概率分布规律。 + +贝叶斯网络根据每个节点的概率表,在给定部分(一个或多个)节点状态值的前提下,对其余全部或部分节点的概率分布进行预测的过程即为网络的推理过程。 + +贝叶斯网络(Bayesian networks or Bayesnets)这里的应用算法有: + +* 朴素贝叶斯(Naive Bayes) +* 高斯朴素贝叶斯(Gaussian Naive Bayes) +* 多项式朴素贝叶斯(Multinomial Naive Bayes) +* AODE(Averaged One-Dependence Estimators) +* 多元自适应回归样条(MARS) +* 贝叶斯网络(Bayesian Belief Network) diff --git a/assets/src/BNS/BNS.0.2.md b/assets/src/BNS/BNS.0.2.md new file mode 100644 index 00000000..de939a1f --- /dev/null +++ b/assets/src/BNS/BNS.0.2.md @@ -0,0 +1,48 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 朴素贝叶斯(Naive Bayes) +机器学习中,朴素贝叶斯分类器是一系列以假设特征之间强(朴素)独立下运用贝叶斯定理为基础的简单概率分类器。 +朴素贝叶斯是一种构建分类器的简单方法。该分类器模型会给问题实例分配用特征值表示的类标签,类标签取自有限集合。它不是训练这种分类器的单一算法,而是一系列基于相同原理的算法:所有朴素贝叶斯分类器都假定样本每个特征与其他特征都不相关。举个例子,如果一种水果其具有红,圆,直径大概3英寸等特征,该水果可以被判定为是苹果。尽管这些特征相互依赖或者有些特征由其他特征决定,然而朴素贝叶斯分类器认为这些属性在判定该水果是否为苹果的概率分布上独立的。 + +对于某些类型的概率模型,在监督式学习的样本集中能获取得非常好的分类效果。在许多实际应用中,朴素贝叶斯模型参数估计使用最大似然估计方法;换而言之,在不用到贝叶斯概率或者任何贝叶斯模型的情况下,朴素贝叶斯模型也能奏效。 + +尽管是带着这些朴素思想和过于简单化的假设,但朴素贝叶斯分类器在很多复杂的现实情形中仍能够获取相当好的效果。2004年,一篇分析贝叶斯分类器问题的文章揭示了朴素贝叶斯分类器获取看上去不可思议的分类效果的若干理论上的原因。尽管如此,2006年有一篇文章详细比较了各种分类方法,发现更新的方法(如决策树和随机森林)的性能超过了贝叶斯分类器。 + +朴素贝叶斯分类器的一个优势在于只需要根据少量的训练数据就可以估计出必要的参数(变量的均值和方差)。由于变量独立假设,只需要估计各个变量的方法,而不需要确定整个协方差矩阵。 + + 朴素贝叶斯的应用过程: + * 收集数据:可以使用任何方法。 + * 准备数据:需要数值型或者布尔型数据。 + * 分析数据:有大量特征时,绘制特征作用不大,此时使用直方图效果更好。 + * 训练算法:计算不同的独立特征的条件概率。 + * 测试算法:计算错误率。 + * 使用算法:一个常见的朴素贝叶斯应用是文档分类。可以在任意的分类场景中使用朴素贝叶斯分类器,不一定非要是文本。 + +#### 应用案例 +```python +import org.apache.spark.mllib.classification.{NaiveBayes, NaiveBayesModel} +import org.apache.spark.mllib.linalg.Vectors +import org.apache.spark.mllib.regression.LabeledPoint +//读取并处理数据 +val data = sc.textFile("data/mllib/sample_naive_bayes_data.txt") +val parsedData = data.map { line => + val parts = line.split(',') + LabeledPoint(parts(0).toDouble, Vectors.dense(parts(1).split(' ').map(_.toDouble))) +} +// 切分数据为训练数据和测试数据 +val splits = parsedData.randomSplit(Array(0.6, 0.4), seed = 11L) +val training = splits(0) +val test = splits(1) +//训练模型 +val model = NaiveBayes.train(training, lambda = 1.0, modelType = "multinomial") +//测试数据 +val predictionAndLabel = test.map(p => (model.predict(p.features), p.label)) +val accuracy = 1.0 * predictionAndLabel.filter(x => x._1 == x._2).count() / test.count() +``` +#### 优缺点 + +优点:学习和预测的效率高,且易于实现;在数据较少的情况下仍然有效,可以处理多分类问题。 + +缺点:分类效果不一定很高,特征独立性假设会是朴素贝叶斯变得简单,但是会牺牲一定的分类准确率。 diff --git a/assets/src/BNS/BNS.0.3.md b/assets/src/BNS/BNS.0.3.md new file mode 100644 index 00000000..7eb40daf --- /dev/null +++ b/assets/src/BNS/BNS.0.3.md @@ -0,0 +1,137 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 高斯朴素贝叶斯(Gaussian Naive Bayes) +高斯朴素贝叶斯算法是一种特殊类型的NB算法,它特别用于当特征具有连续值时。同时假定所有特征都遵循高斯分布,即正态分布。高斯也称为正态分布,是连续变量分布上广泛使用的一种模型。对于单变量,高斯分布可以写成:均值和方差。 +

+ +

+ +对于维向量,多变量的高斯分布形式为:其中为维均值向量,协方差矩阵行列式。高斯分布会出现在许多不同的问题中,可以从多个不同的角度来理解。例如,我们已经证明,对于单个实值变量,使熵最大的是高斯分布。这个性质同样适用于多变量高斯。 + +高斯分布会出现在许多不同的问题中,可以从多个不同的角度来理解。例如,我们已经证明,对于单个实值变量,使熵最大的是高斯分布。这个性质同样适用于多变量高斯。 +另一种情况是,多个随机变量之和也会产生高斯分布。中心极限定理(由拉普拉斯提出)告诉我们,温和的一组随机变量的和的概率分布随着项的增加,趋向于高斯分布。为了阐述这个,考虑个区间[0, 1]上的均匀分布的随机变量,确定它们的均值的分布。如下图所展示的,对于大的,趋向于高斯分布。 +

+ +

+ +在实际应用中,随着N的增加,分布会很快的收敛于高斯分布。因而二元随机变量在次观测中出现次的二项分布将会在时趋向于高斯分布。在考虑高斯分布的几何形式。高斯通过出现在指数位置上的。 +这个二次型依赖于。被称为到的马氏距离( Mahalanobis distance),当是单位矩阵时,退化成欧式距离。当这个二次型在空间中是常数的时候,高斯分布的曲面也是常数。 +首先,我们注意到矩阵可以不失一般性的取为对称矩阵,因为任何非对称项都会从指数中消失。现在考虑,协方差矩阵的特征向量方程因为是实对称矩阵,所以它的特征值也是实数,特征向量可以从正交集中选择,得到的单位矩阵的元素,满足协方差矩阵可以表示成特征向量的展开的形式。 +二次型和高斯密度在曲面上为常数。如果所有特征值都是正的,那么这些曲面是中心位于,轴方向为,轴方向的缩放比例为的椭球面。 +

+ +

+为了很好的定义高斯分布,需要协方差矩阵的特征值严格为正,不然分布就不能标准化。每一个特征值都严格为正的矩阵被称为正定的(positive definite)。 + +尽管,高斯分布被当作密度模型广泛使用,但是它有着一些巨大的局限性。考虑分布中自由参数的数量。一个通用的对称协方差矩阵有个独立参数,和其中的另外的独立参数。对于大的,参数的总数以平方的方式增长,且大矩阵的计算和求逆会相当困难。为了解决这个问题的其中一种方式是使用限制形式的协方差矩阵。如果考虑对角化的协方差矩阵,即,那么密度模型中总共有个独立参数。对应的常数密度的轮廓线由轴对齐的椭球给出。可以进一步地限制协方差矩阵为单位矩阵的倍数,即(这被称为同性协方差),那么模型总共有个独立参数,且得到恒定密度的球面。下图分别展示了通用的、对角的以及同性的协方差矩阵的概率。 +

+ +

+二维高斯分布的固定概率密度等高线。其中,(a)图对应的协方差矩阵为一般形式,(b)图对应的协方差矩阵为对角矩阵,图中椭圆的等高线与坐标轴对齐,(c)图对应的协方差矩阵正比于单位矩阵,图中的等高线是同心圆。尽管这样的方法限制了概率分布的的自由度的数量,使得求协方差矩阵的逆可以很快地完成,但也极大地束缚了概率密度的形式,且限制了它获取数据中有趣的相关性的能力。 + +高斯分布的另一个局限是它本质上是单峰的(即只有一个最大值),因此不能够很好地近似多峰分布。因此高斯分布一方面相当灵活,因为它有很多参数。另一方面,它又有很大的局限性,因为它不能够描述很多概率分布。 + + +#### 应用实例 +```python +import numpy as np +from sklearn.utils import array2d +from sklearn.utils.extmath import logsumexp +import random +import matplotlib.pylab as plt +class GaussianBayes: + def __init__(self): + pass + def train(self, x, y): + n_samples, n_features = x.shape + if(n_samples != y.shape[0]): + raise ValueError('x and y have incompatible shapes.') + self._classes = unique_y = np.unique(y) + n_classes = unique_y.shape[0] + self._theta = np.zeros((n_classes, n_features)) + self._sigma = np.zeros((n_classes, n_features)) + self._class_prior = np.zeros(n_classes) + epsilon = 1e-9 + for i, y_i in enumerate(unique_y): + self._theta[i, :] = np.mean(x[y == y_i, :], axis = 0) + self._sigma[i, :] = np.var(x[y == y_i, :]) + epsilon + self._class_prior[i] = np.float(np.sum(y == y_i)) / n_samples + return self + def predict(self, x): + prob = self.predict_proba(x) + indexs = [] + scores = [] + for ele in prob: + index = np.argmax(ele) + score = ele[index] + indexs.append(index) + scores.append(score) + return [indexs, scores] + def predict_log_prob(self, x): + joint = self.joint_log_likelihood(x) + #log_like_x = np.log(np.sum(np.exp(joint))) + log_like_x = logsumexp(joint, axis = 1) + return joint - np.atleast_2d(log_like_x).T + def predict_proba(self, x): + return np.exp(self.predict_log_prob(x)) + def joint_log_likelihood(self, x): + x = array2d(x) + joint_log_likelihood = [] + for i in xrange(np.size(self._classes)): + jointi = np.log(self._class_prior[i]) + n_ij = - 0.5 * np.sum(np.log(np.pi * self._sigma[i, :])) + n_ij -= 0.5 * np.sum(((x - self._theta[i, :]) ** 2) / + (self._sigma[i, :]), 1) + joint_log_likelihood.append(jointi + n_ij) + + joint_log_likelihood = np.array(joint_log_likelihood).T + return joint_log_likelihood + +def samples(n_samples, n_features = 10, classes = 5, rat = 0.2): + x = np.zeros((n_samples, n_features)) + y = np.zeros((n_samples, 1)) + num = int(n_samples / classes) + for i in range(0, classes): + x[i*num:i*num + num] = np.random.random((num,n_features)) + i + + for i in range(0, x.shape[0]): + y[i, 0] = int(i / num) + index = np.arange(0, x.shape[0]) + random.shuffle(index) + train_index = index[0: int((1-rat) * x.shape[0])] + test_index = index[int((1-rat) * x.shape[0]):-1] + train_x = x[train_index, :] + train_y = y[train_index] + test_x = x[test_index, :] + test_y = y[test_index] + return [train_x, train_y, test_x, test_y] +def plotRes(pre, real, test_x): + s = set(pre) + col = ['r','b','g','y','m'] + fig = plt.figure() + pre = np.array(pre) + ax = fig.add_subplot(111) + for i in range(0, len(s)): + index1 = pre == i + index2 = real == i + x1 = test_x[index1, :] + x2 = test_x[index2, :] + ax.scatter(x1[:,0],x1[:,1],color=col[i],marker='v',linewidths=0.5) + ax.scatter(x2[:,0],x2[:,1],color=col[i],marker='.',linewidths=12) + plt.title('The prediction of the Gaussian Bayes') + plt.legend(('c1:predict','c1:true', + 'c2:predict','c2:true', + 'c3:predict','c3:true', + 'c4:predict','c4:true', + 'c5:predict','c5:true'), shadow = True, loc = (0.01, 0.4)) + plt.show() +if __name__ == '__main__': + [train_x, train_y, test_x, test_y] = samples(2000, 30, 5) + gb = GaussianBayes() + gb.train(train_x, train_y) + + pred_y = gb.predict(test_x) + plotRes(pred_y[0], test_y.ravel(), test_x) +``` diff --git a/assets/src/BNS/BNS.0.4.md b/assets/src/BNS/BNS.0.4.md new file mode 100644 index 00000000..e2f0e368 --- /dev/null +++ b/assets/src/BNS/BNS.0.4.md @@ -0,0 +1,48 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 多项式朴素贝叶斯(Multinomial Naive Bayes) + + 多项式朴素贝叶斯(Multinomial Naive Bayes)算法,用于文本分类(这个领域中数据往往以词向量表示,尽管在实践中 tf-idf向量在预测时表现良好)的两大经典朴素贝叶斯算法之一。分布参数由每类向量决定, 式中 n 是特征的数量(对于文本分类,是词汇量的大小)是样本中属于类 y 中特征i概率 。 + +参数 使用平滑过的最大似然估计法来估计,即相对频率计数: + +

+ +

+ +式中是训练集T中特征 i 在类 y 中出现的次数,是类y中出现所有特征的计数总和。 + +先验平滑因子应用于在学习样本中没有出现的特征,以防在将来的计算中出现0概率输出。 把 被称为拉普拉斯平滑(Lapalce smoothing),而被称为利德斯通(Lidstone smoothing)。 + + + +#### 应用实例 +```python +#GaussianNB differ from MultinomialNB in these two method: +# _calculate_feature_prob, _get_xj_prob +class GaussianNB(MultinomialNB): + """ + GaussianNB inherit from MultinomialNB,so it has self.alpha + and self.fit() use alpha to calculate class_prior + However,GaussianNB should calculate class_prior without alpha. + Anyway,it make no big different + + """ + #calculate mean(mu) and standard deviation(sigma) of the given feature + def _calculate_feature_prob(self,feature): + mu = np.mean(feature) + sigma = np.std(feature) + return (mu,sigma) + + #the probability density for the Gaussian distribution + def _prob_gaussian(self,mu,sigma,x): + return ( 1.0/(sigma * np.sqrt(2 * np.pi)) * + np.exp( - (x - mu)**2 / (2 * sigma**2)) ) + + #given mu and sigma , return Gaussian distribution probability for target_value + def _get_xj_prob(self,mu_sigma,target_value): + return self._prob_gaussian(mu_sigma[0],mu_sigma[1],target_value) + +``` diff --git a/assets/src/BNS/BNS.0.5.md b/assets/src/BNS/BNS.0.5.md new file mode 100644 index 00000000..ea35a35a --- /dev/null +++ b/assets/src/BNS/BNS.0.5.md @@ -0,0 +1,20 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 平均单依赖估计量(Averaged One-Dependence Estimators) + +平均单依赖估计量(Averaged One-Dependence Estimators)是一种半朴素贝叶斯学习方法。它通过聚合多个单依赖分类器的预测来执行分类,其中所有属性依赖于相同的单独父属性以及类。它的开发旨在解决流行的朴素贝叶斯分类器的属性独立性问题。它常常以计算量适度增加为代价,比朴素贝叶斯开发出更准确的分类器。 +像朴素贝叶斯一样,AODE不执行模型选择,也不使用可调参数。因此,它具有较低的方差。 + +它支持增量学习,通过这些学习,分类器可以通过新示例提供的信息进行有效更新。它预测类别概率,而不是简单地预测单个类别,从而允许用户确定每个分类的可信度。其概率模型可以直接处理某些数据丢失的情况。为了保持效率,可以期望利用单依赖分类器,诸如树扩展型朴素贝叶斯分类器,Tree Augmented Naive Bayes(TAN),其中每个属性取决于类和至多一个其他属性。然而,大多数单依赖分类器学习的方法执行模型选择,这个过程通常会带来相当大的计算开销并且相对于朴素贝叶斯大大增加了方差。 + +AODE通过对多个单依赖分类器的预测进行平均来避免模型选择。在每个单依赖分类器中,选择一个属性作为所有其他属性的父属性。该属性称为SuperParent,这种单依赖性分类器称为SuperParent单依赖性估计器(SPODE)。 + +AODE具有计算复杂性 O(ln ^2)在训练时间和 O(kn^2)在分类时刻,其中n是特征的数量,l是训练样本的数量,k是类别的数量。这使得应用于高维数据是不可行的。然而,在这个限制内,它与训练样例的数量成线性关系,因此可以有效地处理大量的训练样例。 + +

+ +

+ +由于AODE在避免模型选择的同时,比朴素贝叶斯更弱的属性条件独立性假设,它的偏差大大降低,方差增加很小。 diff --git a/assets/src/BNS/BNS.0.6.md b/assets/src/BNS/BNS.0.6.md new file mode 100644 index 00000000..49e29537 --- /dev/null +++ b/assets/src/BNS/BNS.0.6.md @@ -0,0 +1,52 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 贝叶斯网络(Bayesian Belief Network) + +贝叶斯网络(Bayesian network),又称信念网络(Belief Network),或有向无环图模型(directed acyclic graphical model),是一种概率图模型,于1985年由Judea Pearl首先提出,它是基于概率推理的图形化网络,可以模拟人类推理过程中因果关系的不确定性处理模型,其网络拓朴结构是一个有向无环图。而贝叶斯公式则是这个概率网络的基础。贝叶斯网络是基于概率推理的数学模型,所谓概率推理就是通过一些变量的信息来获取其他的概率信息的过程,基于概率推理的贝叶斯网络(Bayesian network)是为了解决不定性和不完整性问题而提出的,它对于解决复杂设备不确定性和关联性引起的故障有很大的优势,在多个领域中获得广泛应用。 + +贝叶斯网络的有向无环图(Directed Acyclic Graph,DAG)中的节点表示随机变量,,由代表变量节点及连接这些节点有向边构成。它们可以是可观察到的变量,或隐变量、未知参数等。认为有因果关系(或非条件独立)的变量或命题则用箭头来连接。若两个节点间以一个单箭头连接在一起,表示其中一个节点是“因(parents)”,另一个是“果(children)”,两节点就会产生一个条件概率值。节点代表随机变量,节点间的有向边代表了节点间的互相关系(由父节点指向其子节点),用条件概率进行表达关系强度,没有父节点的用先验概率进行信息表达。节点变量可以是任何问题的抽象,如:测试值,观测现象,意见征询等。适用于表达和分析不确定性和概率性的事件,应用于有条件地依赖多种控制因素的决策,可以从不完全、不精确或不确定的知识或信息中做出推理。 + +使用贝叶斯网络必须知道各个状态之间相关的概率。得到这些参数的过程叫做训练。和训练马尔可夫模型一样,训练贝叶斯网络要用一些已知的数据。比如在训练上面的网络,需要知道一些心血管疾病和吸烟、家族病史等有关的情况。相比马尔可夫链,贝叶斯网络的训练比较复杂,从理论上讲,它是一个 NP-complete问题,也就是说,现阶段没有可以在多项式时间内完成的算法。但是,对于某些应用,这个训练过程可以简化,并在计算上高效实现。 + +贝叶斯理论是处理不确定性信息的重要工具。作为一种基于概率的不确定性推理方法,贝叶斯网络在处理不确定信息的智能化系统中已得到了重要的应用,已成功地用于医疗诊断、统计决策、专家系统、学习预测等领域。这些成功的应用,充分体现了贝叶斯网络技术是一种强有力的不确定性推理方法。 + +#### 应用示例 + + +```python +from bayesian.bbn import build_bbn + +def f_prize_door(prize_door): + return 0.33333333 +def f_guest_door(guest_door): + return 0.33333333 +def f_monty_door(prize_door, guest_door, monty_door): + if prize_door == guest_door: # 参赛者猜对了 + if prize_door == monty_door: + return 0 # Monty不会打开有车的那扇门,不可能发生 + else: + return 0.5 # Monty会打开其它两扇门,二选一 + elif prize_door == monty_door: + return 0 # Monty不会打开有车的那扇门,不可能发生 + elif guest_door == monty_door: + return 0 # 门已经由参赛者选定,不可能发生 + else: + return 1 # Monty打开另一扇有羊的门 + +if __name__ == '__main__': + g = build_bbn( + f_prize_door, + f_guest_door, + f_monty_door, + domains=dict( + prize_door=['A', 'B', 'C'], + guest_door=['A', 'B', 'C'], + monty_door=['A', 'B', 'C'])) + + g.q() + g.q(guest_door='A') +g.q(guest_door='A', monty_door='B') + +``` diff --git a/assets/src/BNS/BNS.md b/assets/src/BNS/BNS.md index b2858aa5..69b7ef51 100644 --- a/assets/src/BNS/BNS.md +++ b/assets/src/BNS/BNS.md @@ -3,8 +3,7 @@ AI的开发离不开算法那我们就接下来开始学习算法吧! #### 贝叶斯网络 - -贝叶斯网络(Bayesian networks or Bayesnets)也称为因果概率网络(CPNs,Causal Probabilistic Networks)、贝叶斯信念网络(BNs,Bayesian belief Networks)或信念网络,是用来对那些带有不确定性问题的问题域进行建模的系统。 +贝叶斯网络(Bayesian networks or Bayesnets)也称为因果概率网络(CPNs,Causal Probabilistic Networks)、贝叶斯信念网络(BNS,Bayesian belief Networks)或信念网络,是用来对那些带有不确定性问题的问题域进行建模的系统。 从形式上说,贝叶斯网络是由一组以单向箭头相连的节点以及与每个节点相对应的概率函数所构成的网络。对于离散变量的贝叶斯网络,概率函数便具有了概率表的形式。这个网络必须是一个有向无环图,即其中不存在一条起始和终止于同一节点的通路。用图形的方法描述数据间的相互(因果)关系,语义清晰、可理解性强,有助于利用数据间的因果关系进行诊断、预测、分类等分析。因而贝叶斯方法具有独特的不确定性知识表达形式、丰富的概率表达能力、综合先验知识的增量学习特性等优点。 @@ -12,11 +11,11 @@ AI的开发离不开算法那我们就接下来开始学习算法吧! 贝叶斯网络根据每个节点的概率表,在给定部分(一个或多个)节点状态值的前提下,对其余全部或部分节点的概率分布进行预测的过程即为网络的推理过程。 -分析流程 +分析流程: 贝叶斯网络的分析流程通常由三个步骤组成,即(1)网络建立,(2)参数学习或参数设置,(3)网络推理,如图所示.

- +

贝叶斯网络分析流程 @@ -60,12 +59,12 @@ AI的开发离不开算法那我们就接下来开始学习算法吧! 如果要计算节点D的概率,由于节点D和节点A、B相关,根据边界概率的定义有:

- +

-在没有任何证据提供给网络的情况下有初始边界概率为 +在没有任何证据提供给网络的情况下有初始边界概率为: -P(D)=0.8×0.1×0.4+0.6×0.1×0.6+0.6×0.9×0.4+0.3×0.9+0.6=0.032+0.036+0.0216+0.0162=0. 446. +P(D)=0.8×0.1×0.4+0.6×0.1×0.6+0.6×0.9×0.4+0.3×0.9+0.6=0.032+0.036+0.0216+0.0162=0.446. 同样,考虑节点C发生了的情况,亦即C=TRUE,知道P(A)从0.1变成0.471,P(notA)也就从0.9变成0.529,将这些值重新代入式(2),得到修改后的边界概率,即条件概率P(D| C)=0.542.给网络输入新的证据以更新各个节点的概率,这个过程称为概率繁殖.贝叶斯网络的作用就在于对不确定性系统进行知识表达并利用概率繁殖来对其进行推理. diff --git a/assets/src/BP/BP.md b/assets/src/BP/BP.md index 54e22b2b..9134f049 100644 --- a/assets/src/BP/BP.md +++ b/assets/src/BP/BP.md @@ -12,7 +12,6 @@ AI的开发离不开算法那我们就接下来开始学习算法吧!

- 人工神经网络中,神经元处理单元可表示不同的对象,例如特征、字母、概念,或者一些有意义的抽象模式。网络中处理单元的类型分为三类:输入单元、输出单元和隐单元。输入单元接受外部世界的信号与数据;输出单元实现系统处理结果的输出;隐单元是处在输入和输出单元之间,不能由系统外部观察的单元。神经元间的连接权值反映了单元间的连接强度,信息的表示和处理体现在网络处理单元的连接关系中。 #### 算法描述 diff --git a/assets/src/CA/CA.0.1.md b/assets/src/CA/CA.0.1.md new file mode 100644 index 00000000..b9570708 --- /dev/null +++ b/assets/src/CA/CA.0.1.md @@ -0,0 +1,19 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 聚类算法 + +聚类分析又称群分析,它是研究(样品或指标)分类问题的一种统计分析方法,同时也是数据挖掘的一个重要算法。聚类(Cluster)分析是由若干模式(Pattern)组成的,通常,模式是一个度量(Measurement)的向量,或者是多维空间中的一个点。聚类分析以相似性为基础,在一个聚类中的模式之间比不在同一聚类中的模式之间具有更多的相似性。 + +聚类算法是一种非监督学习。聚类分析起源于分类学,在古老的分类学中,人们主要依靠经验和专业知识来实现分类,很少利用数学工具进行定量的分类。随着人类科学技术的发展,对分类的要求越来越高,以致有时仅凭经验和专业知识难以确切地进行分类,于是人们逐渐地把数学工具引用到了分类学中,形成了数值分类学,之后又将多元分析的技术引入到数值分类学形成了聚类分析。聚类分析内容非常丰富,有系统聚类法、有序样品聚类法、动态聚类法、模糊聚类法、图论聚类法、聚类预报法等。 + +许多聚类算法在执行之前,需要指定从输入数据集中产生的分类个数。除非事先准备好一个合适的值,否则必须决定一个大概值,关于这个问题已经有一些现成的技术。 + +聚类算法主要可分为:划分方法(partitioning method),层次方法(hierarchical method),基于密度的方法(density-basedmethod),基于网格的方法(grid-based method),和基于模型的方法(model-based method)。 + +聚类算法(Cluster analysis)的应用算法有: +* K-均值(K-Means Algorithm) +* 模糊聚类Fuzzy Clustering +* 期望最大化(Expectation-Maximization) +* 聚类分析(Cluster Analysis) diff --git a/assets/src/CA/CA.0.2.md b/assets/src/CA/CA.0.2.md new file mode 100644 index 00000000..074cbff2 --- /dev/null +++ b/assets/src/CA/CA.0.2.md @@ -0,0 +1,154 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### K-均值(K-Means Algorithm) + +k-means算法,也被称为k-平均或k-均值,是一种得到最广泛使用的聚类算法。 通常它把n个点(可以是样本的一次观察或一个实例)划分到k个聚类中,使得每个点都属于离他最近的均值(此即聚类中心)对应的聚类,以之作为聚类的标准。 + +k-means算法属于无监督学习方法。此算法以k为参数,把n 个对象分为k个簇,以使簇内具有较高的相似度,而且簇间的相似度较低。相似度的计算根据一个簇中对象的平均值(被看作簇的重心)来进行。此算法首先随机选择k个对象,每个对象代表一个聚类的质心。对于其余的每一个对象,根据该对象与各聚类质心之间的距离,把它分配到与之最相似的聚类中。然后,计算每个聚类的新质心。重复上述过程,直到准则函数收敛。k-means算法是一种较典型的逐点修改迭代的动态聚类算法,其要点是以误差平方和为准则函数。逐点修改类中心:一个象元样本按某一原则,归属于某一组类后,就要重新计算这个组类的均值,并且以新的均值作为凝聚中心点进行下一次象元素聚类;逐批修改类中心:在全部象元样本按某一组的类中心分类之后,再计算修改各类的均值,作为下一次分类的凝聚中心点 + +聚类相似度是利用各聚类中对象的均值所获得一个“中心对象”(引力中心)来进行计算的。相异度计算方法:欧几里得距离,曼哈顿距离,闵可夫斯基距离,皮尔逊相关系数. + +#### 应用示例 + +输入:簇的数目k和包含n个对象的数据库。 输出:k个簇,使平方误差准则最小。 + +算法步骤: + +* 1.为每个聚类确定一个初始聚类中心,这样就有K 个初始聚类中心。 +* 2.将样本集中的样本按照最小距离原则分配到最邻近聚类 +* 3.使用每个聚类中的样本均值作为新的聚类中心。 +* 4.重复步骤2.3直到聚类中心不再变化。 +* 5.结束,得到K个聚类 + +```python +#!/usr/bin/env python +# coding: utf-8 +# matplotlib inline +import time +import numpy as np +import tensorflow as tf +import matplotlib.pyplot as plt + +from sklearn.datasets.samples_generator import make_blobs +from sklearn.datasets.samples_generator import make_circles + +N = 200 +K = 4 +DATA_TYPE = 'blobs' +MAX_ITERS = 1000 +colourindexes = [2, 1, 4, 3] +# k-means不适用于circles数据,2个类足以demo这个问题 +if (DATA_TYPE == 'circle'): + K = 2 + colourindexes = [2, 1] + +# 根据聚类中心生成测试数据 +centers = [(-2, -2), (-2, 1.5), (1.5, -2), (2, 1.5)] +if (DATA_TYPE == 'circle'): + data, features = make_circles( + n_samples=N, shuffle=True, noise=0.01, factor=0.4) +else: + data, features = make_blobs(n_samples=N, centers=centers, + n_features=2, cluster_std=0.8, + shuffle=False, random_state=42) + #fig, ax = plt.subplots() + #ax.scatter(np.asarray(centers).transpose()[0], np.asarray( + # centers).transpose()[1], marker='o', s=250) + #plt.show() + + fig, ax = plt.subplots() + ax.scatter(np.asarray(centers).transpose()[0], np.asarray( + centers).transpose()[1], marker='o', s=250) + ax.scatter(data.transpose()[0], data.transpose()[ + 1], marker='o', s=100, c=features, cmap=plt.cm.coolwarm) + plt.show() + +def bucket_mean(data, bucket_ids, num_buckets): + total = tf.unsorted_segment_sum(data, bucket_ids, num_buckets) + count = tf.unsorted_segment_sum( + tf.ones_like(data), bucket_ids, num_buckets) + return total / count + +start = time.time() +points = tf.Variable(data) +cluster_assignments = tf.Variable(tf.zeros([N], dtype=tf.int64)) +centroids = tf.Variable(tf.slice(points.initialized_value(), [0, 0], [K, 2])) + +rep_centroids = tf.reshape(tf.tile(centroids, [N, 1]), [N, K, 2]) +rep_points = tf.reshape(tf.tile(points, [1, K]), [N, K, 2]) +sum_squares = tf.reduce_sum(tf.square(rep_points - rep_centroids), + reduction_indices=2) +best_centroids = tf.argmin(sum_squares, 1) +did_assignments_change = tf.reduce_any( + tf.not_equal(best_centroids, cluster_assignments)) +means = bucket_mean(points, best_centroids, K) + +with tf.control_dependencies([did_assignments_change]): + do_updates = tf.group( + centroids.assign(means), + cluster_assignments.assign(best_centroids)) + +changed = True +iters = 0 + +sess = tf.Session() +sess.run(tf.initialize_all_variables()) +while changed and iters < MAX_ITERS: + iters += 1 + [changed, _] = sess.run([did_assignments_change, do_updates]) + [centers, assignments] = sess.run([centroids, cluster_assignments]) + fig, ax = plt.subplots() + ax.scatter(sess.run(points).transpose()[0], sess.run(points).transpose()[ + 1], marker='o', s=200, c=assignments, cmap=plt.cm.coolwarm) + ax.scatter(centers[:, 0], centers[:, 1], marker='^', + s=550, c=colourindexes, cmap=plt.cm.plasma) + ax.set_title('Iteration ' + str(iters)) + # plt.savefig("kmeans" + str(iters) + ".png") + plt.show() + +fig, ax = plt.subplots() +ax.scatter(sess.run(points).transpose()[0], sess.run(points).transpose()[ + 1], marker='o', s=200, c=assignments, cmap=plt.cm.coolwarm) +ax.scatter(np.asarray(centers).transpose()[0], np.asarray( + centers).transpose()[1], marker='o', s=250, c=colourindexes, cmap=plt.cm.plasma) +plt.show() + + +end = time.time() +print ("Found in %.2f seconds" % (end - start)), iters, "iterations" +print "Centroids:", centers +print "Cluster assignments:", assignments +``` +

+ +

+ +

+ +

+ +```python +Found in 2.15 seconds 8 iterations +Centroids: [[ 1.65289262 -2.04643427] + [-2.0763623 1.61204964] + [-2.08862822 -2.07255306] + [ 2.09831502 1.55936014]] +Cluster assignments: [2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 + 2 2 2 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 + 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 3 0 0 0 0 0 0 + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 + 0 0 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3 + 3 3 3 3 3 3 3 3 3 3 3 3 3 3 3] +``` + +#### 优点 + +* 简单、快速,可并行计算 +* 已经获得防范的应用 + +#### 缺点 + +* 必须事先给出k(要生成的簇的数目),而且对初值敏感,对于不同的初始值,可能会导致不同结果。 +* 对于“躁声”和孤立点数据是敏感的,少量的该类数据能够对平均值产生极大的影响。 diff --git a/assets/src/CA/CA.0.3.md b/assets/src/CA/CA.0.3.md new file mode 100644 index 00000000..47772662 --- /dev/null +++ b/assets/src/CA/CA.0.3.md @@ -0,0 +1,204 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 模糊c-均值聚类算法(Fuzzy C-means Algorithm) +模糊c-均值聚类算法,是一种基于目标函数的模糊聚类算法,主要用于数据的聚类分析。理论成熟,应用广泛,是一种优秀的聚类算法。 +模糊c-均值聚类算法输入就是一个待聚类的数据集,每一个数据都有p个特征。它的输出是一个c行n列的矩阵U,c刚才提到是聚类数目,n是数据集中元素的个数,用这个矩阵就可以表示分类的结果,因为你看某一列,表示的就是这个元素对各个类的隶属程度,哪一个值最大,就说这个元素属于哪一类。 + +还有一个输出是各个类的聚类中心向量集合V,一共有c个元素。每个元素也是有p维的。 +

+ +

+ +

+ +

+ +

+ +

+ + +#### 应用示例 + +```python +typedef struct{ + double x; + double y; +} Position; + + +//len:节点数量 +//range:节点x、y值的范围 +Position *randomPosition(int len, int range){ + srand((unsigned)time(NULL)); + Position *allPos = (Position *)malloc(len * sizeof(Position)); + + short a = 1; + for (int i = 0; i < len; ++i) + { + if (a) + { + allPos[i].x = (double)rand() / 2147483647 * range; + allPos[i].y = (double)rand() / 2147483647 * range; + a = 0; + } + else if (!a) + { + allPos[i].x = (double)rand() / 2147483647 * range+50; + allPos[i].y = (double)rand() / 2147483647 * range+50; + a = 1; + } + } + return allPos; +} + +//posNum:节点数量 +//clusterNum:聚类中心数量 +double **init(int posNum, int clusterNum){ + double **u = (double **)malloc(sizeof(double *) * clusterNum); + for (int i = 0; i ,样例间独立,我们想找到每个样例隐含的类别z,能使得p(x,z)最大。p(x,z)的最大似然估计如下: +

+ +

+ +由jensen不等式可得: +

+ +

+ +对于每一个样例i,让表示该样例隐含变量z的某种分布,满足的条件是。由此,可以确定式子的下界,然后不断的提高此下界达到逼近最后真实值的目的值,这个不等式变成等式为止,然后再依据jensen不等式,当不等式变为等式的时候,当且仅当,也就是说X是常量,推出就是下面的公式: +

+ +

+ +由于Q是随机变量z的概率密度函数,因此,可以得到:分子的和等于c(分子分母都对所有z求和:多个等式分子分母相加不变,这个认为每个样例的两个概率比值都是c)。 + +

+ +

+ + +由此可得出EM算法的一般过程:循环重复E步骤和M步骤直到收敛。 +E步骤:对于每一个i,计算: + +

+ +

+ +M步骤计算: + +

+ +

+ + +#### 应用示例 + +```python +import numpy as np +import matplotlib.pyplot as plt +from scipy.stats import multivariate_normal + +DEBUG = True +# 调试输出函数 +# 由全局变量 DEBUG 控制输出 +def debug(*args, **kwargs): + global DEBUG + if DEBUG: + print(*args, **kwargs) +# 第 k 个模型的高斯分布密度函数 +# 每 i 行表示第 i 个样本在各模型中的出现概率 +# 返回一维列表 + +def phi(Y, mu_k, cov_k): + norm = multivariate_normal(mean=mu_k, cov=cov_k) + return norm.pdf(Y) + +# E 步:计算每个模型对样本的响应度 +# Y 为样本矩阵,每个样本一行,只有一个特征时为列向量 +# mu 为均值多维数组,每行表示一个样本各个特征的均值 +# cov 为协方差矩阵的数组,alpha 为模型响应度数组 +def getExpectation(Y, mu, cov, alpha): + # 样本数 + N = Y.shape[0] + # 模型数 + K = alpha.shape[0] + + # 为避免使用单个高斯模型或样本,导致返回结果的类型不一致 + # 因此要求样本数和模型个数必须大于1 + assert N > 1, "There must be more than one sample!" + assert K > 1, "There must be more than one gaussian model!" + + # 响应度矩阵,行对应样本,列对应响应度 + gamma = np.mat(np.zeros((N, K))) + + # 计算各模型中所有样本出现的概率,行对应样本,列对应模型 + prob = np.zeros((N, K)) + for k in range(K): + prob[:, k] = phi(Y, mu[k], cov[k]) + prob = np.mat(prob) + + # 计算每个模型对每个样本的响应度 + for k in range(K): + gamma[:, k] = alpha[k] * prob[:, k] + for i in range(N): + gamma[i, :] /= np.sum(gamma[i, :]) + return gamma + +# M 步:迭代模型参数 +# Y 为样本矩阵,gamma 为响应度矩阵 +def maximize(Y, gamma): + # 样本数和特征数 + N, D = Y.shape + # 模型数 + K = gamma.shape[1] + + #初始化参数值 + mu = np.zeros((K, D)) + cov = [] + alpha = np.zeros(K) + + # 更新每个模型的参数 + for k in range(K): + # 第 k 个模型对所有样本的响应度之和 + Nk = np.sum(gamma[:, k]) + # 更新 mu + # 对每个特征求均值 + for d in range(D): + mu[k, d] = np.sum(np.multiply(gamma[:, k], Y[:, d])) / Nk + # 更新 cov + cov_k = np.mat(np.zeros((D, D))) + for i in range(N): + cov_k += gamma[i, k] * (Y[i] - mu[k]).T * (Y[i] - mu[k]) / Nk + cov.append(cov_k) + # 更新 alpha + alpha[k] = Nk / N + cov = np.array(cov) + return mu, cov, alpha + +# 数据预处理 +# 将所有数据都缩放到 0 和 1 之间 +def scale_data(Y): + # 对每一维特征分别进行缩放 + for i in range(Y.shape[1]): + max_ = Y[:, i].max() + min_ = Y[:, i].min() + Y[:, i] = (Y[:, i] - min_) / (max_ - min_) + debug("Data scaled.") + return Y + +# 初始化模型参数 +# shape 是表示样本规模的二元组,(样本数, 特征数) +# K 表示模型个数 +def init_params(shape, K): + N, D = shape + mu = np.random.rand(K, D) + cov = np.array([np.eye(D)] * K) + alpha = np.array([1.0 / K] * K) + debug("Parameters initialized.") + debug("mu:", mu, "cov:", cov, "alpha:", alpha, sep="\n") + return mu, cov, alpha + +# 高斯混合模型 EM 算法 +# 给定样本矩阵 Y,计算模型参数 +# K 为模型个数 +# times 为迭代次数 +def GMM_EM(Y, K, times): + Y = scale_data(Y) + mu, cov, alpha = init_params(Y.shape, K) + for i in range(times): + gamma = getExpectation(Y, mu, cov, alpha) + mu, cov, alpha = maximize(Y, gamma) + debug("{sep} Result {sep}".format(sep="-" * 20)) + debug("mu:", mu, "cov:", cov, "alpha:", alpha, sep="\n") + return mu, cov, alpha +``` + + +```python +main.py 文件: +import matplotlib.pyplot as plt +from gmm import * + +# 设置调试模式 +DEBUG = True + +# 载入数据 +Y = np.loadtxt("gmm.data") +matY = np.matrix(Y, copy=True) + +# 模型个数,即聚类的类别个数 +K = 2 + +# 计算 GMM 模型参数 +mu, cov, alpha = GMM_EM(matY, K, 100) + +# 根据 GMM 模型,对样本数据进行聚类,一个模型对应一个类别 +N = Y.shape[0] +# 求当前模型参数下,各模型对样本的响应度矩阵 +gamma = getExpectation(matY, mu, cov, alpha) +# 对每个样本,求响应度最大的模型下标,作为其类别标识 +category = gamma.argmax(axis=1).flatten().tolist()[0] +# 将每个样本放入对应类别的列表中 +class1 = np.array([Y[i] for i in range(N) if category[i] == 0]) +class2 = np.array([Y[i] for i in range(N) if category[i] == 1]) + +# 绘制聚类结果 +plt.plot(class1[:, 0], class1[:, 1], 'rs', label="class1") +plt.plot(class2[:, 0], class2[:, 1], 'bo', label="class2") +plt.legend(loc="best") +plt.title("GMM Clustering By EM Algorithm") +plt.show() +``` + +#### 期望最大化算法的特点 + +* 1.EM算法中,由于似然函数是有界的,并且算法的每一步迭代都使似然函数增加,根据单调有界定理可以证明EM算法具有收敛性。 +* 2.EM算法是一种初始值敏感的算法,选取不同初始参数会有不同的最终结果; +* 3.EM算法得到的不会是全局最优,每次迭代逼近的都是当前的局部最优。 diff --git a/assets/src/CA/CA.0.5.md b/assets/src/CA/CA.0.5.md new file mode 100644 index 00000000..c2aa4fd3 --- /dev/null +++ b/assets/src/CA/CA.0.5.md @@ -0,0 +1,77 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 聚类分析(Cluster Analysis) + +聚类分析指将物理或抽象对象的集合分组为由类似的对象组成的多个类的分析过程。它是一种重要的人类行为。 +聚类分析的目标就是在相似的基础上收集数据来分类。聚类源于很多领域,包括数学,计算机科学,统计学,生物学和经济学。在不同的应用领域,很多聚类技术都得到了发展,这些技术方法被用作描述数据,衡量不同数据源间的相似性,以及把数据源分类到不同的簇中。 + +聚类与分类的不同在于,聚类所要求划分的类是未知的。 +聚类是将数据分类到不同的类或者簇这样的一个过程,所以同一个簇中的对象有很大的相似性,而不同簇间的对象有很大的相异性。 +从统计学的观点看,聚类分析是通过数据建模简化数据的一种方法。传统的统计聚类分析方法包括系统聚类法、分解法、加入法、动态聚类法、有序样品聚类、有重叠聚类和模糊聚类等。采用k-均值、k-中心点等算法的聚类分析工具已被加入到许多著名的统计分析软件包中,如SPSS、SAS等。 + +从机器学习的角度讲,簇相当于隐藏模式。聚类是搜索簇的无监督学习过程。与分类不同,无监督学习不依赖预先定义的类或带类标记的训练实例,需要由聚类学习算法自动确定标记,而分类学习的实例或数据对象有类别标记。聚类是观察式学习,而不是示例式的学习。 +聚类分析是一种探索性的分析,在分类的过程中,人们不必事先给出一个分类的标准,聚类分析能够从样本数据出发,自动进行分类。聚类分析所使用方法的不同,常常会得到不同的结论。不同研究者对于同一组数据进行聚类分析,所得到的聚类数未必一致。 +从实际应用的角度看,聚类分析是数据挖掘的主要任务之一。而且聚类能够作为一个独立的工具获得数据的分布状况,观察每一簇数据的特征,集中对特定的聚簇集合作进一步地分析。聚类分析还可以作为其他算法(如分类和定性归纳算法)的预处理步骤。 + +聚类分析是一个富有挑战性的研究领域,对数据挖掘中聚类分析的一些要求: +* 可伸缩性(scalability)。实际应用要求聚类算法能够处理大数据集,且时间复杂度不能太高(最好是多项式时间),消耗的内存空间也有限。目前,为了将算法拓展到超大数据库(VLDB)领域,研究人员已经进行了许多有益的尝试,包括:增量式挖掘、可靠的采样、数据挤压(data squashing)等。其中,数据挤压技术首先通过扫描数据来获得数据的统计信息,然后在这些统计信息的基础上进行聚类分析。比如BIRCH 算法中使用CF树就是属于数据挤压技术。 + +* 能够处理不同类型的属性。现实中的数据对象己远远超出关系型数据的范畴,比如空间数据、多媒体数据、遗传学数据、时间序列数据、文本数据、万维网上的数据、以及目前逐渐兴起的数据流。这些数据对象的属性类型往往是由多种数据类型综合而成的。 + +* 能够发现任意形状的簇。 + +* 尽量减少用于决定输入参数的领域知识。 + +* 能够处理噪声数据及孤立点。 + +* 对输入数据记录的顺序不敏感。 + +* 高维性(high-dimensional)。一个数据集可能包含若干维。较高的维数给聚类分析带来两个问题:首先,不相关的属性削弱了数据汇聚的趋势,使得数据分布非常稀疏。尽管这种情况在低维空间中并不多见,但是随着维数的增加,不相关属性的出现概率及数量也会增加,最后导致数据空间中几乎不存在簇。其次,高维使得在低维中很有效的区分数据的标准在高维空间中失效了。如在高维空间中,数据点到最近邻点的距离与到其他点的距离没有多少分别,从而导致最近邻查询在高维空间中不稳定,此时若根据接近度来划分簇,结果是不可信的。 + +* 能够根据用户指定的约束条件进行聚类。 + +* 聚类结果具有可解释性和可用性。 + + +聚类分析是一种分类技术。与多元分析的其他方法相比,该方法较为粗糙,理论上还不完善,但应用方面取得了很大成功。与回归分析、判别分析一起被称为多元分析的三大方法。 + +聚类的目的——根据已知数据( 一批观察个体的许多观测指标) , 按照一定的数学公式计算各观察个体或变量(指标)之间亲疏关系的统计量(距离或相关系数等)。 根据某种准则( 最短距离法、最长距离法、中间距离法、重心法等),使同一类内的差别较小,而类与类之间的差别较大,最终将观察个体或变量分为若干类。 + +根据分类的方法可将聚类分析分为:系统聚类、快速聚类、有序聚类。 +根据分类的对象可将聚类分析分为:Q型——样品聚类clustering for individuals;R型——指标聚类clustering for variables。 + +#### 应用示例 +```python +from numpy import vstack +from scipy.cluster.vq import kmeans,vq +from matplotlib.finance import quotes_historical_yahoo_ochl +from datetime import datetime + +start = datetime(2014,7,1) +end = datetime(2014,9,30) +listDji = ['AXP','BA','CAT','CSCO','CVX','DD','DIS','GE', +'GS','HD','IBM', 'INTC','JNJ','JPM','KO','MCD','MMM','MRK', +'MSFT','NKE','PFE','PG','T','TRV', 'UNH','UTX','V','VZ','WMT','XOM'] #30家公司代号 + +'''初始化两个二维数组''' +quotes = [ [0 for col in range(90)] for row in range(30)] +listTemp = [ [0 for col in range(90)] for row in range(30)] + +for i in range(30): + quotes[i] = quotes_historical_yahoo_ochl(listDji[i], start, end) #摘录数据,放入quotes + +days = len(quotes[0]) +for i in range(30): + for j in range(days-1): + if (quotes[i][j][2] and quotes[i][j+1][2] and (quotes[i][j+1][2]>=quotes[i][j][2])): #比较前后两天的收盘价 + listTemp[i][j] = 1.0 + else: + listTemp[i][j] = -1.0 + +data = vstack(listTemp) +centroids,_ = kmeans(data,4) #float or double is supported +result,_= vq(data,centroids) +print(result) +``` diff --git a/assets/src/CART/CART.md b/assets/src/CART/CART.md index 201877e3..e6c6444a 100644 --- a/assets/src/CART/CART.md +++ b/assets/src/CART/CART.md @@ -31,20 +31,28 @@ CART算法原理:CART决策树是结构简洁的二叉树,采用一种二分

对于给定样本集合D,其基尼指数的计算为: +

+ 如果样本集合D根据特征A是否取某一可能值a被分割成D1和D2两部分,即:,D2=D-D1 则在特征A的条件下,集合D的基尼指数计算公式为: +

+ 基尼指数Gini(D)表示集合D的不确定性,基尼指数Gini(D,A)表示经A=a分割后集合D的不确定性。基尼指数值越大,样本集合的不确定性也就越大。 -(2)回归树原理:回归树用平方误差最小化准则,进行特征选择,生成二叉树。将输入空间划分为M个区域R1,R2,…,Rm,则生成的回归树模型表示为: + +(2)回归树原理:回归树用平方误差最小化准则,进行特征选择,生成二叉树。将输入空间划分为M个区域R1,R2,…,Rm,则生成的回归树模型表示为: +

+ 其中cm表示单元Rm上的最小误差平方的最优解. + 2、决策树的剪枝 CART算法对于决策树剪枝方法,采用代价复杂度模型,通过交叉验证来估计对预测样本集的误分类损失,产生最小交叉验证误分类估计树。 diff --git a/assets/src/CAS/CAS.md b/assets/src/CAS/CAS.md new file mode 100644 index 00000000..7fefbfc0 --- /dev/null +++ b/assets/src/CAS/CAS.md @@ -0,0 +1,150 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +机器学习是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。主要研究计算机怎样模拟或实现人类的学习行为,以获取新的知识和技能,重新组织已有的知识结构,不断的改善自身的性能。 + +机器学习理论主要是设计和分析一些让计算机可以自动“学习”的算法。这些算法是一类能从数据中自动分析获得规律,并利用规律对未知数据进行预测的算法。简而言之,机器学习主要以数据为基础,通过大数据本身,运用计算机自我学习来寻找数据本身的规律,而这是机器学习与统计分析的基本区别。 + +机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 + +(1)监督学习:从给定的训练数据集中学习出一个函数,当新的数据输入时,可以根据函数预测相应的结果。监督学习的训练集要求是包括输入和输出,也就是特征和目标。训练集中的目标是有标注的。如今机器学习已固有的监督学习算法有可以进行分类的,例如贝叶斯分类,SVM,ID3,C4.5以及分类决策树,以及现在最火热的人工神经网络,例如BP神经网络,RBF神经网络,Hopfield神经网络、深度信念网络和卷积神经网络等。人工神经网络是模拟人大脑的思考方式来进行分析,在人工神经网络中有显层,隐层以及输出层,而每一层都会有神经元,神经元的状态或开启或关闭,这取决于大数据。同样监督机器学习算法也可以作回归,最常用便是逻辑回归。 + +(2)无监督学习:与有监督学习相比,无监督学习的训练集的类标号是未知的,并且要学习的类的个数或集合可能事先不知道。常见的无监督学习算法包括聚类和关联,例如K均值法、Apriori算法。 + +(3)半监督学习:介于监督学习和无监督学习之间,例如EM算法。 + +如今的机器学习领域主要的研究工作在三个方面进行:1)面向任务的研究,研究和分析改进一组预定任务的执行性能的学习系统;2)认知模型,研究人类学习过程并进行计算模拟;3)理论的分析,从理论的层面探索可能的算法和独立的应用领域算法。 + +#### 聚类分析 + +聚类分析(Cluster analysis,亦称为群集分析)是对于统计数据分析的一门技术,在许多领域受到广泛应用,包括机器学习,数据挖掘,模式识别,图像分析以及生物信息。聚类是把相似的对象通过静态分类的方法分成不同的组别或者更多的子集(subset),这样让在同一个子集中的成员对象都有相似的一些属性,常见的包括在坐标系中更短的空间距离等。 + +一般把数据聚类归纳为一种非监督学习。 + +数据聚类算法可以分为结构性或者分散性。结构性算法利用以前成功使用过的聚类器进行分类,而分散型算法则是一次确定所有分类。结构性算法可以从上至下或者从下至上双向进行计算。从下至上算法从每个对象作为单独分类开始,不断融合其中相近的对象。而从上至下算法则是把所有对象作为一个整体分类,然后逐渐分小。 + +分割式聚类算法,是一次性确定要产生的类别,这种算法也已应用于从下至上聚类算法。 + +基于密度的聚类算法,是为了挖掘有任意形状特性的类别而发明的。此算法把一个类别视为数据集中大于某阈值的一个区域。DBSCAN和OPTICS是两个典型的算法。 + +许多聚类算法在执行之前,需要指定从输入数据集中产生的分类个数。除非事先准备好一个合适的值,否则必须决定一个大概值,关于这个问题已经有一些现成的技术。 + +在已经得到距离值之后,元素间可以被联系起来。通过分离和融合可以构建一个结构。传统上,表示的方法是树形数据结构, 然后对该结构进行修剪。树的根节点表示一个包含所有项目的类别,树叶表示与个别的项目相关的类别。 + +层次聚类算法,要么是自下向上聚集型的,即从叶子节点开始,最终汇聚到根节点;要么是自顶向下分裂型的,即从根节点开始,递归的向下分裂。 + +任意非负值的函数都可以用于衡量一对观测值之间的相似度。决定一个类别是否分裂或者合并的是一个连动的标准,它是两两观测值之间距离的函数。 + +在一个指定高度上切割此树,可以得到一个相应精度的分类。 + + +主要可分为:划分方法(partitioning method),层次方法(hierarchical method),基于密度的方法(density-basedmethod),基于网格的方法(grid-based method),和基于模型的方法(model-based method)。 + +* 分层聚类算法原理 + +开始时将N个观测量(变量)视为N类;规定相似性统计量的测度,并计算相似系数矩阵; + +找出最大相似系数的观测量(变量)组:Sij为类Gi与类Gj的相似系数,S为相似系数矩阵或不相似系数矩阵,若S为相似系数矩阵,则依据Spq最小者挑选Gp与Gq (p>q),若S为不相似系数(距离)矩阵,则依据Spq最大者挑选Gp与Gq进行聚类,即将Gp与Gq合并成一个新类Gt(t=q); + +计算新类Gt与当前各类的相似性系数,更新相似系数矩阵S:将得到的新的系数代换与q相关的行与列,删除与p有关的行与列; + +重复过程:寻找最大相似系数观测变量组和计算相似系数矩阵,直至聚为一类; + +一共有六种分层聚类的方法,五种距离尺度标准。如:明考斯基距离、马氏距离、匹配距离等。 + +* 快速聚类算法原理 + +快速聚类以距离衡量样本间的亲疏程度,但其最终结果不是聚成一类,而是根据各聚类中心,将所有样本点聚成指定的类数。 + +首先设置K个聚类的初始类中心点,计算所有样本点到K个类中心点的距离,按照距离最短的原则,将所有样本分派到各中心点所在的类中,形成一个新的K类,完成一次迭代过程。在下一次迭代过程中,重新计算K个类的类中心点,重复上述过程,直到达到指定的迭代次数或达到终止迭代的判断要求为止。 + +其中K个聚类初始中心点的选取有以下方法: + +1.可以选取前K个观测变量值为初始中心点; + +2.最小最大原则:先选择所有样本数据中距离最远的两个值;并且选择第三个值,使得与前两个聚点的距离最小者等于所有其余数据的较小距离中最大的,依次按这个原则选取,直到最终确定K个中心点;用公式可以表示为: + +

+ +

+ +3.模糊聚类算法原理 + +糊聚类算法根据研究对象本身的属性来构造模糊矩阵,在此基础上根据一定的隶属度来确定其分类系。系统的模糊聚类分析功能根据专家对研究对象的各指标进行打分得出原始数据。通过对原始数据进行变换、计算模糊相似矩阵、利用传递闭包法建立模糊等价矩阵,并根据给定不同的置信水平,求截阵等一系列过程对研究对象进行聚类得出模糊相似阵、分类关系阵和分类关系表。模糊聚类的具体算法过程如下: + +a.对原始数据进行变换。变换方法通常有标准化变换、极差变换、对数变换等。 +b.计算模糊相似矩阵。选取在[-1,1]区间中的普通相似系数rij*=cosθ构成相似系数矩阵 + +

+ +

+ +在此基础上做如下变换: +

+ +

+ +使得rij*被压缩到[0,1]区间内,R=rij构成了一个模糊矩阵。 + +c.建立模糊等价矩阵。对模糊矩阵进行褶积计算: R→R2→R3→…→Rn,经过有限次褶积后使得Rn。R=Rn,由此得到模糊分类关系Rn。模糊褶积的运算法则:设A和B是n×p和p×m的模糊矩阵,则乘积C=A*B为n×m阵,其元素为: + +

+ +

+ +符号的含义是: + +

+ +

+

+ +

+ +d.进行聚类。给定不同的置信水平λ,求Rλ截阵,找出R的λ显示,得到普通的分类关系Rλ。当λ=1时,每个样品自成一类,随λ值的降低,由细到粗逐渐并类。 + +4..基于密度的聚类 +为了发现任意形状的聚类结果,提出了基于密度的聚类方法。这类方法将簇看作是数据空间中由低密度区域分割开的高密度对象区域。 + +DBSCAN(Density-Based Spatial Clustering of Applications with Noise)是一个基于密度的聚类算法。该算法将具有足够高密度的区域划分为簇,并可以在带有“噪音”的空间数据库中发现任意形状的聚类。它定义簇为密度相连的点的最大集合。基于密度的聚类的基本想法涉及一些新的定义。 + +n 一个给定对象周围半径ε内的区域称为该对象的ε-邻域。 + +n 如果一个对象的ε-邻域至少包含最小数目MinPts 的对象,那么该对象称为核心对象。 + +n 给定一个对象集合D,如果p是在q 的ε–邻域内,而q是一个核心对象,我们说对象p从对象q出发是直接密度可达的。 + +n 如果存在一个对象链p1,p2,…,pn,p1=q,pn=p,对pi∈ D,1≤i≤n,pi+1 是从pi关于ε和 MinPts直接密度可达的,则对象p是从对象q关于ε和MinPts 密度可达的(density-reachable)。 + +n 如果对象集合D中存在一个对象o,使得对象p和q是从o关于ε和MinPts 密度可达的,那么对象p和q是关于ε和MinPts 密度相连的(density-connected)。 + +DBSCAN 通过检查数据库中每个点的ε-邻域来寻找聚类。如果一个点p的ε-邻域包含多于MinPts个点,则创建一个以p作为核心对象的新簇。DBSCAN 然后反复地寻找从这些核心对象直接密度可达的对象,这个过程可能涉及几个密度可达簇的合并。当没有新的点可以被添加到任何簇时,该过程结束。 + +#### 应用领域 +在商业上,聚类能帮助市场分析人员从客户基本库中发现不同的客户群,并且用购买模式来刻画不同的客户群的特征。在生物学上,聚类能用于推导植物和动物的分类,对基因进行分类,获得对种群中固有结构的认识。聚类在地球观测数据库中相似地区的确定,汽车保险持有者的分组,及根据房子的类型,价值,和地理位置对一个城市中房屋的分组上也可以发挥作用。聚类也能用于对Web 上的文档进行分类,以发现信息。作为一个数据挖掘的功能,聚类分析能作为一个独立的工具来获得数据分布的情况,观察每个簇的特点,集中对特定的某些簇作进一步的分析。此外,聚类分析可以作为其他算法(如分类等)的预处理步骤,这些算法再在生成的簇上进行处理。 + + +#### 优缺点 + +优点: + +聚类分析模型的优点就是直观,结论形式简明 + +缺点: + +1. 收敛太慢 + +2. 算法复杂度高 + +3. 不能发现非凸形状的簇,或大小差别很大的簇 + +4. 需样本存在均值(限定数据种类) + +5. 需先确定聚类中心点的个数 + +6. 对噪声和离群点敏感 + +7. 最重要是结果不一定是全局最优,只能保证局部最优 + +不同的聚类方法,也有一定的差异性,但总体表现为:K均值稳定,谱聚类效果好, 层次聚类快。 diff --git a/assets/src/CBA/CBA.md b/assets/src/CBA/CBA.md index 39a1d72e..6d788700 100644 --- a/assets/src/CBA/CBA.md +++ b/assets/src/CBA/CBA.md @@ -1,6 +1,36 @@ ### Deeplearning Algorithms tutorial 谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! + AI的开发离不开算法那我们就接下来开始学习算法吧! +机器学习是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。主要研究计算机怎样模拟或实现人类的学习行为,以获取新的知识和技能,重新组织已有的知识结构,不断的改善自身的性能。 + +机器学习理论主要是设计和分析一些让计算机可以自动“学习”的算法。这些算法是一类能从数据中自动分析获得规律,并利用规律对未知数据进行预测的算法。简而言之,机器学习主要以数据为基础,通过大数据本身,运用计算机自我学习来寻找数据本身的规律,而这是机器学习与统计分析的基本区别。 + +机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 + +#### CBA +CBA(Classification base of Association)算法是一个基于关联规则进行分类的算法,该算法首先利用Apriori算法挖掘出的关联规则,然后进行分类判断。 + +CBA算法作为分类算法,它的判断依据是Apriori算法挖掘出的频繁项。如果一个项集中包含预先知道的属性,同时也包含分类属性值,然后计算该频繁项,能否计算出由已知属性推出决策属性的关联规则,如果满足规则的最小置信度的要求,那么可以把频繁项集中的决策属性值作为最后的分类结果。具体的算法细节如下: + +1.输入数据记录; +2.对属性值作数字替换,形成类似关联规则算法的事务记录; +3.根据转化的事务记录,进行Apriori算法计算,挖掘频繁项集; +4.输入查询的属性值,找出符合条件的频繁项集(包含查询属性和分类决策属性);如果找到这样的规则,则算分类成功,输出结果。 +Apriori使用逐层搜索的迭代方法。首先,通过扫描事务集,累计每个项的计数,并收集满足最小支持度的项,找出频繁1项集的集合,记为L1。然后用L1寻找频繁2项集的集合L2,依次类推,直到不能再找到频繁k项集。 + + +#### 算法背景 + +CBA算法是基于Apriori算法基础上,由Liu,Hsu和MA提出来的。主要是对已经挖掘出的关联规则,做分类判断,所以在某种程度上说CBA算法也是一种集成的挖掘算法。 + +#### 相关应用 + +CBA算法应用广泛,如可用在保险领域、生物学领域、地震研究等领域中。 + +如可用于消费市场价格分析,猜测顾客的消费习惯;网络安全领域中的入侵检测技术;可用在用于高校管理中,根据挖掘规则可以有效地辅助学校管理部门有针对性的开展贫困助学工作;也可用在移动通信领域中,指导运营商的业务运营和辅助业务提供商的决策制定等。 + +#### 优点 -#### CBA \ No newline at end of file +优点:分类的准确度较高,在大量数据集上比C4.5更精确。 diff --git a/assets/src/DL/DL.0.1.md b/assets/src/DL/DL.0.1.md new file mode 100644 index 00000000..f4e9aa74 --- /dev/null +++ b/assets/src/DL/DL.0.1.md @@ -0,0 +1,33 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 深度学习(Deep Learning) +深度学习的概念源于人工神经网络的研究。含多隐层的多层感知器就是一种深度学习结构。深度学习通过组合低层特征形成更加抽象的高层表示属性类别或特征,以发现数据的分布式特征表示。 + +深度学习的概念由Hinton等人于2006年提出。基于深度置信网络(DBN)提出非监督贪心逐层训练算法,为解决深层结构相关的优化难题带来希望,随后提出多层自动编码器深层结构。此外Lecun等人提出的卷积神经网络是第一个真正多层结构学习算法,它利用空间相对关系减少参数数目以提高训练性能。 + +深度学习是机器学习研究中的一个新的领域,其动机在于建立、模拟人脑进行分析学习的神经网络,它模仿人脑的机制来解释数据,例如图像,声音和文本。深度学习是无监督学习的一种。 + +深度学习的概念源于人工神经网络的研究。含多隐层的多层感知器就是一种深度学习结构。深度学习通过组合低层特征形成更加抽象的高层表示属性类别或特征,以发现数据的分布式特征表示。 + +Deep learning本身算是machine learning的一个分支,简单可以理解为neural network的发展。大约二三十年前,neural network曾经是ML领域特别火热的一个方向,但是后来确慢慢淡出了,原因包括以下几个方面: + +(1)比较容易过拟合,参数比较难tune,而且需要不少trick; + +(2)训练速度比较慢,在层次比较少(小于等于3)的情况下效果并不比其它方法更优; + +所以中间有大约20多年的时间,神经网络被关注很少,这段时间基本上是SVM和boosting算法的天下。但是,一个痴心的老先生Hinton,他坚持了下来,并最终(和其它人一起Bengio、Yann.lecun等)提成了一个实际可行的deep learning框架。 + +Deep learning与传统的神经网络之间有相同的地方也有很多不同。 + +二者的相同在于deep learning采用了神经网络相似的分层结构,系统由包括输入层、隐层(多层)、输出层组成的多层网络,只有相邻层节点之间有连接,同一层以及跨层节点之间相互无连接,每一层可以看作是一个logistic regression模型;这种分层结构,是比较接近人类大脑的结构的。 + +深度学习(Deep Learning)的应用算法有: +* 深度信念网络(Deep Belief Machines) +* 深度卷积神经网络(Deep Convolutional Neural Networks) +* 深度递归神经网络(Deep Recurrent Neural Networks) +* 分层时间记忆(Hierarchical Temporal Memory) +* 深度玻尔兹曼机(Deep Boltzmann Machine) +* 堆叠自动编码器(Stacked Boltzmann Machine) +* 生成式对抗网络(Generative Adversarial Networks) diff --git a/assets/src/DL/DL.0.2.md b/assets/src/DL/DL.0.2.md new file mode 100644 index 00000000..55386c8d --- /dev/null +++ b/assets/src/DL/DL.0.2.md @@ -0,0 +1,80 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 深度信念网络(Deep Belief Machines) +深度信念网络 (Deep Belief Network, DBN) 由 Geoffrey Hinton 在 2006 年提出。它是一种生成模型,通过训练其神经元间的权重,我们可以让整个神经网络按照最大概率来生成训练数据。我们不仅可以使用 DBN 识别特征、分类数据,还可以用它来生成数据。 +深度信念网络(Deep Belief Network, DBN)由多层神经元构成,这些神经元又分为显性神经元和隐性神经元(以下简称显元和隐元)。显元用于接受输入,隐元用于提取特征。因此隐元也有个别名,叫特征检测器 (feature detectors)。最顶上的两层间的连接是无向的,组成联合内存 (associative memory)。较低的其他层之间有连接上下的有向连接。最底层代表了数据向量 (data vectors),每一个神经元代表数据向量的一维。 + +深度信念网络(Deep Belief Network, DBN)组成元件是受限玻尔兹曼机 (Restricted Boltzmann Machines, RBM)。训练 DBN 的过程是一层一层地进行的。在每一层中,用数据向量来推断隐层,再把这一隐层当作下一层 (高一层) 的数据向量。 + +

+ +

+ +如上图所示用两个限制玻尔兹曼机堆叠起来,构成深度信念网络(Deep Belief Nets, 简称DBN)。 + +* 利用输入,生成第一个限制玻尔兹曼机,得到输入的特征。 +* 利用上面得到的输入的特征,生成每二个限制玻尔兹曼机,得到特征的特征。 +* 依次循环,可以得到多个限制玻尔兹曼机。 +* 把得到次序到多个限制玻尔兹曼机堆叠起来,构成一个DBN。 +* 以上是一种贪婪的训练堆叠方式,对网络的预训练非常好。 + +这样得到的效果跟autoencoder的堆叠一致。 + +wake-sleep算法:在分类问题中,DBN的最底层可以是已知的label层,如下图: +

+ +

+ +上图是MNIST数字识别的一个任务,输入是28*28的图片,输出是0到9的数字。 + +在经过上面提到的贪婪地堆叠训练后,再加上一层label层进行训练。然后再利用wake-sleep算法进行调优: +* wake: 认知过程,通过外界的特征和向上的权重 (认知权重) 产生每一层的抽象表示 (结点状态) ,并且使用梯度下降修改层间的下行权重 (生成权重) 。自底向上,进行训练 +* sleep: 生成过程,通过顶层表示 (醒时学得的概念) 和向下权重,生成底层的状态,同时修改层间向上的权重。自项向下,进行训练 + +在上面的训练完成后,如果对最上的两层进行随机的Gibbs采样,然后再逐渐从顶到底,生成的图像就是0到9中的一个图像。 +感觉这个跟人回忆、画画、做梦的过程非常像。 +

+ +

+由stuff、image、label的构成,是右边这种模式,而非左边那种。所以,一个更好的方式是直接从image,进行非监督还原成stuff,然后再学习stuff与label的关系。这也就是非监督的预训练有效的原因。 + +#### 应用示例 +```python +import numpy as np +from rbm import * +class dbn: + def __init__(self,sizes = [],learning_rate = 0.01,numepochs = 1): + print 'dbn init ,sizes:',sizes,', numepochs:',numepochs + self.sizes = sizes + self.rbms = [] + self.learning_rate = learning_rate + self.numepochs = numepochs + + for i in range(len(self.sizes)-1): + self.rbms.append(rbm(sizes[i:i+2],self.learning_rate,self.numepochs)) + + def train(self,X): + #for i in range(self.numepochs): + for j in range(len(self.sizes)-1): + self.rbms[j].train(X) + X = self.rbms[j].v2h(X) + + def v2h(self,X): + for j in range(len(self.sizes)-1): + X = self.rbms[j].v2h(X) + return X + + def h2v(self,X): + for j in range(len(self.sizes)-1): + if j == len(self.sizes)-2: + X = self.rbms[len(self.sizes)-j-2].h2v(X,False); + else: + X = self.rbms[len(self.sizes)-j-2].h2v(X) + return X + + def predict(self, X): + return self.h2v(self.v2h(X)) + +``` diff --git a/assets/src/DL/DL.0.3.md b/assets/src/DL/DL.0.3.md new file mode 100644 index 00000000..08e6668d --- /dev/null +++ b/assets/src/DL/DL.0.3.md @@ -0,0 +1,222 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 深度卷积神经网络(Deep Convolutional Neural Networks) + +深度卷积神经网络(DCNN)在特征识别相关任务中取得的效果,远比传统方法好。因此,DCNN常用于图像识别、语音识别等。但是,因为深度卷积神经网络结构庞大,一般都会包含几十个神经层,每一层,又有数百至数千个神经元;同时,DCNN任意两层之间神经元的相互影响错综复杂。这两个主要的因素,导致DCNN难以理解、分析。为此,用户很难从失败或成功的例子中学习到如何设计一个好的卷积神经网络。因此,设计一个效果好的神经网络,往往需要依靠大量的尝试。 + +而卷积神经网络(Convolutional Neural Network,CNN)是一种前馈神经网络,它的人工神经元可以响应一部分覆盖范围内的周围单元,对于大型图像处理有出色表现。 它包括卷积层(convolutional layer)和池化层(pooling layer)。 + +卷积神经网络是近年发展起来,并引起广泛重视的一种高效识别方法。20世纪60年代,Hubel和Wiesel在研究猫脑皮层中用于局部敏感和方向选择的神经元时发现其独特的网络结构可以有效地降低反馈神经网络的复杂性,继而提出了卷积神经网络(Convolutional Neural Networks-简称CNN)。现在,CNN已经成为众多科学领域的研究热点之一,特别是在模式分类领域,由于该网络避免了对图像的复杂前期预处理,可以直接输入原始图像,因而得到了更为广泛的应用。 K.Fukushima在1980年提出的新识别机是卷积神经网络的第一个实现网络。随后,更多的科研工作者对该网络进行了改进。其中,具有代表性的研究成果是Alexander和Taylor提出的“改进认知机”,该方法综合了各种改进方法的优点并避免了耗时的误差反向传播。 + +卷积神经网络的基本结构包括两层,其一为特征提取层,每个神经元的输入与前一层的局部接受域相连,并提取该局部的特征。一旦该局部特征被提取后,它与其它特征间的位置关系也随之确定下来;其二是特征映射层,网络的每个计算层由多个特征映射组成,每个特征映射是一个平面,平面上所有神经元的权值相等。特征映射结构采用影响函数核小的sigmoid函数作为卷积网络的激活函数,使得特征映射具有位移不变性。此外,由于一个映射面上的神经元共享权值,因而减少了网络自由参数的个数。卷积神经网络中的每一个卷积层都紧跟着一个用来求局部平均与二次提取的计算层,这种特有的两次特征提取结构减小了特征分辨率。 + +卷积神经网络主要用来识别位移、缩放及其他形式扭曲不变性的二维图形。由于CNN的特征检测层通过训练数据进行学习,所以在使用CNN时,避免了显式的特征抽取,而隐式地从训练数据中进行学习;再者由于同一特征映射面上的神经元权值相同,所以网络可以并行学习,这也是卷积网络相对于神经元彼此相连网络的一大优势。卷积神经网络以其局部权值共享的特殊结构在语音识别和图像处理方面有着独特的优越性,其布局更接近于实际的生物神经网络,权值共享降低了网络的复杂性,特别是多维输入向量的图像可以直接输入网络这一特点避免了特征提取和分类过程中数据重建的复杂度。 + +

+ +

+ +一个典型的卷积神经网络包含两个卷积层(convolution layer),两个池化层(pooling layer)和一个全连接层(fully connected layer)。 + +

+ +

+ +卷积层,采用各种卷积核对输入图片进行卷积处理,基本卷积过程如图2所示。卷积操作具有平移不变性。因而,能够支持神经元学习到鲁棒性比较高的特征。 + +

+ +

+池化层的操作,是一种降采样操作。该操作是在一个小区域内,采取一个特定的值作为输出值。比如图3,在每个特定的小区域内,我们选取最大值作为输出值。池化层的操作可以达到一定的空间不变性效果。 + +卷积神经网络中的激励函数,根据一系列的输入值,神经元之间连接的权值以及激励规则,刺激神经元。 + +卷积神经网络中的损失函数,在训练阶段,用于评估网络输出结果与实际值的差异。然后用损失函数的值更新每个神经元之间的权重值。卷积神经网络的训练目的就是最小化损失函数值。 + +深度卷积神经网络在许多模式识别任务上较传统的方法而言已经展示了很大的提升,比如语音识别,图像分类和视频分类。 + + +#### 应用示例 +```python +import argparse +import os + +import matplotlib +matplotlib.use('AGG') +import matplotlib.pyplot as plt +import numpy as np +from keras.datasets import cifar10 +from keras.layers import (Activation, Conv3D, Dense, Dropout, Flatten, + MaxPooling3D) +from keras.layers.advanced_activations import LeakyReLU +from keras.losses import categorical_crossentropy +from keras.models import Sequential +from keras.optimizers import Adam +from keras.utils import np_utils +from keras.utils.vis_utils import plot_model +from sklearn.model_selection import train_test_split + +import videoto3d +from tqdm import tqdm + + +def plot_history(history, result_dir): + plt.plot(history.history['acc'], marker='.') + plt.plot(history.history['val_acc'], marker='.') + plt.title('model accuracy') + plt.xlabel('epoch') + plt.ylabel('accuracy') + plt.grid() + plt.legend(['acc', 'val_acc'], loc='lower right') + plt.savefig(os.path.join(result_dir, 'model_accuracy.png')) + plt.close() + + plt.plot(history.history['loss'], marker='.') + plt.plot(history.history['val_loss'], marker='.') + plt.title('model loss') + plt.xlabel('epoch') + plt.ylabel('loss') + plt.grid() + plt.legend(['loss', 'val_loss'], loc='upper right') + plt.savefig(os.path.join(result_dir, 'model_loss.png')) + plt.close() + + +def save_history(history, result_dir): + loss = history.history['loss'] + acc = history.history['acc'] + val_loss = history.history['val_loss'] + val_acc = history.history['val_acc'] + nb_epoch = len(acc) + + with open(os.path.join(result_dir, 'result.txt'), 'w') as fp: + fp.write('epoch\tloss\tacc\tval_loss\tval_acc\n') + for i in range(nb_epoch): + fp.write('{}\t{}\t{}\t{}\t{}\n'.format( + i, loss[i], acc[i], val_loss[i], val_acc[i])) + + +def loaddata(video_dir, vid3d, nclass, result_dir, color=False, skip=True): + files = os.listdir(video_dir) + X = [] + labels = [] + labellist = [] + + pbar = tqdm(total=len(files)) + + for filename in files: + pbar.update(1) + if filename == '.DS_Store': + continue + name = os.path.join(video_dir, filename) + label = vid3d.get_UCF_classname(filename) + if label not in labellist: + if len(labellist) >= nclass: + continue + labellist.append(label) + labels.append(label) + X.append(vid3d.video3d(name, color=color, skip=skip)) + + pbar.close() + with open(os.path.join(result_dir, 'classes.txt'), 'w') as fp: + for i in range(len(labellist)): + fp.write('{}\n'.format(labellist[i])) + + for num, label in enumerate(labellist): + for i in range(len(labels)): + if label == labels[i]: + labels[i] = num + if color: + return np.array(X).transpose((0, 2, 3, 4, 1)), labels + else: + return np.array(X).transpose((0, 2, 3, 1)), labels + + +def main(): + parser = argparse.ArgumentParser( + description='simple 3D convolution for action recognition') + parser.add_argument('--batch', type=int, default=128) + parser.add_argument('--epoch', type=int, default=100) + parser.add_argument('--videos', type=str, default='UCF101', + help='directory where videos are stored') + parser.add_argument('--nclass', type=int, default=101) + parser.add_argument('--output', type=str, required=True) + parser.add_argument('--color', type=bool, default=False) + parser.add_argument('--skip', type=bool, default=True) + parser.add_argument('--depth', type=int, default=10) + args = parser.parse_args() + + img_rows, img_cols, frames = 32, 32, args.depth + channel = 3 if args.color else 1 + fname_npz = 'dataset_{}_{}_{}.npz'.format( + args.nclass, args.depth, args.skip) + + vid3d = videoto3d.Videoto3D(img_rows, img_cols, frames) + nb_classes = args.nclass + if os.path.exists(fname_npz): + loadeddata = np.load(fname_npz) + X, Y = loadeddata["X"], loadeddata["Y"] + else: + x, y = loaddata(args.videos, vid3d, args.nclass, + args.output, args.color, args.skip) + X = x.reshape((x.shape[0], img_rows, img_cols, frames, channel)) + Y = np_utils.to_categorical(y, nb_classes) + + X = X.astype('float32') + np.savez(fname_npz, X=X, Y=Y) + print('Saved dataset to dataset.npz.') + print('X_shape:{}\nY_shape:{}'.format(X.shape, Y.shape)) + + # Define model + model = Sequential() + model.add(Conv3D(32, kernel_size=(3, 3, 3), input_shape=( + X.shape[1:]), border_mode='same')) + model.add(Activation('relu')) + model.add(Conv3D(32, kernel_size=(3, 3, 3), border_mode='same')) + model.add(Activation('softmax')) + model.add(MaxPooling3D(pool_size=(3, 3, 3), border_mode='same')) + model.add(Dropout(0.25)) + + model.add(Conv3D(64, kernel_size=(3, 3, 3), border_mode='same')) + model.add(Activation('relu')) + model.add(Conv3D(64, kernel_size=(3, 3, 3), border_mode='same')) + model.add(Activation('softmax')) + model.add(MaxPooling3D(pool_size=(3, 3, 3), border_mode='same')) + model.add(Dropout(0.25)) + + model.add(Flatten()) + model.add(Dense(512, activation='sigmoid')) + model.add(Dropout(0.5)) + model.add(Dense(nb_classes, activation='softmax')) + + model.compile(loss=categorical_crossentropy, + optimizer=Adam(), metrics=['accuracy']) + model.summary() + plot_model(model, show_shapes=True, + to_file=os.path.join(args.output, 'model.png')) + + X_train, X_test, Y_train, Y_test = train_test_split( + X, Y, test_size=0.2, random_state=43) + + history = model.fit(X_train, Y_train, validation_data=(X_test, Y_test), batch_size=args.batch, + epochs=args.epoch, verbose=1, shuffle=True) + model.evaluate(X_test, Y_test, verbose=0) + model_json = model.to_json() + if not os.path.isdir(args.output): + os.makedirs(args.output) + with open(os.path.join(args.output, 'ucf101_3dcnnmodel.json'), 'w') as json_file: + json_file.write(model_json) + model.save_weights(os.path.join(args.output, 'ucf101_3dcnnmodel.hd5')) + + loss, acc = model.evaluate(X_test, Y_test, verbose=0) + print('Test loss:', loss) + print('Test accuracy:', acc) + plot_history(history, args.output) + save_history(history, args.output) + + +if __name__ == '__main__': + main() +``` diff --git a/assets/src/DL/DL.0.4.md b/assets/src/DL/DL.0.4.md new file mode 100644 index 00000000..23c62f29 --- /dev/null +++ b/assets/src/DL/DL.0.4.md @@ -0,0 +1,299 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 深度递归神经网络(Deep Recurrent Neural Networks) + +递归神经网络(RNN)是两种人工神经网络的总称。一种是时间递归神经网络(Recurrent Neural Networks,RNN),又名循环神经网络,另一种是结构递归神经网络(recursive neural network)。时间递归神经网络的神经元间连接构成矩阵,而结构递归神经网络利用相似的神经网络结构递归构造更为复杂的深度网络。RNN一般指代时间递归神经网络。单纯递归神经网络因为无法处理随着递归,权重指数级爆炸或消失的问题(Vanishing gradient problem),难以捕捉长期时间关联;而结合不同的LSTM可以很好解决这个问题。 + +时间递归神经网络可以描述动态时间行为,因为和前馈神经网络(feedforward neural network)接受较特定结构的输入不同,RNN将状态在自身网络中循环传递,因此可以接受更广泛的时间序列结构输入。手写识别是最早成功利用RNN的研究结果 + +循环神经网络不同于传统的FNNs(Feed-forward Neural Networks,前向反馈神经网络),循环神经网络引入了定向循环,能够处理那些输入之间前后关联的问题。 +

+ +

+ +循环神经网络的目的是用来处理序列数据的问题。通常在传统的神经网络模型中,是从输入层到隐含层再到输出层,层与层之间是全连接的,每层之间的节点是无连接的。但是这种普通的神经网络对于很多问题却是无法解决的。比如你需要要预测一个句子的下一个单词是什么,一般需要用到前面的单词,因为一个句子中前后单词并不是独立的。RNNs之所以称为循环神经网路,即一个序列当前的输出与前面的输出也有关。对应的表现形式为网络会对前面的信息进行记忆并应用于当前输出的计算中,即隐藏层之间的节点不再无连接而是有连接的,并且隐藏层的输入不仅包括输入层的输出还包括上一时刻隐藏层的输出。理论上,RNNs能够对任何长度的序列数据进行处理。 +

+ +

+ +

+ +

+

循环神经网络进行展开成一个全神经网络的过程

+ + +时间递归神经网络包含输入单元(Input units),输入集标记为,而输出单元(Output units)的输出集则被标记为。RNNs还包含隐藏单元(Hidden units),我们将其输出集标记为,这些隐藏单元完成了最为主要的工作。你会发现,在图中:有一条单向流动的信息流是从输入单元到达隐藏单元的,与此同时另一条单向流动的信息流从隐藏单元到达输出单元。在某些情况下,RNNs会打破后者的限制,引导信息从输出单元返回隐藏单元,这些被称为“Back Projections”,并且隐藏层的输入还包括上一隐藏层的状态,即隐藏层内的节点可以自连也可以互连。 + +在深度递归神经网络中,它的主要作用是做什么呢? + + 时间递归神经网络已经被在实践中证明对NLP是非常成功的。如词向量表达、语句合法性检查、词性标注、机器翻译、图像描述生成等。在时间递归神经网络中,目前使用最广泛最成功的模型便是LSTMs(Long Short-Term Memory,长短时记忆模型)模型,该模型通常比vanilla RNNs能够更好地对长短时依赖进行表达,该模型相对于一般的RNNs,只是在隐藏层做了改变。 + + + 那么我们应该怎么训练时间递归神经网络呢? + + 对于递归神经网络的训练和对传统的人工神经网络训练一样。同样使用BP误差反向传播算法,不过这里有点区别。如果将RNNs进行网络展开,那么参数是共享的,而传统神经网络不是这样的。所以使用梯度下降算法中,每一步的输出不仅依赖当前步的网络,而且还依赖前面操作的网络的状态。该学习算法称为Backpropagation Through Time (BPTT).这里我们需要了解到的是,在vanilla RNNs训练中,BPTT无法解决长时依赖问题(即当前的输出与前面很长的一段序列有关,一般超过十步就无能为力了),因为BPTT会带来所谓的梯度消失或梯度爆炸问题(the vanishing/exploding gradient problem)。当然,有很多方法去解决这个问题,如LSTMs便是专门应对这种问题的。 + + + 接下来我们需要对RNNs进行扩展和模型改进. + +* 第一种:Simple RNNs(SRNs) + +SRNs是RNNs的一种特例,它是一个由三层网络组成的,并且在隐藏层增加了上下文单元,下图中的便是隐藏层,便是上下文单元。上下文单元节点与隐藏层中的节点的连接是固定的,并且权值也是固定的(值是多少),其实是一个上下文节点与隐藏层节点一一对应,并且值是确定的。在每一步中,使用标准的前向反馈进行传播,然后使用学习算法进行学习。上下文每一个节点保存其连接的隐藏层节点的上一步的输出,即保存上文,并作用于当前步对应的隐藏层节点的状态,即隐藏层的输入由输入层的输出与上一步的自己的状态所决定的。因此SRNs能够解决标准的多层感知机(MLP)无法解决的对序列数据进行预测的任务。 + +

+ +

+ +* 第二种:Bidirectional RNNs + + Bidirectional RNNs双向网络改进之处,假设当前的输出(第步的输出)不仅仅与前面的序列有关,并且还与后面的序列有关。例如:预测一个语句中缺失的词语那么就需要根据上下文来进行预测。Bidirectional RNNs是一个相对较简单的RNNs,是由两个RNNs上下叠加在一起组成的。输出由这两个RNNs的隐藏层的状态决定的。 + + +

+ +

+ +* 第三种: Deep(Bidirectional)RNNs + +Deep(Bidirectional)RNNs与Bidirectional RNNs相似,只是对于每一步的输入有多层网络。该网络便有更强大的表达与学习能力,但是复杂性也提高了,同时需要更多的训练数据。 + +

+ +

+ +* 第四种:Echo State Networks + + ESNs(回声状态网络)也是一种RNNs,但是它与传统的RNNs相差很大。回声状态网络具有三个特点: + +* 它的核心结构时一个随机生成、且保持不变的储备池(Reservoir),储备池是大规模的、随机生成的、稀疏连接(SD通常保持1%~5%,SD表示储备池中互相连接的神经元占总的神经元个数N的比例)的循环结构; +* 它的储备池到输出层的权值矩阵是唯一需要调整的部分; +* 通过简单的线性回归就可完成网络的训练。 + +回声状态网络是一种特殊类型的循环神经网络,其基本思想是:使用大规模随机连接的循环网络取代经典神经网络中的中间层,从而简化网络的训练过程。因此ESNs的关键是中间的储备池。网络中的参数包括:为储备池中节点的连接权值矩阵,为输入层到储备池之间的连接权值矩阵,表明储备池中的神经元之间是连接的,为输出层到储备池之间的反馈连接权值矩阵,表明储备池会有输出层来的反馈,为输入层、储备池、输出层到输出层的连接权值矩阵,表明输出层不仅与储备池连接,还与输入层和自己连接。表示输出层的偏置项。 + + 对于ESNs,关键是储备池的四个参数,如储备池内部连接权谱半径SR(,只有SR <1时,ESNs才能具有回声状态属性)、储备池规模N(即储备池中神经元的个数)、储备池输入单元尺度IS(IS为储备池的输入信号连接到储备池内部神经元之前需要相乘的一个尺度因子)、储备池稀疏程度SD(即为储备池中互相连接的神经元个数占储备池神经元总个数的比例)。对于IS,如果需要处理的任务的非线性越强,那么输入单元尺度越大。该原则的本质就是通过输入单元尺度IS,将输入变换到神经元激活函数相应的范围(神经元激活函数的不同输入范围,其非线性程度不同)。 +

+ +

+ +

+ +

+ +

+ +

+ +* 第五种:Gated Recurrent Unit Recurrent Neural Networks + + GRUs也是一般的RNNs的改良版本,主要是体现在两个方面。一是,序列中不同的位置处的单词(已单词举例)对当前的隐藏层的状态的影响不同,越前面的影响越小,即每个前面状态对当前的影响进行了距离加权,距离越远,权值越小。二是,在产生误差error时,误差可能是由某一个或者几个单词而引发的,所以应当仅仅对对应的单词weight进行更新。GRUs的结构如下图所示。GRUs首先根据当前输入单词向量word vector已经前一个隐藏层的状态hidden state计算出update gate和reset gate。再根据reset gate、当前word vector以及前一个hidden state计算新的记忆单元内容(new memory content)。当reset gate为1的时候,new memory content忽略之前的所有memory content,最终的memory是之前的hidden state与new memory content的结合。 +

+ +

+ +#### 应用示例 +```python + +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from __future__ import print_function + +import os +import sys +import time +from datetime import timedelta + +import numpy as np +import tensorflow as tf +from sklearn import metrics + +from cnn_model import TCNNConfig, TextCNN +from data.cnews_loader import read_vocab, read_category, batch_iter, process_file, build_vocab + +base_dir = 'data/cnews' +train_dir = os.path.join(base_dir, 'cnews.train.txt') +test_dir = os.path.join(base_dir, 'cnews.test.txt') +val_dir = os.path.join(base_dir, 'cnews.val.txt') +vocab_dir = os.path.join(base_dir, 'cnews.vocab.txt') + +save_dir = 'checkpoints/textcnn' +save_path = os.path.join(save_dir, 'best_validation') # 最佳验证结果保存路径 + + +def get_time_dif(start_time): + """获取已使用时间""" + end_time = time.time() + time_dif = end_time - start_time + return timedelta(seconds=int(round(time_dif))) + + +def feed_data(x_batch, y_batch, keep_prob): + feed_dict = { + model.input_x: x_batch, + model.input_y: y_batch, + model.keep_prob: keep_prob + } + return feed_dict + + +def evaluate(sess, x_, y_): + """评估在某一数据上的准确率和损失""" + data_len = len(x_) + batch_eval = batch_iter(x_, y_, 128) + total_loss = 0.0 + total_acc = 0.0 + for x_batch, y_batch in batch_eval: + batch_len = len(x_batch) + feed_dict = feed_data(x_batch, y_batch, 1.0) + loss, acc = sess.run([model.loss, model.acc], feed_dict=feed_dict) + total_loss += loss * batch_len + total_acc += acc * batch_len + + return total_loss / data_len, total_acc / data_len + + +def train(): + print("Configuring TensorBoard and Saver...") + # 配置 Tensorboard,重新训练时,请将tensorboard文件夹删除,不然图会覆盖 + tensorboard_dir = 'tensorboard/textcnn' + if not os.path.exists(tensorboard_dir): + os.makedirs(tensorboard_dir) + + tf.summary.scalar("loss", model.loss) + tf.summary.scalar("accuracy", model.acc) + merged_summary = tf.summary.merge_all() + writer = tf.summary.FileWriter(tensorboard_dir) + + # 配置 Saver + saver = tf.train.Saver() + if not os.path.exists(save_dir): + os.makedirs(save_dir) + + print("Loading training and validation data...") + # 载入训练集与验证集 + start_time = time.time() + x_train, y_train = process_file(train_dir, word_to_id, cat_to_id, config.seq_length) + x_val, y_val = process_file(val_dir, word_to_id, cat_to_id, config.seq_length) + time_dif = get_time_dif(start_time) + print("Time usage:", time_dif) + + # 创建session + session = tf.Session() + session.run(tf.global_variables_initializer()) + writer.add_graph(session.graph) + + print('Training and evaluating...') + start_time = time.time() + total_batch = 0 # 总批次 + best_acc_val = 0.0 # 最佳验证集准确率 + last_improved = 0 # 记录上一次提升批次 + require_improvement = 1000 # 如果超过1000轮未提升,提前结束训练 + + flag = False + for epoch in range(config.num_epochs): + print('Epoch:', epoch + 1) + batch_train = batch_iter(x_train, y_train, config.batch_size) + for x_batch, y_batch in batch_train: + feed_dict = feed_data(x_batch, y_batch, config.dropout_keep_prob) + + if total_batch % config.save_per_batch == 0: + # 每多少轮次将训练结果写入tensorboard scalar + s = session.run(merged_summary, feed_dict=feed_dict) + writer.add_summary(s, total_batch) + + if total_batch % config.print_per_batch == 0: + # 每多少轮次输出在训练集和验证集上的性能 + feed_dict[model.keep_prob] = 1.0 + loss_train, acc_train = session.run([model.loss, model.acc], feed_dict=feed_dict) + loss_val, acc_val = evaluate(session, x_val, y_val) # todo + + if acc_val > best_acc_val: + # 保存最好结果 + best_acc_val = acc_val + last_improved = total_batch + saver.save(sess=session, save_path=save_path) + improved_str = '*' + else: + improved_str = '' + + time_dif = get_time_dif(start_time) + msg = 'Iter: {0:>6}, Train Loss: {1:>6.2}, Train Acc: {2:>7.2%},' \ + + ' Val Loss: {3:>6.2}, Val Acc: {4:>7.2%}, Time: {5} {6}' + print(msg.format(total_batch, loss_train, acc_train, loss_val, acc_val, time_dif, improved_str)) + + session.run(model.optim, feed_dict=feed_dict) # 运行优化 + total_batch += 1 + + if total_batch - last_improved > require_improvement: + # 验证集正确率长期不提升,提前结束训练 + print("No optimization for a long time, auto-stopping...") + flag = True + break # 跳出循环 + if flag: # 同上 + break + + +def test(): + print("Loading test data...") + start_time = time.time() + x_test, y_test = process_file(test_dir, word_to_id, cat_to_id, config.seq_length) + + session = tf.Session() + session.run(tf.global_variables_initializer()) + saver = tf.train.Saver() + saver.restore(sess=session, save_path=save_path) # 读取保存的模型 + + print('Testing...') + loss_test, acc_test = evaluate(session, x_test, y_test) + msg = 'Test Loss: {0:>6.2}, Test Acc: {1:>7.2%}' + print(msg.format(loss_test, acc_test)) + + batch_size = 128 + data_len = len(x_test) + num_batch = int((data_len - 1) / batch_size) + 1 + + y_test_cls = np.argmax(y_test, 1) + y_pred_cls = np.zeros(shape=len(x_test), dtype=np.int32) # 保存预测结果 + for i in range(num_batch): # 逐批次处理 + start_id = i * batch_size + end_id = min((i + 1) * batch_size, data_len) + feed_dict = { + model.input_x: x_test[start_id:end_id], + model.keep_prob: 1.0 + } + y_pred_cls[start_id:end_id] = session.run(model.y_pred_cls, feed_dict=feed_dict) + + # 评估 + print("Precision, Recall and F1-Score...") + print(metrics.classification_report(y_test_cls, y_pred_cls, target_names=categories)) + + # 混淆矩阵 + print("Confusion Matrix...") + cm = metrics.confusion_matrix(y_test_cls, y_pred_cls) + print(cm) + + time_dif = get_time_dif(start_time) + print("Time usage:", time_dif) + + +if __name__ == '__main__': + if len(sys.argv) != 2 or sys.argv[1] not in ['train', 'test']: + raise ValueError("""usage: python run_cnn.py [train / test]""") + + print('Configuring CNN model...') + config = TCNNConfig() + if not os.path.exists(vocab_dir): # 如果不存在词汇表,重建 + build_vocab(train_dir, vocab_dir, config.vocab_size) + categories, cat_to_id = read_category() + words, word_to_id = read_vocab(vocab_dir) + config.vocab_size = len(words) + model = TextCNN(config) + + if sys.argv[1] == 'train': + train() + else: + test() +``` diff --git a/assets/src/DL/DL.0.5.md b/assets/src/DL/DL.0.5.md new file mode 100644 index 00000000..bc9bc8ed --- /dev/null +++ b/assets/src/DL/DL.0.5.md @@ -0,0 +1,200 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 分层时间记忆(Hierarchical Temporal Memory) +分层时间记忆算法(Hierarchical Temporal Memory),全称HTM Cortical Learning Algorithms是由《人工智能的未来》(On Intelligence)一书作者Jeff Hawkins创建的Numenta公司发表的新一代人工智能算法。HTM算法旨在模拟新大脑皮层的工作原理,将复杂的问题转化为模式匹配与预测。正如它的名字HTM一样,该算法与普通的神经网络算法有诸多的不同之处。HTM强调对“神经元”进行分层级,强调信息模式的空间特性与时间特性。目前Numenta公司已经推出基于HTM算法的python平台和可进行视觉识别的软件工具箱。 + +传统的人工智能算法大多是针对特定的任务目标而设计的。HTM算法与之不同 ,它注重先把问题转化成模式匹配与预测的问题再解决。这使提出人工智能的“统一理论”成为可能。HTM算法是建立在大量解剖学和神经科学的基础上的。HTM算法认为人类之所以具有智能,新大脑皮层是不可缺少的必要条件,并且由其承担高级脑活动。我们的大脑的运行机制是将接受到的各种模式与记忆中模式进行匹配,并对下一刻将会接收到的信息作出预测及反应,如此循环往复。这正是其时效性(Temporal)的体现。 +HTM算法表面上与神经网络算法有相似之处,其实质是完全不同的。这就好比一般电路与门电路的区别。将模拟“神经元”按照新大脑皮层的结构连接之后就会产生与一般神经网路完全不同的效果。一般的神经网络注重前馈,而HTM算法更注重信息的双向交流,这也是由于神经解剖学发现反馈突触数量不亚于前馈的原因。而反馈并不能得到大多数人的重视。 + +HTM算法也是一种拥有记忆性和可学习性的算法。它相对于其他学习算法更注重对神经网络的训练而不是架构。HTM算法认为只要经过合理的训练,该算法适用于解决大多数人工智能问题。对于不同的任务目标实验者需要将数据先空间化和时间化再对HTM网络进行训练即可。 + +其实HTM算法是源于生物学理论,意味着它来自神经解剖学和神经生理学,是解释生物学的新皮质如何运作的。我们有时说HTM 理论是“约束于生物学”,和“启发于生物学”相反,后者是机器学习领域常用的说法。HTM 理论必须与新皮质的生物学细节相容,并且不能依赖生物组织中不可能实现的原理。比如,考虑锥体细胞,这是新皮质中最常见的神经元类型。锥体细胞有称作树突的树状延伸,通过数千个突触连接。神经学家知道树突是激活的处理单元,通过突触的交流是动态的、内在随机的过程。锥体细胞是新皮质的核心信息处理元件,突触是记忆的基础。所以,为了理解新皮质是如何运作的,我们需要一种适应神经元和突触的本质特征的理论。人工神经网络(ANN)一般是对没有树突并且只有很少的高度精确的突触和特征的神经元建模,真实的神经元并非如此。这种人工神经元与生物神经元不相容,因此不可能发展成与脑的运作原理相同的网络。这个评论不是说 ANN 没用,只是它们的运作原理和生物神经网络的不同。你将会看到,HTM 理论解释了为什么神经元有数千个突触和激活树突。我们认为,这些和很多其他生物学特征对智能系统来说是必不可少、无法忽视的。 + +HTM的原理:稀疏分布表征理论,运用的表征方法称作稀疏分布表征,简称 SDR。SDR 是包含数千比特的向量。在任何时候,一小部分比特置 1,其余的置 0。HTM 理论会解释为什么在 SDR 中,总是有一小部分零散的比特置 1,以及这些置 1 的比特的比重必须小,通常小于 2%。SDR 中的比特对应着新皮质中的神经元。稀疏分布表征有一些意义重大并且不可思议的特性。为了方便比较,考虑在可编程计算机中的表征方法。单词存储在计算机中的含义不是单词内在的。如果给你看计算机内存中某处的 64 比特,你并不能知道它表示什么。在程序运行的某一时刻,这些比特可能是表示一个意思,在另一时刻,可能又表示别的意思。无论是哪种情况,只能依赖物理地址, +而非比特本身。对于 SDR,表征的比特编码了自身的语义特征,即表达和含义是一致的。如果两个 SDR 有相同的比特位置 1,它们就共有某种语义特征。如果两个 SDR 有越多相同的比特位置 1,它们在语义上就越相似。SDR 解释了人脑是如何做语义归纳的,它正是这种表征方法的内在特性。另一个展示稀疏表征的特有能力的例子是,一组神经元可以同时激活多种表征并且不引起混乱。这就好比在计算机内存中的某处,不仅仅只能容纳一个值,而是同时容纳二十个值,并且不引起混乱。我们称这种独一无二的特性为“联合性”。在 HTM 理论中它被用来同时做多个预测。稀疏分布表征的运用是 HTM 理论的关键所在。我们认为,所有真正的智能系统必须要运用稀疏分布表征。为了轻松理解 HTM 理论,你需要培养一种面向 SDR 的数学特性和表征特性的直觉。 + + +每个 HTM 系统都需要“感知器官”,我们称之为“编码器”。每种编码器负责把某类数据(数字、事件、温度、图像或者 GPS 坐标)转化成一个稀疏分布表征,以便 HTM 学习算法进一步处理。每种编码器都是为明确的数据类型专门设计的,往往有很多途径可以把输入信息转化为 SDR,就如同哺乳动物们的视网膜构造五花八门。只要感知信息被编码成适当的 SDR,HTM 学习算法就可以处理了。 + +基于 HTM 理论的机器智能令人兴奋的一个方面是,我们可以创造一些生物学上不存在的具有类似功能的编码器。比如,我们可以创造接收 GPS 坐标的编码器并把数据转化成 SDR。这种编码器允许 HTM 系统直接通过空间位置检测运动。HTM 系统可以进一步对运动分类,预测未来的位置,侦查运动中的异常。能够运用非人类感官的能力启发了智能机器可能的发展方向。智能机器不仅仅在人类事务上表现出优越性,还将处理那些人类难以感知或者无能为力的问题。 + + +每个 HTM 系统都需要“感知器官”,我们称之为“编码器”。每种编码器负责把某类数据(数字、事件、温度、图像或者 GPS 坐标)转化成一个稀疏分布表征,以便 HTM 学习算法进一步处理。每种编码器都是为明确的数据类型专门设计的,往往有很多途径可以把输入信息转化为 SDR,就如同哺乳动物们的视网膜构造五花八门。只要感知信息被编码成适当的 SDR,HTM 学习算法就可以处理了。 + +基于 HTM 理论的机器智能令人兴奋的一个方面是,我们可以创造一些生物学上不存在的具有类似功能的编码器。比如,我们可以创造接收 GPS 坐标的编码器并把数据转化成 SDR。这种编码器允许 HTM 系统直接通过空间位置检测运动。HTM 系统可以进一步对运动分类,预测未来的位置,侦查运动中的异常。能够运用非人类感官的能力启发了智能机器可能的发展方向。智能机器不仅仅在人类事务上表现出优越性,还将处理那些人类难以感知或者无能为力的问题。 + +

+ +

+

HTM 算法在图像识别中的应用

+ +因而HTM算法应用与传统的算法应用是不同的。传统上每一个程序解决一个具体问题例如处理电邮或是分析数据。与此相反,HTM算法可以被训练来解决不领域不同类型的问题。一个HTM系统,相比之下,是在训练,而不是编程。 HTM通过感知的数据流以人类认知世界的方式来学习世界中的对象。通过模拟人类大脑的模式发现机制,HTM提供一种在杂乱 、大型、现实世界的数据集中进行模式识别和预测的方法。其应用领域很广,比如图像和声音识别,复杂系统的故障预测,网络点击预测,欺诈检测系统预测,文本的语义分析等 。HTM底层的学习算法并不局限于特定的应用领域。 + +#### 应用示例 +```python + +from carver.htm.config import config +from carver.htm.synapse import CONNECTED_CUTOFF +from carver.htm.segment import Segment + +#one column out of n should fire: +desiredLocalActivity = config.getint('constants','desiredLocalActivity') + +def pool_spatial(htm): + ''' + A couple notable deviations: + *column overlap boost and cutoff are swapped from pseudocode, details inline + see _spatial_overlap + *time and inputData removed from code - used a data producer model, linked to htm + *getBestMatchingSegment now takes an argument for whether it is a nextStep segment or a sequence one + inspired by binarybarry on http://www.numenta.com/phpBB2/viewtopic.php?t=1403 + ''' + + _spatial_overlap(htm) + + activeColumns = _spatial_inhibition(htm) + + inhibitionRadius = _spatial_learning(htm, activeColumns) + + htm.inhibitionRadius = inhibitionRadius + +def pool_temporal(htm, updateSegments, learning=True): + updateSegments = _temporal_phase1(htm, learning, updateSegments) + + updateSegments = _temporal_phase2(htm, updateSegments, learning) + + if learning: + updateSegments = _temporal_phase3(htm, updateSegments) + + return updateSegments + +def _spatial_overlap(htm): + 'Overlap, p 35' + + for col in htm.columns: + col.overlap = len(col.old_firing_synapses()) + + #The paper has conflicting information in the following lines. + #The text implies boost before cutoff, the code: cutoff then boost. I + #chose boost first because I think the boost should help a column + #overcome the cutoff. + col.overlap *= col.boost + + if col.overlap < col.MIN_OVERLAP: + col.overlap = 0 + +def _spatial_inhibition(htm): + 'Inhibition, p 35' + activeColumns = [] + for col in htm.columns: + kthNeighbor = col.kth_neighbor(desiredLocalActivity) + minLocalActivity = kthNeighbor.overlap + + if col.overlap > 0 and col.overlap >= minLocalActivity: + activeColumns.append(col) + col.active = True + else: + col.active = False + + return activeColumns + +def _spatial_learning(htm, activeColumns): + 'Learning, p 36' + for col in activeColumns: + for s in col.synapses: + if s.was_firing(): + s.permanence_increment() + else: + s.permanence_decrement() + + for col in htm.columns: + col.dutyCycleMin = 0.01 * col.neighbor_duty_cycle_max() + col.dutyCycleActive = col.get_duty_cycle_active() + col.boost = col.next_boost() + + col.dutyCycleOverlap = col.get_duty_cycle_overlap() + if col.dutyCycleOverlap < col.dutyCycleMin: + col.increase_permanences(0.1 * CONNECTED_CUTOFF) + + return htm.average_receptive_field_size() + +def _temporal_phase1(htm, learning, updateSegments): + ''' + Phase 1, p40 + @param htm: htm network object + @param learning: boolean describing whether the network is learning now + @param updateSegments: hash from cell to a list of segments to update when cell becomes active + ''' + + for col in htm.columns_active(): + buPredicted = False + learningCellChosen = False + for cell in col.cells: + if cell.predicted: + seg = cell.findSegmentWasActive(nextStep=True) + + #distal dendrite segments = sequence memory + if seg and seg.distal: + buPredicted = True + cell.active = True + + #Learning Phase 1, p 41 + if learning and seg.wasActiveFromLearningCells: + learningCellChosen = True + cell.learning = True + + if not buPredicted: + for cell in col.cells: + cell.active = True + + #Learning Phase 1, p41 + if learning and not learningCellChosen: + cell, seg = col.bestCell(nextStep=True) + cell.learning = True + + if seg is None: + seg = cell.create_segment(htm, nextStep=True) + + updateSegments.add(cell, seg, timeDelta=-1) + + return updateSegments + +def _temporal_phase2(htm, updateSegments, learning): + 'Phase 2, p40' + for cell in htm.cells: + for seg in cell.segments: + if seg.active: + cell.predicting = True + + if learning: + updateSegments.add(cell, seg, timeDelta=0) + + #for each cell, grab the best segment. right now, this does not prevent + #duplication of learning on the best segment + if learning and cell.predicting: + bestSeg = cell.bestMatchingSegment(nextStep=False) + if bestSeg is None: + bestSeg = cell.create_segment(htm, nextStep=False) + + bestSeg.round_out_synapses(htm) + + updateSegments.add(cell, bestSeg, timeDelta=-1) + + return updateSegments + +def _temporal_phase3(htm, updateSegments): + 'Phase 3, p42' + for cell in htm.cells: + if cell.learning: + for synapseStates in updateSegments[cell]: + Segment.adapt_up(synapseStates) + updateSegments.reset(cell) + elif not cell.predicting and cell.predicted: + for synapseStates in updateSegments[cell]: + Segment.adapt_down(synapseStates) + updateSegments.reset(cell) + + return updateSegments +``` diff --git a/assets/src/DL/DL.0.6.md b/assets/src/DL/DL.0.6.md new file mode 100644 index 00000000..a711993c --- /dev/null +++ b/assets/src/DL/DL.0.6.md @@ -0,0 +1,708 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 堆叠自动编码器(Stacked AutoEncoder) + +自从Hinton 2006年的工作之后,越来越多的研究者开始关注各种自编码器模型相应的堆叠模型。实际上,自编码器(Auto-Encoder)是一个较早的概念了,比如Hinton等人在1986, 1989年的工作。 + +自编码器可以理解为一个试图去还原其原始输入的系统。 +

+ +

+ +图中,虚线蓝色框内就是一个自编码器模型,它由编码器(Encoder)和解码器(Decoder)两部分组成,本质上都是对输入信号做某种变换。 +编码器将输入信号x变换成编码信号y,而解码器将编码y转换成输出信号,即 +

+ +

+ +而自编码器的目的是,让输出尽可能复现输入x.但是,这样问题就来了,如果f和g都是恒等映射,那就是,实际上事实确实如此,但这样的变换就没有什么用了,所以我们需要对中间信号y(也叫作“编码”)做一定的约束,这样,系统往往能学出很有趣的编码变换f和编码y。 + +在这里需要强调一点,对于自编码器,往往并不关系输出是什么,因常我们只需要关心中间层的编码,或者是从输入到编码的映射。在我们强迫编码y和输入x不同的情况下,系统还能够去复原原始信号x,那么说明编码y已经承载了原始数据的所有信息,但以一种不同的形式!这就是特征提取。这个是通过自动学出来的,事实上,自动学习原始数据的特征表达也是神经网络和深度学习的核心目的之一。 + +自编码器与神经网络,其中神经网络就是在对原始信号逐层地做非线性变换: + +

+ +

+ +该网络把输入层数据转换到中间层(隐层),再转换到输出层。图中的每个节点代表数据的一个维度(偏置项图中未标出)。每两层之间的变换都是“线性变化”+“非线性激活”,用公式表示即为。图中的每个节点代表数据的一个维度(偏置项图中未标出)。每两层之间的变换都是“线性变化”+“非线性激活”,用公式表示为: +

+ +

+ +神经网络通常可以用于分类,这样可以得道从输入层到输出层的变换函数。因此,我们需要定义一个目标函数来衡量当前的输出和真实结果的差异,利用该函数去逐步调整(如梯度下降)系统的参数,以使得整个网络尽可能去拟合训练数据。如果有正则约束的话,还同时要求模型尽量简单(以防止过拟合)。 + +但是自编码器怎么表示呢? + +自编码器试图复现其原始输入,因此,在训练中,网络中的输出应与输入相同,即 y=x,因此,一个自编码器的输入、输出应有相同的结构,即: +

+ +

+ +这里我们可以利用训练数据训练这个网络,等训练结束后,这个网络即学习出了的能力。对我们来说,此时的h是至关重要的,因为它是在尽量不损失信息量的情况下,对原始数据的另一种表达。结合神经网络的惯例,我们再将自编码器的公式表示如下:(假设激活函数是sigmoid,用s表示) + +

+ +

+ +其中,表示损失函数,结合数据的不同形式,可以是二次误差(squared error loss)或交叉熵误差(cross entropy loss)。如果,一般称为tied weights。 + +这里我们会给隐层加入一定的约束。从数据维度来看,常见以下两种情况: + +* n>p,即隐层维度小于输入数据维度。从x→h的变换是一种降维的操作,网络试图以更小的维度去描述原始数据而尽量不损失数据信息。实际上,当每两层之间的变换均为线性,且监督训练的误差是二次型误差时,该网络等价于PCA! + +* n

的三层网络,能够学习出一种特征变化(这里用θ表示变换的参数,包括W,b和激活函数)。实际上,当训练结束后,输出层就没什么意义了,我们一般会将其去掉的,即将自编码器表示为: +

+ +

+ +自编码器模型这里表示为3层的神经网络,这是因为训练的需要,我们将原始数据作为假想的目标输出,以此构建监督误差来训练整个网络。等训练结束后,输出层就可以去掉了,而我们关心的只是从x到h的变换过程。 + +接下来的思路就很自然了——我们已经得到特征表达h,那么我们就可以将h再当做原始信息,训练一个新的自编码器,得到新的特征表达。 + +堆叠自编码器(Stacked Auto-Encoder, SAE),这里Stacked就是逐层垒叠的意思,跟“栈”有点像,当把多个自编码器Stack起来之后就是如下的过程: +

+ +

+ +这里需要注意的是,整个网络的训练不是一蹴而就的,而是需要逐层进行。根据n,m,k结构,实际上我们是先训练网络n→m→n,得到n→m的变换,然后再训练 +m→k→m,得到m→k的变换。最终堆叠成SAE,即为n→m→k的结果,整个过程就像一层层往上构建网络,这个就是非常有名的 +layer-wise unsuperwised pre-training(逐层非监督预训练)。 + +稀疏自编码器如前所示,这种模型背后的思想是,高维而稀疏的表达是好的。一般而言h中哪些节点是被抑制的(对于sigmoid单元即输出为0),而是指定一个稀疏性参数ρ,,代表隐藏神经元的平均活跃程度(在训练集上取平均)。比如,当ρ=0.05时,可以认为隐层节点在95%的时间里都是被一直的,只有5%的机会被激活。实际上,为了满足这一条件,隐层神经元的活跃度需要接近于0。 + +既然要求平均激活度为ρ,那么我们只要引入一个度量,来衡量神经元i的实际激活度与期望激活度ρ之间的差异即可,然后将这个度量添加到目标函数作为正则,训练整个网络即可。那么,什么样的度量适合这个任务呢?了解过概率论、信息论基础的人应该清楚——相对熵,也就是KL散度(KL divergence)。因此,整个网络所添加的惩罚项: +

+ +

+ +我们可以从下图(摘自UFLDL)中直观理解KL散度作为惩罚项的含义。图中假设平均激活度ρ=0.2。 + +

+ +

+ +可以看出,当一旦偏离期望激活度ρ,这种误差便急剧增大,从而作为惩罚项添加到目标函数,指导整个网络学习出稀疏的特征表达。 + + +降噪自编码器(Stacked Denoising Autoencoders)核心思想是,一个能够从中恢复出原始信号的表达未必是最好的,能够对“被污染/破坏”的原始数据编码、解码,然后还能恢复真正的原始数据,这样的特征才是好的。 + +假设原始数据x被我们“故意破坏”,比如加入高斯白噪,或者把某些维度数据抹掉,变成了,然后再对编码、解码,得到恢复信号,该恢复信号尽可能逼近未被污染的数据x。此时,监督训练的误差从变成了。 + +降噪自编码器的系统结构如下图: + +

+ +

+ +深度学习兴起正式因为逐层预训练方法的提出,使得深度网络的训练成为可能。对于一个深度网络而言,这种逐层预训练的方法,正是前面介绍的这种堆叠自动编码器(Stacked AutoEncoder)。对于常见的分类任务,一般分为以下两个阶段: + +* 逐层预训练(layer-wise pre-training) +* 微调(fune-tuning ) + +上面讲述的的自动编码器,本质上都是非监督学习,自动编码器各层的输出都是原始数据的不同表达。对于分类任务,往往在自动编码器顶端再添加一分类层(如Softmax层),并结合有标注的训练数据,在误差函数的指导下,对系统的参数进行微调,以使得整个网络能够完成所需的分类任务。 + +

+ +

+ +对于微调过程,即可以只调整分类层的参数(此时相当于把整个SAE当做一个feature extractor),也可以调整整个网络的参数(适合训练数据量比较大的情况)。 + +但是为什么训练稀疏自编码器为什么一般都是三层的结构,实际上这里的三层是指训练单个自编码器所假想的3层神经网络,这对任何基于神经网络的编码器都是这样。多层的稀疏自编码器自然是有的,只不过是通过layer-wise pre-training这种方式逐层堆叠起来的,而不是直接去训练多层的网络。 + +实际上,这正是在训练深层神经网络中遇到的问题。直接去训练一个深层的自编码器,其实本质上就是在做深度网络的训练,由于梯度扩散等问题,这样的网络往往根本无法训练。这倒不是因为会破坏稀疏性等原因,只要网络能够训练,对模型施加的约束总能得到相应的结果。 + +但是为什么逐层预训练就可以使得深度网络的训练成为可能了呢?其实一个直观的解释是,预训练好的网络在一定程度上拟合了训练数据的结构,这使得整个网络的初始值是在一个合适的状态,便于有监督阶段加快迭代收敛。 + +#### 应用示例 +```python +# This piece of software is bound by The MIT License (MIT) +# Copyright (c) 2014 Siddharth Agrawal +# Code written by : Siddharth Agrawal +# Email ID : siddharth.950@gmail.com + +import struct +import array +import numpy +import math +import time +import scipy.io +import scipy.optimize + +""" Returns elementwise sigmoid output of input array """ + +def sigmoid(x): + + return (1 / (1 + numpy.exp(-x))) + +""" Returns the groundtruth matrix for a set of labels """ + +def getGroundTruth(labels): + + """ Prepare data needed to construct groundtruth matrix """ + + labels = numpy.array(labels).flatten() + data = numpy.ones(len(labels)) + indptr = numpy.arange(len(labels)+1) + + """ Compute the groundtruth matrix and return """ + + ground_truth = scipy.sparse.csr_matrix((data, labels, indptr)) + ground_truth = numpy.transpose(ground_truth.todense()) + + return ground_truth + +""" The Sparse Autoencoder class """ + +class SparseAutoencoder(object): + + """ Initialization of Autoencoder object """ + + def __init__(self, visible_size, hidden_size, rho, lamda, beta): + + """ Initialize parameters of the Autoencoder object """ + + self.visible_size = visible_size # number of input units + self.hidden_size = hidden_size # number of hidden units + self.rho = rho # desired average activation of hidden units + self.lamda = lamda # weight decay parameter + self.beta = beta # weight of sparsity penalty term + + """ Set limits for accessing 'theta' values """ + + self.limit0 = 0 + self.limit1 = hidden_size * visible_size + self.limit2 = 2 * hidden_size * visible_size + self.limit3 = 2 * hidden_size * visible_size + hidden_size + self.limit4 = 2 * hidden_size * visible_size + hidden_size + visible_size + + """ Initialize Neural Network weights randomly + W1, W2 values are chosen in the range [-r, r] """ + + r = math.sqrt(6) / math.sqrt(visible_size + hidden_size + 1) + + rand = numpy.random.RandomState(int(time.time())) + + W1 = numpy.asarray(rand.uniform(low = -r, high = r, size = (hidden_size, visible_size))) + W2 = numpy.asarray(rand.uniform(low = -r, high = r, size = (visible_size, hidden_size))) + + """ Bias values are initialized to zero """ + + b1 = numpy.zeros((hidden_size, 1)) + b2 = numpy.zeros((visible_size, 1)) + + """ Create 'theta' by unrolling W1, W2, b1, b2 """ + + self.theta = numpy.concatenate((W1.flatten(), W2.flatten(), + b1.flatten(), b2.flatten())) + + """ Returns gradient of 'theta' using Backpropagation algorithm """ + + def sparseAutoencoderCost(self, theta, input): + + """ Extract weights and biases from 'theta' input """ + + W1 = theta[self.limit0 : self.limit1].reshape(self.hidden_size, self.visible_size) + W2 = theta[self.limit1 : self.limit2].reshape(self.visible_size, self.hidden_size) + b1 = theta[self.limit2 : self.limit3].reshape(self.hidden_size, 1) + b2 = theta[self.limit3 : self.limit4].reshape(self.visible_size, 1) + + """ Compute output layers by performing a feedforward pass + Computation is done for all the training inputs simultaneously """ + + hidden_layer = sigmoid(numpy.dot(W1, input) + b1) + output_layer = sigmoid(numpy.dot(W2, hidden_layer) + b2) + + """ Estimate the average activation value of the hidden layers """ + + rho_cap = numpy.sum(hidden_layer, axis = 1) / input.shape[1] + + """ Compute intermediate difference values using Backpropagation algorithm """ + + diff = output_layer - input + + sum_of_squares_error = 0.5 * numpy.sum(numpy.multiply(diff, diff)) / input.shape[1] + weight_decay = 0.5 * self.lamda * (numpy.sum(numpy.multiply(W1, W1)) + + numpy.sum(numpy.multiply(W2, W2))) + KL_divergence = self.beta * numpy.sum(self.rho * numpy.log(self.rho / rho_cap) + + (1 - self.rho) * numpy.log((1 - self.rho) / (1 - rho_cap))) + cost = sum_of_squares_error + weight_decay + KL_divergence + + KL_div_grad = self.beta * (-(self.rho / rho_cap) + ((1 - self.rho) / (1 - rho_cap))) + + del_out = numpy.multiply(diff, numpy.multiply(output_layer, 1 - output_layer)) + del_hid = numpy.multiply(numpy.dot(numpy.transpose(W2), del_out) + numpy.transpose(numpy.matrix(KL_div_grad)), + numpy.multiply(hidden_layer, 1 - hidden_layer)) + + """ Compute the gradient values by averaging partial derivatives + Partial derivatives are averaged over all training examples """ + + W1_grad = numpy.dot(del_hid, numpy.transpose(input)) + W2_grad = numpy.dot(del_out, numpy.transpose(hidden_layer)) + b1_grad = numpy.sum(del_hid, axis = 1) + b2_grad = numpy.sum(del_out, axis = 1) + + W1_grad = W1_grad / input.shape[1] + self.lamda * W1 + W2_grad = W2_grad / input.shape[1] + self.lamda * W2 + b1_grad = b1_grad / input.shape[1] + b2_grad = b2_grad / input.shape[1] + + """ Transform numpy matrices into arrays """ + + W1_grad = numpy.array(W1_grad) + W2_grad = numpy.array(W2_grad) + b1_grad = numpy.array(b1_grad) + b2_grad = numpy.array(b2_grad) + + """ Unroll the gradient values and return as 'theta' gradient """ + + theta_grad = numpy.concatenate((W1_grad.flatten(), W2_grad.flatten(), + b1_grad.flatten(), b2_grad.flatten())) + + return [cost, theta_grad] + + +""" The Softmax Regression class """ + +class SoftmaxRegression(object): + + """ Initialization of Regressor object """ + + def __init__(self, input_size, num_classes, lamda): + + """ Initialize parameters of the Regressor object """ + + self.input_size = input_size # input vector size + self.num_classes = num_classes # number of classes + self.lamda = lamda # weight decay parameter + + """ Randomly initialize the class weights """ + + rand = numpy.random.RandomState(int(time.time())) + + self.theta = 0.005 * numpy.asarray(rand.normal(size = (num_classes*input_size, 1))) + + """ Returns the cost and gradient of 'theta' at a particular 'theta' """ + + def softmaxCost(self, theta, input, labels): + + """ Compute the groundtruth matrix """ + + ground_truth = getGroundTruth(labels) + + """ Reshape 'theta' for ease of computation """ + + theta = theta.reshape(self.num_classes, self.input_size) + + """ Compute the class probabilities for each example """ + + theta_x = numpy.dot(theta, input) + hypothesis = numpy.exp(theta_x) + probabilities = hypothesis / numpy.sum(hypothesis, axis = 0) + + """ Compute the traditional cost term """ + + cost_examples = numpy.multiply(ground_truth, numpy.log(probabilities)) + traditional_cost = -(numpy.sum(cost_examples) / input.shape[1]) + + """ Compute the weight decay term """ + + theta_squared = numpy.multiply(theta, theta) + weight_decay = 0.5 * self.lamda * numpy.sum(theta_squared) + + """ Add both terms to get the cost """ + + cost = traditional_cost + weight_decay + + """ Compute and unroll 'theta' gradient """ + + theta_grad = -numpy.dot(ground_truth - probabilities, numpy.transpose(input)) + theta_grad = theta_grad / input.shape[1] + self.lamda * theta + theta_grad = numpy.array(theta_grad) + theta_grad = theta_grad.flatten() + + return [cost, theta_grad] + +""" Loads the images from the provided file name """ + +def loadMNISTImages(file_name): + + """ Open the file """ + + image_file = open(file_name, 'rb') + + """ Read header information from the file """ + + head1 = image_file.read(4) + head2 = image_file.read(4) + head3 = image_file.read(4) + head4 = image_file.read(4) + + """ Format the header information for useful data """ + + num_examples = struct.unpack('>I', head2)[0] + num_rows = struct.unpack('>I', head3)[0] + num_cols = struct.unpack('>I', head4)[0] + + """ Initialize dataset as array of zeros """ + + dataset = numpy.zeros((num_rows*num_cols, num_examples)) + + """ Read the actual image data """ + + images_raw = array.array('B', image_file.read()) + image_file.close() + + """ Arrange the data in columns """ + + for i in range(num_examples): + + limit1 = num_rows * num_cols * i + limit2 = num_rows * num_cols * (i + 1) + + dataset[:, i] = images_raw[limit1 : limit2] + + """ Normalize and return the dataset """ + + return dataset / 255 +""" Loads the image labels from the provided file name """ + +def loadMNISTLabels(file_name): + + """ Open the file """ + + label_file = open(file_name, 'rb') + + """ Read header information from the file """ + + head1 = label_file.read(4) + head2 = label_file.read(4) + + """ Format the header information for useful data """ + + num_examples = struct.unpack('>I', head2)[0] + + """ Initialize data labels as array of zeros """ + + labels = numpy.zeros((num_examples, 1), dtype = numpy.int) + + """ Read the label data """ + + labels_raw = array.array('b', label_file.read()) + label_file.close() + + """ Copy and return the label data """ + + labels[:, 0] = labels_raw[:] + + return labels + +""" Returns the hidden layer activations of the Autoencoder """ + +def feedForwardAutoencoder(theta, hidden_size, visible_size, input): + + """ Define limits to access useful data """ + + limit0 = 0 + limit1 = hidden_size * visible_size + limit2 = 2 * hidden_size * visible_size + limit3 = 2 * hidden_size * visible_size + hidden_size + + """ Access W1 and b1 from 'theta' """ + + W1 = theta[limit0 : limit1].reshape(hidden_size, visible_size) + b1 = theta[limit2 : limit3].reshape(hidden_size, 1) + + """ Compute the hidden layer activations """ + + hidden_layer = 1 / (1 + numpy.exp(-(numpy.dot(W1, input) + b1))) + + return hidden_layer + +""" Returns a row of Stacked Autoencoder parameters """ + +def stack2Params(stack): + + """ Initialize an empty list of parameters """ + + params = [] + num_layers = len(stack) / 2 + + """ For each layer in the neural network, append the corresponding parameters """ + + for i in range(num_layers): + + params = numpy.concatenate((params, numpy.array(stack[i, "W"]).flatten())) + params = numpy.concatenate((params, numpy.array(stack[i, "b"]).flatten())) + + return params +""" Returns a stack of Stacked Autoencoder parameters """ + +def params2Stack(params, net_config): + + """ Initialize an empty stack """ + + stack = {} + limit0 = 0 + + for i in range(len(net_config)-2): + + """ Calculate limits of layer parameters, using neural network config """ + + limit1 = limit0 + net_config[i] * net_config[i+1] + limit2 = limit1 + net_config[i+1] + + """ Extract layer parameters, and store in the stack """ + + stack[i, "W"] = params[limit0 : limit1].reshape(net_config[i+1], net_config[i]) + stack[i, "b"] = params[limit1 : limit2].reshape(net_config[i+1], 1) + + limit0 = limit2 + + return stack + +""" Function for finetuning the Stacked Autoencoder """ + +def stackedAutoencoderCost(theta, net_config, lamda, data, labels): + + """ Calculate limits for Softmax parameters """ + + input_size = net_config[-2] + num_classes = net_config[-1] + + limit0 = 0 + limit1 = num_classes * input_size + + """ Extract Softmax and layer parameters """ + + softmax_theta = theta[limit0 : limit1].reshape(num_classes, input_size) + stack = params2Stack(theta[limit1 :], net_config) + + num_layers = len(stack) / 2 + + """ Calculate activations for every layer """ + + activation = {} + activation[0] = data + + for i in range(num_layers): + + activation[i+1] = sigmoid(numpy.dot(stack[i, "W"], activation[i]) + stack[i, "b"]) + + """ Compute the groundtruth matrix """ + + ground_truth = getGroundTruth(labels) + + """ Compute the class probabilities for each example """ + + theta_x = numpy.dot(softmax_theta, activation[num_layers]) + hypothesis = numpy.exp(theta_x) + probabilities = hypothesis / numpy.sum(hypothesis, axis = 0) + + """ Compute the traditional cost term """ + + cost_examples = numpy.multiply(ground_truth, numpy.log(probabilities)) + traditional_cost = -(numpy.sum(cost_examples) / data.shape[1]) + + """ Compute the weight decay term """ + + theta_squared = numpy.multiply(softmax_theta, softmax_theta) + weight_decay = 0.5 * lamda * numpy.sum(theta_squared) + + """ Add both terms to get the cost """ + + cost = traditional_cost + weight_decay + + """ Compute Softmax 'theta' gradient """ + + softmax_theta_grad = -numpy.dot(ground_truth - probabilities, numpy.transpose(activation[num_layers])) + softmax_theta_grad = softmax_theta_grad / data.shape[1] + lamda * softmax_theta + + """ Compute intermediate difference values using Backpropagation algorithm """ + + delta = {} + delta[num_layers] = -numpy.multiply(numpy.dot(numpy.transpose(softmax_theta), ground_truth - probabilities), + numpy.multiply(activation[num_layers], 1 - activation[num_layers])) + for i in range(num_layers-1): + + index = num_layers - i - 1 + delta[index] = numpy.multiply(numpy.dot(numpy.transpose(stack[index, "W"]), delta[index+1]), + numpy.multiply(activation[index], 1 - activation[index])) + + """ Compute the partial derivatives, with respect to the layer parameters """ + + stack_grad = {} + + for i in range(num_layers): + + index = num_layers - i - 1 + stack_grad[index, "W"] = numpy.dot(delta[index+1], numpy.transpose(activation[index])) / data.shape[1] + stack_grad[index, "b"] = numpy.sum(delta[index+1], axis = 1) / data.shape[1] + + """ Concatenate the gradient values and return as 'theta' gradient """ + + params_grad = stack2Params(stack_grad) + theta_grad = numpy.concatenate((numpy.array(softmax_theta_grad).flatten(), + numpy.array(params_grad).flatten())) + + return [cost, theta_grad] + + +""" Returns predictions using the trained Stacked Autoencoder model """ + +def stackedAutoencoderPredict(theta, net_config, data): + + """ Calculate limits for Softmax parameters """ + + input_size = net_config[-2] + num_classes = net_config[-1] + + limit0 = 0 + limit1 = num_classes * input_size + + """ Extract Softmax and layer parameters """ + + softmax_theta = theta[limit0 : limit1].reshape(num_classes, input_size) + stack = params2Stack(theta[limit1 :], net_config) + + num_layers = len(stack) / 2 + + """ Calculate the activations of the final layer """ + + activation = data + + for i in range(num_layers): + + activation = sigmoid(numpy.dot(stack[i, "W"], activation) + stack[i, "b"]) + + """ Compute the class probabilities for each example """ + + theta_x = numpy.dot(softmax_theta, activation) + hypothesis = numpy.exp(theta_x) + probabilities = hypothesis / numpy.sum(hypothesis, axis = 0) + + """ Give the predictions based on probability values """ + + predictions = numpy.zeros((data.shape[1], 1)) + predictions[:, 0] = numpy.argmax(probabilities, axis = 0) + + return predictions + + +""" Loads data, trains the Stacked Autoencoder model and predicts classes for test data """ + +def executeStackedAutoencoder(): + + """ Define the parameters of the first Autoencoder """ + + visible_size = 784 # size of input vector + hidden_size1 = 200 # size of hidden layer vector of first autoencoder + hidden_size2 = 200 # size of hidden layer vector of second autoencoder + rho = 0.1 # desired average activation of hidden units + lamda = 0.003 # weight decay parameter + beta = 3 # weight of sparsity penalty term + max_iterations = 200 # number of optimization iterations + num_classes = 10 # number of classes + + """ Load MNIST images for training and testing """ + + train_data = loadMNISTImages('train-images.idx3-ubyte') + train_labels = loadMNISTLabels('train-labels.idx1-ubyte') + + """ Initialize the first Autoencoder with the above parameters """ + + encoder1 = SparseAutoencoder(visible_size, hidden_size1, rho, lamda, beta) + + """ Run the L-BFGS algorithm to get the optimal parameter values """ + + opt_solution = scipy.optimize.minimize(encoder1.sparseAutoencoderCost, encoder1.theta, + args = (train_data,), method = 'L-BFGS-B', + jac = True, options = {'maxiter': max_iterations}) + sae1_opt_theta = opt_solution.x + + """ Get the features corresponding to first Autoencoder """ + + sae1_features = feedForwardAutoencoder(sae1_opt_theta, hidden_size1, visible_size, train_data) + + """ Initialize the second Autoencoder with the above parameters """ + + encoder2 = SparseAutoencoder(hidden_size1, hidden_size2, rho, lamda, beta) + + """ Run the L-BFGS algorithm to get the optimal parameter values """ + + opt_solution = scipy.optimize.minimize(encoder2.sparseAutoencoderCost, encoder2.theta, + args = (sae1_features,), method = 'L-BFGS-B', + jac = True, options = {'maxiter': max_iterations}) + sae2_opt_theta = opt_solution.x + + """ Get the features corresponding to second Autoencoder """ + + sae2_features = feedForwardAutoencoder(sae2_opt_theta, hidden_size2, hidden_size1, sae1_features) + + """ Initialize Softmax Regressor with the above parameters """ + + regressor = SoftmaxRegression(hidden_size2, num_classes, lamda) + + """ Run the L-BFGS algorithm to get the optimal parameter values """ + + opt_solution = scipy.optimize.minimize(regressor.softmaxCost, regressor.theta, + args = (sae2_features, train_labels,), method = 'L-BFGS-B', + jac = True, options = {'maxiter': max_iterations}) + softmax_opt_theta = opt_solution.x + + """ Create a stack of the Stacked Autoencoder parameters """ + + stack = {} + stack[0, "W"] = sae1_opt_theta[encoder1.limit0 : encoder1.limit1].reshape(hidden_size1, visible_size) + stack[1, "W"] = sae2_opt_theta[encoder2.limit0 : encoder2.limit1].reshape(hidden_size2, hidden_size1) + stack[0, "b"] = sae1_opt_theta[encoder1.limit2 : encoder1.limit3].reshape(hidden_size1, 1) + stack[1, "b"] = sae2_opt_theta[encoder2.limit2 : encoder2.limit3].reshape(hidden_size2, 1) + + """ Create a vector of the Stacked Autoencoder parameters for optimization """ + + stack_params = stack2Params(stack) + stacked_ae_theta = numpy.concatenate((softmax_opt_theta.flatten(), stack_params.flatten())) + + """ Create a neural network configuration, with number of units in each layer """ + + net_config = [visible_size, hidden_size1, hidden_size2, num_classes] + + """ Load MNIST test images and labels """ + + test_data = loadMNISTImages('t10k-images.idx3-ubyte') + test_labels = loadMNISTLabels('t10k-labels.idx1-ubyte') + + """ Get predictions after greedy training """ + + predictions = stackedAutoencoderPredict(stacked_ae_theta, net_config, test_data) + + """ Print accuracy of the trained model """ + + correct = test_labels[:, 0] == predictions[:, 0] + print """Accuracy after greedy training :""", numpy.mean(correct) + + """ Finetune the greedily trained model """ + + opt_solution = scipy.optimize.minimize(stackedAutoencoderCost, stacked_ae_theta, + args = (net_config, lamda, train_data, train_labels,), + method = 'L-BFGS-B', jac = True, options = {'maxiter': max_iterations}) + stacked_ae_opt_theta = opt_solution.x + + """ Get predictions after finetuning """ + + predictions = stackedAutoencoderPredict(stacked_ae_opt_theta, net_config, test_data) + + """ Print accuracy of the trained model """ + + correct = test_labels[:, 0] == predictions[:, 0] + print """Accuracy after finetuning :""", numpy.mean(correct) + +executeStackedAutoencoder() +``` diff --git a/assets/src/DL/DL.0.7.md b/assets/src/DL/DL.0.7.md new file mode 100644 index 00000000..bcbaf62f --- /dev/null +++ b/assets/src/DL/DL.0.7.md @@ -0,0 +1,149 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 生成式对抗网络(Generative Adversarial Networks) +生成对抗网络(Generative Adversarial Network,简称GAN)是非监督式学习的一种方法,通过让两个神经网络相互博弈的方式进行学习。该方法由伊恩·古德费洛等人于2014年提出。 + +生成对抗网络由一个生成网络与一个判别网络组成。生成网络从潜在空间(latent space)中随机采样作为输入,其输出结果需要尽量模仿训练集中的真实样本。判别网络的输入则为真实样本或生成网络的输出,其目的是将生成网络的输出从真实样本中尽可能分辨出来。而生成网络则要尽可能地欺骗判别网络。两个网络相互对抗、不断调整参数,最终目的是使判别网络无法判断生成网络的输出结果是否真实。 + +生成对抗网络常用于生成以假乱真的图片。此外,该方法还被用于生成视频、三维物体模型等。 + +机器学习的模型可大体分为两类,生成模型(Generative Model)和判别模型(Discriminative Model)。判别模型需要输入变量 ,通过某种模型来预测 。生成模型是给定某种隐含信息,来随机产生观测数据。 + +举个例子: +* 判别模型:给定一张图,判断这张图里的动物是猫还是狗 +* 生成模型:给一系列猫的图片,生成一张新的猫咪(不在数据集里) +

+ +

+ + +对于判别模型,损失函数是容易定义的,因为输出的目标相对简单。但对于生成模型,损失函数的定义就不是那么容易。我们对于生成结果的期望,往往是一个暧昧不清,难以数学公理化定义的范式。所以不妨把生成模型的回馈部分,交给判别模型处理。这就是Goodfellow他将机器学习中的两大类模型,Generative和Discrimitive给紧密地联合在了一起 。 + +GAN的基本原理其实非常简单,这里以生成图片为例进行说明。假设我们有两个网络,G(Generator)和D(Discriminator)。正如它的名字所暗示的那样,它们的功能分别是: + +G是一个生成图片的网络,它接收一个随机的噪声z,通过这个噪声生成图片,记做G(z)。 + +D是一个判别网络,判别一张图片是不是“真实的”。它的输入参数是x,x代表一张图片,输出D(x)代表x为真实图片的概率,如果为1,就代表100%是真实的图片,而输出为0,就代表不可能是真实的图片。 + +在训练过程中,生成网络G的目标就是尽量生成真实的图片去欺骗判别网络D。而D的目标就是尽量把G生成的图片和真实的图片分别开来。这样,G和D构成了一个动态的“博弈过程”。 + +最后博弈的结果是什么?在最理想的状态下,G可以生成足以“以假乱真”的图片G(z)。对于D来说,它难以判定G生成的图片究竟是不是真实的,因此D(G(z)) = 0.5。 +这样我们的目的就达成了:我们得到了一个生成式的模型G,它可以用来生成图片。 +Goodfellow从理论上证明了该算法的收敛性 ,以及在模型收敛时,生成数据具有和真实数据相同的分布(保证了模型效果)。 + +应用领域:目前生成对抗网络最常使用的地方就是图像生成,如超分辨率任务,语义分割等等 + +#### 应用实例: +```python +import tensorflow as tf +from tensorflow.examples.tutorials.mnist import input_data +import numpy as np +import matplotlib as mpl +mpl.use('Agg') +import matplotlib.pyplot as plt +import matplotlib.gridspec as gridspec +import os,sys + +sys.path.append('utils') +from nets import * +from datas import * + +def sample_z(m, n): + return np.random.uniform(-1., 1., size=[m, n]) + +class DCGAN(): + def __init__(self, generator, discriminator, data): + self.generator = generator + self.discriminator = discriminator + self.data = data + + # data + self.z_dim = self.data.z_dim + self.size = self.data.size + self.channel = self.data.channel + + self.X = tf.placeholder(tf.float32, shape=[None, self.size, self.size, self.channel]) + self.z = tf.placeholder(tf.float32, shape=[None, self.z_dim]) + + # nets + self.G_sample = self.generator(self.z) + + self.D_real, _ = self.discriminator(self.X) + self.D_fake, _ = self.discriminator(self.G_sample, reuse = True) + + # loss + self.D_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=self.D_real, labels=tf.ones_like(self.D_real))) + tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=self.D_fake, labels=tf.zeros_like(self.D_fake))) + self.G_loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=self.D_fake, labels=tf.ones_like(self.D_fake))) + + # solver + self.D_solver = tf.train.AdamOptimizer(learning_rate=2e-4).minimize(self.D_loss, var_list=self.discriminator.vars) + self.G_solver = tf.train.AdamOptimizer(learning_rate=2e-4).minimize(self.G_loss, var_list=self.generator.vars) + + self.saver = tf.train.Saver() + gpu_options = tf.GPUOptions(allow_growth=True) + self.sess = tf.Session(config=tf.ConfigProto(gpu_options=gpu_options)) + + def train(self, sample_dir, ckpt_dir='ckpt', training_epoches = 1000000, batch_size = 32): + fig_count = 0 + self.sess.run(tf.global_variables_initializer()) + + for epoch in range(training_epoches): + # update D + X_b = self.data(batch_size) + self.sess.run( + self.D_solver, + feed_dict={self.X: X_b, self.z: sample_z(batch_size, self.z_dim)} + ) + # update G + k = 1 + for _ in range(k): + self.sess.run( + self.G_solver, + feed_dict={self.z: sample_z(batch_size, self.z_dim)} + ) + + # save img, model. print loss + if epoch % 100 == 0 or epoch < 100: + D_loss_curr = self.sess.run( + self.D_loss, + feed_dict={self.X: X_b, self.z: sample_z(batch_size, self.z_dim)}) + G_loss_curr = self.sess.run( + self.G_loss, + feed_dict={self.z: sample_z(batch_size, self.z_dim)}) + print('Iter: {}; D loss: {:.4}; G_loss: {:.4}'.format(epoch, D_loss_curr, G_loss_curr)) + + if epoch % 1000 == 0: + samples = self.sess.run(self.G_sample, feed_dict={self.z: sample_z(16, self.z_dim)}) + + fig = self.data.data2fig(samples) + plt.savefig('{}/{}.png'.format(sample_dir, str(fig_count).zfill(3)), bbox_inches='tight') + fig_count += 1 + plt.close(fig) + + #if epoch % 2000 == 0: + #self.saver.save(self.sess, os.path.join(ckpt_dir, "dcgan.ckpt")) + + +if __name__ == '__main__': + + # constraint GPU + os.environ['CUDA_VISIBLE_DEVICES'] = '3' + + # save generated images + sample_dir = 'Samples/celebA_dcgan' + if not os.path.exists(sample_dir): + os.makedirs(sample_dir) + + # param + generator = G_conv() + discriminator = D_conv() + + data = celebA() + + # run + dcgan = DCGAN(generator, discriminator, data) + dcgan.train(sample_dir) + +``` diff --git a/assets/src/DRA/DRA.0.1.md b/assets/src/DRA/DRA.0.1.md new file mode 100644 index 00000000..4a82ff22 --- /dev/null +++ b/assets/src/DRA/DRA.0.1.md @@ -0,0 +1,46 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 降维算法(Dimensionality Reduction Algorithm) + +机器学习领域中所谓的降维就是指采用某种映射方法,将原高维空间中的数据点映射到低维度的空间中。降维的本质是学习一个映射函数 f : x->y,其中 x 是原始数据点的表达,目前最多使用向量表达形式。 y 是数据点映射后的低维向量表达,通常 y 的维度小于 x 的维度(当然提高维度也是可以的)。f 可能是显式的或隐式的、线性的或非线性的。 + +目前大部分降维算法处理向量表达的数据,也有一些降维算法处理高阶张量表达的数据。之所以使用降维后的数据表示是因为在原始的高维空间中,包含有冗余信息以及噪音信息,在实际应用例如图像识别中造成了误差,降低了准确率;而通过降维, 我们希望减少冗余信息所造成的误差, 提高识别(或其他应用)的精度。又或者希望通过降维算法来寻找数据内部的本质结构特征。降维算法可以细分为特征选择和特征提取两大方法。 + +降维目前主要常用的降维算法是:主成分分析(PCA),线性判别分析(LDA),局部线性嵌入(LLE),拉普拉斯特征映射(LE)。 + +* 主成分分析(Principal Component Analysis) + +主成分分析(Principal Component Analysis,简称PCA)是最常用的线性降维方法,它的目标是通过某种线性投影,将高维的数据映射到低维的空间中表示,并期望在所投影的维度上数据的方差最大,以此使用较少的数据维度,同时保留住较多的原数据点的特性。 + +通俗的理解,如果把所有的点都映射到一起,那么几乎所有的信息(如点和点之间的距离关系)都丢失了,而如果映射后方差尽可能的大,那么数据点则会分散开来,以此来保留更多的信息。可以证明,PCA 是丢失原始数据信息最少的一种线性降维方式。(实际上就是最接近原始数据,但是 PCA 并不试图去探索数据内在结构)。 + +* 线性判别分析(Linear Discriminant Analysis) + +线性判别分析(Linear Discriminant Analysis,简称LDA)是一种有监督的(supervised)线性降维算法。与 PCA 保持数据信息不同,LDA 是为了使得降维后的数据点尽可能地容易被区分! + +* 局部线性嵌入(Locally Linear embedding) + +局部线性嵌入(Locally Linear embedding,简称LLE)是一种非线性降维算法,它能够使降维后的数据较好地保持原有流形结构。LLE 可以说是流形学习方法最经典的工作之一。很多后续的流形学习、降维方法都与 LLE 有密切联系。 + +* 拉普拉斯特征映射(Laplacian Eigenmaps) + +拉普拉斯特征映射(Laplacian Eigenmaps,简称LE)看问题的角度和 LLE 有些相似,也是用局部的角度去构建数据之间的关系。它的直观思想是希望相互间有关系的点(在图中相连的点)在降维后的空间中尽可能的靠近。Laplacian Eigenmaps 可以反映出数据内在的流形结构。 + +降维算法(Dimensionality Reduction Algorithm)的应用算法有: + +* 主成分分析法(Principal Component Analysis) +* 多维缩放(Mutiple Dimensional Scaling) +* 线性判别分析(Linear Discriminant Analysis) +* 等度量映射(IsometricMapping,Isomap) +* 局部线性嵌入(Locally linear embedding) +* 拉普拉斯特征映射(Laplacian Eigenmaps) +* t-分布随机近邻嵌入(t-Distributed Stochastic Neighbor Embedding,t-SNE) +* 深度自动编码器(Deep Autoencoder Networks) + +不同降维算法的区别和特征对比: + +

+ +

diff --git a/assets/src/DRA/DRA.0.2.md b/assets/src/DRA/DRA.0.2.md new file mode 100644 index 00000000..50574b30 --- /dev/null +++ b/assets/src/DRA/DRA.0.2.md @@ -0,0 +1,103 @@ +### Deeplearning Algorithms tutorial + +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 主成分分析(Principal Component Analysis) + +在多元统计分析中,主成分分析(Principal components analysis,PCA)是一种分析、简化数据集的技术。主成分分析经常用于减少数据集的维数,同时保持数据集中的对方差贡献最大的特征。这是通过保留低阶主成分,忽略高阶主成分做到的。这样低阶成分往往能够保留住数据的最重要方面。但是,这也不是一定的,要视具体应用而定。由于主成分分析依赖所给数据,所以数据的准确性对分析结果影响很大。 + +主成分分析由卡尔·皮尔逊于1901年发明,用于分析数据及建立数理模型。其方法主要是通过对协方差矩阵进行特征分解,以得出数据的主成分(即特征向量)与它们的权值(即特征值)。PCA是最简单的以特征量分析多元统计分布的方法。其结果可以理解为对原数据中的方差做出解释:哪一个方向上的数据值对方差的影响最大?换而言之,PCA提供了一种降低数据维度的有效办法;如果分析者在原数据中除掉最小的特征值所对应的成分,那么所得的低维度数据必定是最优化的(也即,这样降低维度必定是失去讯息最少的方法)。主成分分析在分析复杂数据时尤为有用,比如人脸识别。 + +PCA是最简单的以特征量分析多元统计分布的方法。通常情况下,这种运算可以被看作是揭露数据的内部结构,从而更好的解释数据的变量的方法。如果一个多元数据集能够在一个高维数据空间坐标系中被显现出来,那么PCA就能够提供一幅比较低维度的图像,这幅图像即为在讯息最多的点上原对象的一个‘投影’。这样就可以利用少量的主成分使得数据的维度降低了。 + +PCA跟因子分析密切相关,并且已经有很多混合这两种分析的统计包。而真实要素分析则是假定底层结构,求得微小差异矩阵的特征向量。 + +

+ +

+主成分分析实例:一个平均值为(1, 3)、标准差在(0.878, 0.478)方向上为3、在其正交方向为1的高斯分布。这里以黑色显示的两个向量是这个分布的协方差矩阵的特征向量,其长度按对应的特征值之平方根为比例,并且移动到以原分布的平均值为原点。 + +#### 应用示例 +```python +from __future__ import division +import numpy as np +import pandas as pd + +# 根据保留多少维特征进行降维 +class PCAcomponent(object): + def __init__(self, X, N=3): + self.X = X + self.N = N + self.variance_ratio = [] + self.low_dataMat = [] + + def _fit(self): + X_mean = np.mean(self.X, axis=0) + dataMat = self.X - X_mean + # 另一种计算协方差矩阵的方法:dataMat.T * dataMat / dataMat.shape[0] + # 若rowvar非0,一列代表一个样本;为0,一行代表一个样本 + covMat = np.cov(dataMat, rowvar=False) + # 求特征值和特征向量,特征向量是按列放的,即一列代表一个特征向量 + eigVal, eigVect = np.linalg.eig(np.mat(covMat)) + eigValInd = np.argsort(eigVal) + eigValInd = eigValInd[-1:-(self.N + 1):-1] # 取前N个较大的特征值 + small_eigVect = eigVect[:, eigValInd] # *N维投影矩阵 + self.low_dataMat = dataMat * small_eigVect # 投影变换后的新矩阵 + # reconMat = (low_dataMat * small_eigVect.I) + X_mean # 重构数据 + # 输出每个维度所占的方差百分比 + [self.variance_ratio.append(eigVal[i] / sum(eigVal)) for i in eigValInd] + return self.low_dataMat + + def fit(self): + self._fit() + return self + + +# 根据保留多大方差百分比进行降维 +class PCApercent(object): + def __init__(self, X, percentage=0.95): + self.X = X + self.percentage = percentage + self.variance_ratio = [] + self.low_dataMat = [] + + # 通过方差百分比选取前n个主成份 + def percent2n(self, eigVal): + sortVal = np.sort(eigVal)[-1::-1] + percentSum, componentNum = 0, 0 + for i in sortVal: + percentSum += i + componentNum += 1 + if percentSum >= sum(sortVal) * self.percentage: + break + return componentNum + + def _fit(self): + X_mean = np.mean(self.X, axis=0) + dataMat = self.X - X_mean + covMat = np.cov(dataMat, rowvar=False) + eigVal, eigVect = np.linalg.eig(np.mat(covMat)) + n = self.percent2n(eigVal) + eigValInd = np.argsort(eigVal) + eigValInd = eigValInd[-1:-(n + 1):-1] + n_eigVect = eigVect[:, eigValInd] + self.low_dataMat = dataMat * n_eigVect + [self.variance_ratio.append(eigVal[i] / sum(eigVal)) for i in eigValInd] + return self.low_dataMat + + def fit(self): + self._fit() + return self + +df = pd.read_csv(r'iris.txt', header=None) +data, label = df[range(len(df.columns) - 1)], df[[len(df.columns) - 1]] +data = np.mat(data) +print("Original dataset = {}*{}".format(data.shape[0], data.shape[1])) +pca = PCAcomponent(data, 3) +# pca = PCApercent(data, 0.98) +pca.fit() +print(pca.low_dataMat) +print(pca.variance_ratio) + +``` diff --git a/assets/src/DRA/DRA.0.3.md b/assets/src/DRA/DRA.0.3.md new file mode 100644 index 00000000..92552131 --- /dev/null +++ b/assets/src/DRA/DRA.0.3.md @@ -0,0 +1,200 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! + +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 多维缩放(Mutiple Dimensional Scaling) + +降维就是能够用一组个数为d的向量zi来代表个数为D的向量xi所包含的有用信息,其中d + +

+ +多维缩放(Mutiple Dimensional Scaling)的目标是在降维的过程中将数据的dissimilarity(差异性)保持下来,也可以理解降维让高维空间中的距离关系与低维空间中距离关系保持不变. + +算法原理: + +假定m个样本在原始空间的距离矩阵为,其第i 行和第j 列的元素为样本 的距离。这样就可以获得样本在d′ 维空间的表示,,而且任意两个样本在d′ 维空间中的欧式距离等于原始空间中的距离,即. + +因此令,其中B 为降维后样本的内积矩阵,,因而会有: + +

+ +

+ +则有: + +

+ +

+ +接下来我们用要用来表示. + +通常我们为方便计算,首先需要对数据进行中心化,即,则有: + +

+ +

+ +

+ +

+ +同理也有.则我们可以得到 +

+ +

+ +

+ +

+ +

+ +

+ + +其中为矩阵B的迹,定义为则可得到: + +

+ +

+ +因而: + +

+ +

+ +

+ +

+ +

+ +

+ +因此就会有: + +

+ +

+ +

+ +

+ +

+ +

+ +对于bij ,代入上式后得到: + +

+ +

+ +这样就可以求得降维后矩阵B的各个元素,接着对矩阵B 做特征值分解,即 + +

+ +

+ +通常,D 是一个对称实矩阵,此时得到的B刚好会有d个非0的特征值.其中 为特征值构成的对角矩阵.假定其中有d∗ 个非零特征值,它们构成对角矩阵 ,令V∗表示相应的特征向量矩阵,则Z可表达为: + +

+ +

+ +此外如果想还原原始样本矩阵,就选择d 个特征值和对应的特征向量,如果想要达到降维目的,就取个最大特征值和相应的特征向量。 + +应用示例: +```python + +import os, sys, getopt, pdb +from numpy import * +from numpy.linalg import * +from numpy.random import * +import pylab + +def mds(d, dimensions = 2): + """ + Multidimensional Scaling - Given a matrix of interpoint distances, + find a set of low dimensional points that have similar interpoint + distances. + """ + + (n,n) = d.shape + E = (-0.5 * d**2) + + # Use mat to get column and row means to act as column and row means. + Er = mat(mean(E,1)) + Es = mat(mean(E,0)) + + # From Principles of Multivariate Analysis: A User's Perspective (page 107). + F = array(E - transpose(Er) - Es + mean(E)) + + [U, S, V] = svd(F) + + Y = U * sqrt(S) + + return (Y[:,0:dimensions], S) + +def norm(vec): + return sqrt(sum(vec**2)) + +def square_points(size): + nsensors = size ** 2 + return array([(i / size, i % size) for i in range(nsensors)]) + +def test(): + + points = square_points(10) + + distance = zeros((100,100)) + for (i, pointi) in enumerate(points): + for (j, pointj) in enumerate(points): + distance[i,j] = norm(pointi - pointj) + + Y, eigs = mds(distance) + + pylab.figure(1) + pylab.plot(Y[:,0],Y[:,1],'.') + + pylab.figure(2) + pylab.plot(points[:,0], points[:,1], '.') + + pylab.show() + +def main(): + + def usage(): + print sys.argv[0] + "[-h] [-d]" + + try: + (options, args) = getopt.getopt(sys.argv[1:], 'dh', ['help','debug']) + except getopt.GetoptError: + # print help information and exit: + usage() + sys.exit(2) + + for o, a in options: + if o in ('-h', '--help'): + usage() + sys.exit() + elif o in ('-d', '--debug'): + pdb.set_trace() + + test() + +if __name__ == "__main__": + main() + +``` diff --git a/assets/src/DRA/DRA.0.4.md b/assets/src/DRA/DRA.0.4.md new file mode 100644 index 00000000..d9a3b485 --- /dev/null +++ b/assets/src/DRA/DRA.0.4.md @@ -0,0 +1,521 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 线性判别分析(Linear Discriminant Analysis) + +线性判别分析(Linear Discriminant Analysis),是一种监督学习(supervised learning)算法。线性判别式分析也叫做Fisher线性判别(Fisher Linear Discriminant ,FLD),是模式识别的经典算法,它是在1996年由Belhumeur引入模式识别和人工智能领域的。其鉴别分析的基本思想是将高维的模式样本投影到最佳鉴别矢量空间,以达到抽取分类信息和压缩特征空间维数的效果,投影后保证模式样本在新的子空间有最大的类间距离和最小的类内距离,即模式在该空间中有最佳的可分离性。因此,它是一种有效的特征抽取方法。使用这种方法能够使投影后模式样本的类间散布矩阵最大,并且同时类内散布矩阵最小。 + +线性判别分析(Linear Discriminant Analysis)是对费舍尔的线性鉴别方法的归纳,这种方法使用统计学,模式识别和机器学习方法,试图找到两类物体或事件的特征的一个线性组合,以能够特征化或区分它们。所得的组合可用来作为一个线性分类器,或者,更常见的是,为后续的分类做降维处理。 + +线性判别分析(Linear Discriminant Analysis)与方差分析(ANOVA)和回归分析紧密相关,这两种分析方法也试图通过一些特征或测量值的线性组合来表示一个因变量。然而,方差分析使用类别自变量和连续数因变量,而判别分析连续自变量和类别因变量(即类标签)。[3] 逻辑回归和概率回归比方差分析更类似于LDA,因为他们也是用连续自变量来解释类别因变量的。LDA的基本假设是自变量是正态分布的,当这一假设无法满足时,在实际应用中更倾向于用上述的其他方法。 + +线性判别分析(Linear Discriminant Analysis)也与主成分分析(PCA)和因子分析紧密相关,它们都在寻找最佳解释数据的变量线性组合。[4] LDA明确的尝试为数据类之间不同建立模型。 另一方面,PCA不考虑类的任何不同,因子分析是根据不同点而不是相同点来建立特征组合。判别的分析不同因子分析还在于,它不是一个相互依存技术:即必须区分出自变量和因变量(也称为准则变量)的不同。 + +在对自变量每一次观察测量值都是连续量的时候,LDA能有效的起作用。当处理类别自变量时,与LDA相对应的技术称为判别反应分析。 + +通常它能够保证投影后模式样本在新的空间中有最小的类内距离和最大的类间距离,即模式在该空间中有最佳的可分离性。 + + +应用示例: +```python +from __future__ import print_function + +import os +import time +import pickle +import itertools +import numpy as np +import matplotlib.pyplot as plt + +import theano +import lasagne + +# init color printer +class BColors: + """ + Colored command line output formatting + """ + HEADER = '\033[95m' + OKBLUE = '\033[94m' + OKGREEN = '\033[92m' + WARNING = '\033[93m' + FAIL = '\033[91m' + ENDC = '\033[0m' + BOLD = '\033[1m' + UNDERLINE = '\033[4m' + + def __init__(self): + """ Constructor """ + pass + + def print_colored(self, string, color): + """ Change color of string """ + return color + string + BColors.ENDC + +col = BColors() + + +def threaded_generator(generator, num_cached=10): + """ + Threaded generator + """ + import Queue + queue = Queue.Queue(maxsize=num_cached) + queue = Queue.Queue(maxsize=num_cached) + end_marker = object() + + # define producer + def producer(): + for item in generator: + #item = np.array(item) # if needed, create a copy here + queue.put(item) + queue.put(end_marker) + + # start producer + import threading + thread = threading.Thread(target=producer) + thread.daemon = True + thread.start() + + # run as consumer + item = queue.get() + while item is not end_marker: + yield item + queue.task_done() + item = queue.get() + + +def generator_from_iterator(iterator): + """ + Compile generator from iterator + """ + for x in iterator: + yield x + + +def threaded_generator_from_iterator(iterator, num_cached=10): + """ + Compile threaded generator from iterator + """ + generator = generator_from_iterator(iterator) + return threaded_generator(generator, num_cached) + + +def accuracy_score(t, p): + """ + Compute accuracy + """ + return float(np.sum(p == t)) / len(p) + + +class LDA(object): + """ LDA Class """ + + def __init__(self, r=1e-3, n_components=None, verbose=False, show=False): + """ Constructor """ + self.r = r + self.n_components = n_components + + self.scalings_ = None + self.coef_ = None + self.intercept_ = None + self.means = None + + self.verbose = verbose + self.show = show + + def fit(self, X, y, X_te=None): + """ Compute lda on hidden layer """ + + # split into semi- and supervised- data + X_all = X.copy() + X = X[y >= 0] + y = y[y >= 0] + + # get class labels + classes = np.unique(y) + + # set number of components + if self.n_components is None: + self.n_components = len(classes) - 1 + + # compute means + means = [] + for group in classes: + Xg = X[y == group, :] + means.append(Xg.mean(0)) + self.means = np.asarray(means) + + # compute covs + covs = [] + for group in classes: + Xg = X[y == group, :] + Xg = Xg - np.mean(Xg, axis=0) + covs.append(np.cov(Xg.T)) + + # within scatter + Sw = np.average(covs, axis=0) + + # total scatter + X_all = X_all - np.mean(X_all, axis=0) + if X_te is not None: + St = np.cov(np.concatenate((X_all, X_te)).T) + else: + St = np.cov(X_all.T) + + # between scatter + Sb = St - Sw + + # cope for numerical instability + Sw += np.identity(Sw.shape[0]) * self.r + + # compute eigen decomposition + from scipy.linalg.decomp import eigh + evals, evecs = eigh(Sb, Sw) + + # sort eigen vectors according to eigen values + evecs = evecs[:, np.argsort(evals)[::-1]] + + # normalize eigen vectors + evecs /= np.apply_along_axis(np.linalg.norm, 0, evecs) + + # compute lda data + self.scalings_ = evecs + self.coef_ = np.dot(self.means, evecs).dot(evecs.T) + self.intercept_ = (-0.5 * np.diag(np.dot(self.means, self.coef_.T))) + + if self.verbose: + top_k_evals = evals[-self.n_components:] + print("LDA-Eigenvalues (Train):", np.array_str(top_k_evals, precision=2, suppress_small=True)) + print("Ratio min(eigval)/max(eigval): %.3f, Mean(eigvals): %.3f" % (top_k_evals.min() / top_k_evals.max(), top_k_evals.mean())) + + if self.show: + plt.figure("Eigenvalues") + ax = plt.subplot(111) + top_k_evals /= np.sum(top_k_evals) + plt.plot(range(self.n_components), top_k_evals, 'bo-') + plt.grid('on') + plt.xlabel('Eigenvalue', fontsize=20) + plt.ylabel('Explained Discriminative Variance', fontsize=20) + plt.ylim([0.0, 1.05 * np.max(top_k_evals)]) + + ax.tick_params(axis='x', labelsize=18) + ax.tick_params(axis='y', labelsize=18) + + return evals + + def transform(self, X): + """ transform data """ + X_new = np.dot(X, self.scalings_) + return X_new[:, :self.n_components] + + def predict_proba(self, X): + """ estimate probability """ + prob = -(np.dot(X, self.coef_.T) + self.intercept_) + np.exp(prob, prob) + prob += 1 + np.reciprocal(prob, prob) + prob /= prob.sum(axis=1).reshape((prob.shape[0], -1)) + return prob + + def predict_log_proba(self, X): + """ estimate log probability """ + return np.log(self.predict_proba(X)) + + +def create_iter_functions(l_out, l_in, y_tensor_type, objective, learning_rate, l_2, compute_updates): + """ Create functions for training, validation and testing to iterate one epoch. """ + + # init target tensor + targets = y_tensor_type('y') + + # compute train costs + tr_output = lasagne.layers.get_output(l_out, deterministic=False) + tr_cost = objective(tr_output, targets) + + # compute validation costs + va_output = lasagne.layers.get_output(l_out, deterministic=True) + va_cost = objective(va_output, targets) + + # collect all parameters of net and compute updates + all_params = lasagne.layers.get_all_params(l_out, trainable=True) + + # add weight decay + if l_2 is not None: + tr_cost += l_2 * lasagne.regularization.apply_penalty(all_params, lasagne.regularization.l2) + + # compute updates from gradients + all_grads = lasagne.updates.get_or_compute_grads(tr_cost, all_params) + updates = compute_updates(all_grads, all_params, learning_rate) + + # compile iter functions + tr_outputs = [tr_cost] + iter_train = theano.function([l_in.input_var, targets], tr_outputs, updates=updates) + + va_outputs = [va_cost, va_output] + iter_valid = theano.function([l_in.input_var, targets], va_outputs) + + # compile output function + compute_output = theano.function([l_in.input_var], va_output) + + return dict(train=iter_train, valid=iter_valid, test=iter_valid, compute_output=compute_output) + + +def train(iter_funcs, dataset, train_batch_iter, valid_batch_iter, r): + """ + Train the model with `dataset` with mini-batch training. + Each mini-batch has `batch_size` recordings. + """ + import sys + import time + + for epoch in itertools.count(1): + + # iterate train batches + batch_train_losses = [] + iterator = train_batch_iter(dataset['X_train'], dataset['y_train']) + generator = threaded_generator_from_iterator(iterator) + + start, after = time.time(), time.time() + for i_batch, (X_b, y_b) in enumerate(generator): + batch_res = iter_funcs['train'](X_b, y_b) + batch_train_losses.append(batch_res[0]) + after = time.time() + train_time = (after-start) + + # report loss during training + perc = 100 * (float(i_batch) / train_batch_iter.n_batches) + dec = int(perc // 4) + progbar = "|" + dec * "#" + (25-dec) * "-" + "|" + vals = (perc, progbar, train_time, np.mean(batch_train_losses)) + loss_str = " (%d%%) %s time: %.2fs, loss: %.5f" % vals + print(col.print_colored(loss_str, col.WARNING), end="\r") + sys.stdout.flush() + + print("\x1b[K", end="\r") + avg_train_loss = np.mean(batch_train_losses) + + # lda evaluation (accuracy based) + + # iterate validation batches + batch_valid_losses = [] + iterator = valid_batch_iter(dataset['X_valid'], dataset['y_valid']) + generator = threaded_generator_from_iterator(iterator) + net_output_va, y_va = None, np.zeros(0, dtype=np.int32) + for X_b, y_b in generator: + batch_res = iter_funcs['valid'](X_b, y_b) + batch_valid_losses.append(batch_res[0]) + + y_va = np.concatenate((y_va, y_b)) + net_output = iter_funcs['compute_output'](X_b) + if net_output_va is None: + net_output_va = net_output + else: + net_output_va = np.vstack((net_output_va, net_output)) + + avg_valid_loss = np.mean(batch_valid_losses) + + # compute train set net output + iterator = train_batch_iter(dataset['X_train'], dataset['y_train']) + generator = threaded_generator_from_iterator(iterator) + net_output_tr, y_tr = None, np.zeros(0, dtype=np.int32) + for i_batch, (X_b, y_b) in enumerate(generator): + y_tr = np.concatenate((y_tr, y_b)) + net_output = iter_funcs['compute_output'](X_b) + if net_output_tr is None: + net_output_tr = net_output + else: + net_output_tr = np.vstack((net_output_tr, net_output)) + + # fit lda on net output + print("") + dlda = LDA(r=r, n_components=None, verbose=True) + evals = dlda.fit(net_output_tr, y_tr) + + # predict on train set + proba = dlda.predict_proba(net_output_tr[y_tr >= 0]) + y_tr_pr = np.argmax(proba, axis=1) + tr_acc = 100 * accuracy_score(y_tr[y_tr >= 0], y_tr_pr) + + # predict on validation set + proba = dlda.predict_proba(net_output_va) + y_va_pr = np.argmax(proba, axis=1) + va_acc = 100 * accuracy_score(y_va, y_va_pr) + + # estimate overfitting + overfit = va_acc / tr_acc + + # collect results + yield { + 'number': epoch, + 'train_loss': avg_train_loss, + 'train_acc': tr_acc, + 'valid_loss': avg_valid_loss, + 'valid_acc': va_acc, + 'overfitting': overfit, + 'eigenvalues': evals + } + + +def fit(l_out, l_in, data, objective, y_tensor_type, + train_batch_iter, valid_batch_iter, + r=1e-3, num_epochs=100, patience=20, + learn_rate=0.01, update_learning_rate=None, + l_2=None, compute_updates=None, + exp_name='ff', out_path=None, dump_file=None): + """ Train model """ + + # log model evolution + log_file = os.path.join(out_path, 'results.pkl') + + print("\n") + print(col.print_colored("Running Test Case: " + exp_name, BColors.UNDERLINE)) + + # adaptive learning rate + learning_rate = theano.shared(np.float32(learn_rate)) + if update_learning_rate is None: + def update_learning_rate(lr, e): + return lr + learning_rate.set_value(update_learning_rate(learn_rate, 0)) + + # initialize evaluation output + pred_tr_err, pred_val_err, overfitting = [], [], [] + tr_accs, va_accs = [], [] + eigenvalues = [] + + print("Building model and compiling functions...") + iter_funcs = create_iter_functions(l_out, l_in, y_tensor_type, objective, learning_rate=learning_rate, + l_2=l_2, compute_updates=compute_updates) + + print("Starting training...") + now = time.time() + try: + + # initialize early stopping + last_improvement = 0 + best_model = lasagne.layers.get_all_param_values(l_out) + + # iterate training epochs + prev_acc_tr, prev_acc_va = 0.0, 0.0 + for epoch in train(iter_funcs, data, train_batch_iter, valid_batch_iter, r): + + print("Epoch {} of {} took {:.3f}s".format( + epoch['number'], num_epochs, time.time() - now)) + now = time.time() + + # update learning rate + learn_rate = update_learning_rate(learn_rate, epoch['number']) + learning_rate.set_value(learn_rate) + + # --- collect train output --- + + tr_loss, va_loss = epoch['train_loss'], epoch['valid_loss'] + train_acc, valid_acc = epoch['train_acc'], epoch['valid_acc'] + overfit = epoch['overfitting'] + + # prepare early stopping + if valid_acc >= prev_acc_va: + last_improvement = 0 + best_model = lasagne.layers.get_all_param_values(l_out) + + # dump net parameters during training + if dump_file is not None: + with open(dump_file, 'w') as fp: + params = lasagne.layers.get_all_param_values(l_out) + pickle.dump(params, fp) + + # increase improvement counter + last_improvement += 1 + + # plot train output + if train_acc is None: + txt_tr = 'costs_tr %.5f' % tr_loss + else: + txt_tr = 'costs_tr %.5f (%.3f), ' % (tr_loss, train_acc) + if train_acc >= prev_acc_tr: + txt_tr = col.print_colored(txt_tr, BColors.OKGREEN) + prev_acc_tr = train_acc + + if valid_acc is None: + txt_val = '' + else: + txt_val = 'costs_val %.5f (%.3f), tr/val %.3f' % (va_loss, valid_acc, overfit) + if valid_acc >= prev_acc_va: + txt_val = col.print_colored(txt_val, BColors.OKGREEN) + prev_acc_va = valid_acc + + print(' lr: %.5f' % learn_rate) + print(' ' + txt_tr + txt_val) + + # collect model evolution data + tr_accs.append(train_acc) + va_accs.append(valid_acc) + pred_tr_err.append(tr_loss) + pred_val_err.append(va_loss) + overfitting.append(overfit) + eigenvalues.append(epoch['eigenvalues']) + + # --- early stopping: preserve best model --- + if last_improvement > patience: + print(col.print_colored("Early Stopping!", BColors.WARNING)) + status = "Epoch: %d, Best Validation Accuracy: %.3f" % (epoch['number'], prev_acc_va) + print(col.print_colored(status, BColors.WARNING)) + break + + # maximum number of epochs reached + if epoch['number'] >= num_epochs: + break + + # shuffle train data + if not hasattr(data['X_train'], 'reset_batch_generator'): + rand_idx = np.random.permutation(data['X_train'].shape[0]) + data['X_train'] = data['X_train'][rand_idx] + data['y_train'] = data['y_train'][rand_idx] + + # save results + exp_res = dict() + exp_res['pred_tr_err'] = pred_tr_err + exp_res['tr_accs'] = tr_accs + exp_res['pred_val_err'] = pred_val_err + exp_res['va_accs'] = va_accs + exp_res['overfitting'] = overfitting + exp_res['eigenvalues'] = eigenvalues + + with open(log_file, 'w') as fp: + pickle.dump(exp_res, fp) + + except KeyboardInterrupt: + pass + + # set net to best weights + lasagne.layers.set_all_param_values(l_out, best_model) + + # evaluate on test set + test_losses, test_acc = [], [] + iterator = valid_batch_iter(data['X_test'], data['y_test']) + for X_b, y_b in iterator: + loss_te = iter_funcs['test'](X_b, y_b) + test_losses.append(loss_te[0]) + if len(loss_te) > 1: + test_acc.append(loss_te[1]) + + # compute evaluation measures + avg_loss_te = np.mean(test_losses) + avg_acc_te = np.mean(test_acc) + + print("--------------------------------------------") + print('Loss on Test-Set: %.5f' % avg_loss_te) + print("--------------------------------------------\n") + + if out_path is not None: + + # add test results and save results + exp_res['avg_loss_te'] = avg_loss_te + exp_res['avg_acc_te'] = avg_acc_te + + with open(log_file, 'w') as fp: + pickle.dump(exp_res, fp) + + return l_out, prev_acc_va +``` diff --git a/assets/src/DRA/DRA.0.5.md b/assets/src/DRA/DRA.0.5.md new file mode 100644 index 00000000..5cc0bdbd --- /dev/null +++ b/assets/src/DRA/DRA.0.5.md @@ -0,0 +1,149 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 等度量映射(IsometricMapping,Isomap) + +等度量映射(Isomap)是最经典的非线性映射降维方法之一,它在MDS的基础上引入了“测地距离”的概念,直接解决了MDS使用欧氏距离无法应对非线性流形的问题。 +测地距离(Geometric Distance)是高维流形中两点之间的最短距离,高维流形中,空间是不规则的,所以最短距离不一定是直线距离(欧氏距离)。就像蚂蚁从立方体的一面爬到另一面,不能直接横穿立方体一样。 + +

+ +

+ +图中左边的两个点的最近距离是蓝色实线的距离,而不应该是虚线的距离。 + +通常情况下真实的测地距离是非常难以求出的,但是等度量映射基于流形局部近似于欧式空间的定义提出了一种近似的求解方式。 + +我们通常的做法是: + +1. 求得原样本的KNN图,并依据定义保留其欧式距离。 +2. 所有非KNN的点间的距离规定为无穷大。 +3. 用dijkstra或floyd求出任意两点的最短路便可近似表示两点间的测地距离。 +4. 然后等度量映射(Isomap)将得到的测地距离矩阵输入MDS完成降维。 + +最后等度量映射(Isomap)将得到的测地距离矩阵输入MDS完成降维。 + +最后的结果是这样的。 + +

+ +

+ +应用示例: +```python +from IsomapCuda import * +from DataUtils import * +import getopt,sys + +GPU_MEM_SIZE = 512 + +def Isomap(dataSet,outfile,srcDims,trgDims,k,eps=1000000000., CIsomap=False): + """ + Classical isomap + """ + + #first do KNN + knnRefs,knnDists,knnm = KNN(dataSet,k,eps,srcDims) + mdists = [] + if CIsomap: + mdists = C_Isomap(knnDists,knnm,k) + + #then do APSP + pathMatrix = APSP(knnRefs,knnDists,knnm,eps) + del knnRefs + del knnDists + del knnm + + #then normalize the matrix + normMatrix = NormMatrix(pathMatrix,mdists) + del pathMatrix + del mdists + + #then get eigenvalues + #embedding = EigenEmbedding(normMatrix,trgDims) + embedding = QEig(normMatrix,trgDims) + del normMatrix + + return embedding + + +def NMIsomap(dataSet,outfile,srcDims,trgDims,k,eps=1000000000., saveSteps = False): + """ + Non-Metric Isomap + """ + + #first do KNN + knnRefs,knnDists = loadSplitTable(KNN(dataSet,k,eps,srcDims)) + + #then do APSP + pathMatrix = APSP(knnRefs,knnDists,eps) + del knnRefs + del knnDists + + #XXX:hacky way of saving this info + if saveSteps: + saveTable(pathMatrix,outfile[:-4]+'_distances.csv') + + #then get the rank matrix + origDims = len(pathMatrix) + rankMatrix = RankMatrix(pathMatrix) + del pathMatrix + + #then get the NMDS embedding + embedding = NMDS(rankMatrix, loadMatrix(dataSet)[:,:trgDims], origDims, trgDims) + + return embedding + + + +if __name__ == '__main__': + arg_values = ['nonmetric=','outdims=','indims=','if=','of=','k=','eps=','help','h'] + optlist, args = getopt.getopt(sys.argv[1:], 'x', arg_values) + + trgDims = 3 + srcDims = 10000000000 + k =6 + eps = 1000000000. + infile='swissroll.csv' + outfile='embedding.csv' + nonmetric=False + + + for o in optlist: + if o[0].strip('-') == 'outdims': + trgDims = int(o[1]) + for o in optlist: + if o[0].strip('-') == 'indims': + srcDims = int(o[1]) + for o in optlist: + if o[0].strip('-') == 'if': + infile = o[1] + for o in optlist: + if o[0].strip('-') == 'of': + outfile = o[1] + for o in optlist: + if o[0].strip('-') == 'k': + k = int(o[1]) + for o in optlist: + if o[0].strip('-') == 'nonmetric': + if o[1].strip(' \r\n\t') == 'True' or o[1].strip(' \r\n\t') == 'true': + nonmetric = True + + for o in optlist: + if o[0].strip('-') == 'help' or o[1].strip('-') == 'h': + print "The following commands are available:" + print "\t--if=inputfile\tDefaults to swissroll.csv" + print "\t--of=outputfile\tDefaults to embedding.csv" + print "\t--k=k_nearest_neighbours\tDefaults to 12" + print "\t--outdims=embedding_dimensions\tDefaults to 3" + print "\t--indims=input_dimensions\tDefaults to all in the input file" + print "\t--nonmetric\tEnables non-metric MDS embeddings" + result = None + if not nonmetric: + result = Isomap(infile,outfile,srcDims,trgDims,k,eps,False) + else: + result = NMIsomap(infile,outfile,srcDims,trgDims,k,eps,False) + + saveTable(result,outfile) +``` diff --git a/assets/src/DRA/DRA.0.6.md b/assets/src/DRA/DRA.0.6.md new file mode 100644 index 00000000..41683bc3 --- /dev/null +++ b/assets/src/DRA/DRA.0.6.md @@ -0,0 +1,356 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 局部线性嵌入(Locally Linear Embedding) +数据降维是指通过线性的或非线性的映射关系将高维数据转换成低维数据的过程。一般情况下,该低维数据代表了原始高维数据的主要成分(图1),并描述了原始高维数据的空间分布结构。由于经过降维后的数据更易于被分类、识别、可视化以及存储等,故数据降维技术在诸多科研领域受到了越来越多地关注。 + +从数据本身的的性质特征来看,数据降维可以大致分为线性降维和非线性降维两种技术方法。其中,线性降维技术仅对于数据维数相对较低、且具有全局线性结构的数据有着很好的降维效果。然而,在实际的科学研究中,科研工作者却需要面对海量的非线性高维数据。因此,能够有效处理高维非线性数据的方法亟待被提出,本文将介绍一种用于处理高维非线性数据的降维方法。 + +局部线性嵌入(Locally linear embedding, LLE)是一种非线性的降维方法,该算法由 Sam T.Roweis等人于2000年提出并发表在《Science》杂志上。LLE试图保留原始高维数据的局部性质,通过假设局部原始数据近似位于一张超平面上,从而使得该局部的某一个数据可以由其邻域数据线性表示。 + +Sam T.Roweis 和 Lawrence K.Saul提出局部线性嵌入(Locally linear embedding, LLE)算法,它是针对非线性数据的一种新的降维技术,并且能够使降维后的数据保持原有的拓扑结构。 LLE算法可以广泛的应用于非线性数据的降维、聚类以及图像分割等领域。 + +局部线性嵌入(Locally linear embedding, LLE)是最新提出的非线性降维方法。该算法即具有处理非线性数据的优点又有线性降维方法计算性能的优越性。 简单的讲,该方法是将高维流型用剪刀剪成很多的小块,每一小块可以用平面代替,然后再低维中重新拼合出来, 且要求保留各点之间的拓扑关系不变。整个问题最后被转化为两个二次规划问题。 + +局部线性嵌入(Locally linear embedding, LLE)算法可以归结为三步: +1. 寻找每个样本点的k个近邻点; +2. 由每个样本点的近邻点计算出该样本点的局部重建权值矩阵; +3. 由该样本点的局部重建权值矩阵和其近邻点计算出该样本点的输出值。 + +局部线性嵌入算法的第一步是计算出每个样本点的k个近邻点。把相对于所求样本点距离最近的k个样本点规定为所求样本点的k个近邻点。k是一个预先给定值。Sam T.Roweis 和 Lawrence K.Saul算法采用的是欧氏距离,则减轻复杂的计算。然而本文是假定高维空间中的数据是非线性分布的,采用了diijstra距离。Dijkstra 距离是一种测地距离,它能够保持样本点之间的曲面特性,在ISOMAP算法中有广泛的应用。针对样本点多的情况,普通的dijkstra算法不能满足LLE算法的要求。 + + +应用示例: +```python + +import numpy +import sources + +from sklearn import manifold +from sklearn.utils.extmath import randomized_svd +from sklearn.neighbors import NearestNeighbors + + +from wordreps import WordReps +from scipy.sparse import csr_matrix, eye +from scipy.sparse.linalg import eigsh +from scipy.sparse.linalg.eigen.arpack.arpack import ArpackNoConvergence + +from scipy.io import savemat, loadmat + +import sys +import time +import argparse +import collections + + +class MetaEmbed(): + + def __init__(self, wordreps, words): + self.words = words + self.ids = {} + for (i,word) in enumerate(words): + self.ids[word] = i + + self.reps = wordreps + self.dims = [x.dim for x in self.reps] + self.embeds = [] + N = len(words) + + # Create the source embedding matrices + write("Creating source embedding matrices...") + for i in range(len(self.reps)): + M = numpy.zeros((self.reps[i].dim, N), dtype=numpy.float64) + for j in range(N): + M[:,j] = self.reps[i].vects[self.words[j]] + self.embeds.append(M) + write("done\n") + pass + + def compute_neighbours(self, nns): + """ + Compute the nearest neighbours for each embedding. + """ + self.NNS = [] + for i in range(len(self.embeds)): + start_time = time.clock() + write("Computing nearest neighbours for embedding no = %d ..." % i) + nbrs = NearestNeighbors(n_neighbors=nns, algorithm='ball_tree').fit(self.embeds[i].T) + distances, indices = nbrs.kneighbors(self.embeds[i].T) + self.NNS.append(indices[:,1:]) + end_time = time.clock() + write("Done (%s sec.)\n" % str(end_time - start_time)) + pass + + def show_nns(self, word ,nns): + """ + Print nearest neigbours for a word in different embeddings. + """ + for i in range(len(self.embeds)): + print "Showing nearest neighbours for = %s" % word + print "\nEmbedding no = %d" % i + for s in self.NNS[i][self.ids[word], :][:nns]: + print self.words[s] + pass + + def compute_weights(self): + """ + Computes the reconstruction weights. + """ + start_time = time.clock() + T = 10 # no. of iterations. + alpha = 0.01 # learning rate. + N = len(self.words) + self.W = numpy.zeros((N, N), dtype=numpy.float64) + + # initialise the weights. + for i in range(N): + nns = set() + for j in range(len(self.embeds)): + for x in self.NNS[j][i,:]: + nns.add(x) + val = 1.0 / float(len(nns)) + for j in nns: + self.W[i,j] = val + + # iterate + for i in range(N): + write("\x1b[2K\rLearning weights for (%d of %d) = %s" % (i, N, self.words[i])) + for t in range(T): + d = [self.embeds[j][:,i] - numpy.sum([self.W[i,k] * self.embeds[j][:,k] for k in self.NNS[j][i,:]], axis=0) for j in range(len(self.embeds))] + #for j in range(len(self.embeds)): + # d.append(self.embeds[j][:,i] - numpy.sum([self.W[i,k] * self.embeds[j][:,k] for k in self.NNS[j][i,:]], axis=0)) + + grad = numpy.zeros(N, dtype=numpy.float64) + for j in range(len(self.embeds)): + for k in self.NNS[j][i,:]: + grad[k] += -2.0 * numpy.dot(d[j], self.embeds[j][:,k]) + + self.W[i,:] -= (alpha * grad) + + total = numpy.sum(self.W[i,:]) + if total != 0: + self.W[i,:] = self.W[i,:] / total + write("\n") + end_time = time.clock() + write("Done (took %s seconds)\n" % str(end_time - start_time)) + pass + + def save_weights(self, fname): + """ + Save the weight matrix to a disk file. + """ + savemat(fname, {"W":self.W}) + pass + + def load_weights(self, fname): + """ + Load the weight matrix from a disk file. + """ + self.W = loadmat(fname)["W"] + pass + + def test_compute_weights(self): + """ + Check whether the weights are computed correctly + """ + N = len(self.words) + # Check whether non-neighbours have weights equal to zero. + write("Checking whether non-neighbours have zero weights...\n") + for i in range(N): + pred_nns = set(numpy.where(self.W[i,:] != 0)[0]) + nns = set() + for j in range(len(self.embeds)): + nns = nns.union(set(self.NNS[j][i,:])) + assert(pred_nns == nns) + + # Check whether reconstruction weights add upto one. + write("Checking whether weights add to 1...\n") + for i in range(N): + assert(numpy.allclose(numpy.sum(self.W[i,:]), 1)) + + # print nearest neighbours and their weights + nn_file = open("../work/nn.csv", 'w') + for i in range(N): + nn_file.write("%s, " % self.words[i]) + L = [] + for j in range(N): + if self.W[i,j] != 0: + L.append((self.words[j], self.W[i,j])) + L.sort(lambda x, y: -1 if x[1] > y[1] else 1) + for (w, val) in L: + nn_file.write("%s, %f, " % (w, val)) + nn_file.write("\n") + nn_file.close() + pass + + def compute_M(self): + """ + Compute the smallest eigenvectors of M = (I - W')\T(I - W'). + """ + # Building W' + N = len(self.words) + start_time = time.clock() + write("Computing W'...") + for i in range(N): + z = numpy.zeros(N) + write("Completed %d of %d\r" % (i, N)) + for nns in self.NNS: + z[nns[i,:]] += 1 + self.W[i,:] = z * self.W[i,:] + end_time = time.clock() + write("Done (took %s seconds)\n" % str(end_time - start_time)) + + # Computing M. + start_time = time.clock() + write("Computing M....") + self.W = csr_matrix(self.W) + M = eye(N, format=self.W.format) - self.W + M = (M.T * M).tocsr() + end_time = time.clock() + write("Done (took %s seconds)\n" % str(end_time - start_time)) + return M + + def compute_embeddings(self, k, M, embed_fname): + """ + Perform eigen decomposition. + """ + N = len(self.words) + start_time = time.clock() + write("Computing Eigen decomposition...") + s, V = eigsh(M, k+1, tol=1E-6, which="SA", maxiter=100) + end_time = time.clock() + write("Done (took %s seconds)\n" % str(end_time - start_time)) + P = V[:, 1:] + err = numpy.sum(s[1:]) + write("Projection error = %f\n" % err) + + write("Writing embeddings to file...") + # Write embeddings to file. + with open(embed_fname, 'w') as embed_file: + for i in range(N): + embed_file.write("%s %s\n" % (self.words[i], " ".join([str(x) for x in P[i,:]]))) + write("Done\n") + pass + + +def write(msg): + sys.stdout.write(msg) + sys.stdout.flush() + pass + + +def meta_embed(embeddings, words, nns, comps, embed_path): + """ + Perform meta-embedding using LLE. + """ + ME = MetaEmbed(embeddings, words) + ME.compute_neighbours(nns) + #ME.show_nns("king", 5) + + #ME.compute_weights_parallel() + ME.compute_weights() + + #ME.save_weights("../work/weights_%d" % nns) + #ME.load_weights("../work/weights+n=%d.meta" % nns) + #ME.test_compute_weights() + M = ME.compute_M() + for k in comps: + embed_fname = "%s/n=%d+k=%d" % (embed_path, nns, k) + write("Embedding NNS = %d, Components (k) = %d\n" % (nns, k)) + try: + ME.compute_embeddings(k, M, embed_fname) + except ArpackNoConvergence as e: + print e + return ME + + +def baseline_concatenate(embeddings, words, embed_fname): + """ + Concatenate embeddings to create co-embeddings. + """ + dim = sum([x.dim for x in embeddings]) + + print "Concatenation dimension =", dim + # concatenate the vectors. + with open(embed_fname, 'w') as embed_file: + for (i,word) in enumerate(words): + L = [] + for x in embeddings: + w = 8 if x.dim == 300 else 1 + #w = 1 + L.append(w * x.vects[word]) + + z = numpy.concatenate(L) + embed_file.write("%s %s\n" % (word, " ".join([str(x) for x in z]))) + pass + +def get_common_words(embeddings): + words = set(embeddings[0].vocab) + for i in range(1, len(embeddings)): + words = words.intersection(set(embeddings[i].vocab)) + return words + + +def get_selected_words(fname): + words = [] + with open(fname) as F: + for line in F: + words.append(line.strip()) + return words + +def perform_embedding(nns, comps): + print "Neigbourhood size = %d" % nns + + #embed_sett + embed_settings = sources.embed_settings + embeddings = [] + for (embd_fname, dim) in embed_settings: + start_time = time.clock() + sys.stdout.write("Loading %s -- (%d dim) ..." % (embd_fname, dim)) + sys.stdout.flush() + WR = WordReps() + WR.read_model(embd_fname, dim) + end_time = time.clock() + sys.stdout.write("\nDone. took %s seconds\n" % str(end_time - start_time)) + sys.stdout.flush() + embeddings.append(WR) + + common_words = get_common_words(embeddings) + selected_words = get_selected_words("../work/selected-words") + words = [] + for word in selected_words: + if word in common_words and word not in words: + words.append(word) + print "No. of common words =", len(common_words) + print "Vocabulary size =", len(words) + ME = meta_embed(embeddings, words, nns, comps, "../work/meta-embeds") + pass + +def save_embedding(words, WR, fname): + F = open(fname, 'w') + for w in words: + if w in WR.vects: + F.write("%s " % w) + F.write("%s\n" % " ".join([str(x) for x in WR.vects[w]])) + # elif w.lower() in WR.vects: + # F.write("%s " % w.lower()) + # F.write("%s\n" % " ".join([str(x) for x in WR.vects[w.lower()]])) + F.close() + pass + +def main(): + parser = argparse.ArgumentParser() + parser.add_argument("-nns", type=int, help="number of nearest neighbours") + parser.add_argument("-comps", type=str, help="components for the projection") + args = parser.parse_args() + comps = [int(x) for x in args.comps.split(',')] + perform_embedding(args.nns, comps) + pass + +if __name__ == '__main__': + main() + pass + +``` diff --git a/assets/src/DRA/DRA.0.7.md b/assets/src/DRA/DRA.0.7.md new file mode 100644 index 00000000..082ec559 --- /dev/null +++ b/assets/src/DRA/DRA.0.7.md @@ -0,0 +1,203 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 拉普拉斯特征映射(Laplacian Eigenmaps) + +拉普拉斯特征映射(Laplacian Eigenmaps,LE),就是将核函数方法应用在局部保持投影的非监督降维方法,也是无监督降维的一种方法,LE方法的直观思想是希望相互间有关系的点(在图中相连的点)在降维后的空间中尽可能的靠近。LE可以反映出数据内在的流形结构。 + +拉普拉斯特征映射是一种基于图的降维算法,它希望相互间有关系的点(在图中相连的点)在降维后的空间中尽可能的靠近,从而在降维后仍能保持原有的数据结构。 借鉴了图论里面的Laplacian矩阵,把每个样本点看成图中的一个节点,通过样本距离或者邻接矩阵得到W(可以表征样本间的相似关系,用来重构数据流形的局部结构特征),再通过D = diag(sum(W,2)),得到对角的度矩阵(每个元素都是行和或者列和),然后通过L = D - W 得到Laplacian矩阵。 + +Laplacian Eigenmaps算法的主要思想是,如果两个数据实例i和j很相似,那么i和j在降维后目标子空间中应该尽量接近。设数据实例的数目为n,目标子空间即最终的降维目标的维度为m。定义n×m大小的矩阵Y,其中每一个行向量yTi是数据实例i在目标m维子空间中的向量表示(即降维后的数据实例i)。 + + +Laplacian Eigenmap算法主要步骤: + +1. 建立邻接图:这里采用ϵ−最近邻图和K−最近邻图都能够解决问题。两种方法各有利弊,前者几何解释清楚,并且邻接矩阵天然是对称的,然而参数选择有困难,并且图的连通性未必有好的保证;后者参数选择容易,且图的连接性较好,但是几何解释不清晰。 + + +2. 赋权:我们常用热核来赋给权重,即对于连通的两个点i,i′,令;而对其它点对权值赋0. 最终我们可以用邻接矩阵W来表示这个图. + +3. 计算Laplace算子矩阵:完成建图后,我们定义顶点vi的度是: +

+ +

+ +并构造一个度矩阵: + +

+ +

+ +由此即可得到未归一化的图Laplace矩阵: + +

+ +

+ +容易说明, L是对称半正定矩阵,特征值是非负实数,且0是L的特征值,而特征向量是常1向量。值得说明的是我们经常采用的是经过归一化的L矩阵,规范化的方法是: + +

+ +

+ +4. 计算特征向量:即解以下问题: + +

+ +

+ +得到特征值 + +5. 特征映射:(先验地)假定低维流形维数d的值,并将数据映射到特征空间上,即 + +

+ +

+ +这就是拉普拉斯特征映射(Laplacian Eigenmaps)算法进行数据降维处理的全过程。 + +应用示例: +```python + from numpy import exp, median +from scipy.sparse.csgraph import laplacian +from sklearn.manifold.locally_linear import ( + null_space, LocallyLinearEmbedding) +from sklearn.metrics.pairwise import pairwise_distances, rbf_kernel +from sklearn.neighbors import kneighbors_graph, NearestNeighbors + + +def ler(X, Y, n_components=2, affinity='nearest_neighbors', + n_neighbors=None, gamma=None, mu=1.0, y_gamma=None, + eigen_solver='auto', tol=1e-6, max_iter=100, + random_state=None): + """ + Laplacian Eigenmaps for Regression (LER) + + Parameters + ---------- + X : ndarray, 2-dimensional + The data matrix, shape (num_points, num_dims) + + Y : ndarray, 1 or 2-dimensional + The response matrix, shape (num_points, num_responses). + + n_components : int + Number of dimensions for embedding. Default is 2. + + affinity : string or callable, default : "nearest_neighbors" + How to construct the affinity matrix. + - 'nearest_neighbors' : construct affinity matrix by knn graph + - 'rbf' : construct affinity matrix by rbf kernel + + n_neighbors : int, optional, default=None + Number of neighbors for kNN graph construction on X. + + gamma : float, optional, default=None + Scaling factor for RBF kernel on X. + + mu : float, optional, default=1.0 + Influence of the Y-similarity penalty. + + y_gamma : float, optional + Scaling factor for RBF kernel on Y. + Defaults to the inverse of the median distance between rows of Y. + + Returns + ------- + embedding : ndarray, 2-dimensional + The embedding of X, shape (num_points, n_components) + """ + + if eigen_solver not in ('auto', 'arpack', 'dense'): + raise ValueError("unrecognized eigen_solver '%s'" % eigen_solver) + + nbrs = NearestNeighbors(n_neighbors=n_neighbors + 1) + nbrs.fit(X) + X = nbrs._fit_X + + Nx, d_in = X.shape + Ny = Y.shape[0] + + if n_components > d_in: + raise ValueError("output dimension must be less than or equal " + "to input dimension") + if Nx != Ny: + raise ValueError("X and Y must have same number of points") + if affinity == 'nearest_neighbors': + if n_neighbors >= Nx: + raise ValueError("n_neighbors must be less than number of points") + if n_neighbors == None or n_neighbors <= 0: + raise ValueError("n_neighbors must be positive") + elif affinity == 'rbf': + if gamma != None and gamma <= 0: + raise ValueError("n_neighbors must be positive") + else: + raise ValueError("affinity must be 'nearest_neighbors' or 'rbf' must be positive") + + if Y.ndim == 1: + Y = Y[:, None] + + if y_gamma is None: + dists = pairwise_distances(Y) + y_gamma = 1.0 / median(dists) + + if affinity == 'nearest_neighbors': + affinity = kneighbors_graph(X, n_neighbors, include_self=True) + else: + if gamma == None: + dists = pairwise_distances(X) + gamma = 1.0 / median(dists) + affinity = kneighbors_graph(X, n_neighbors, mode='distance', include_self=True) + affinity.data = exp(-gamma * affinity.data ** 2) + + K = rbf_kernel(Y, gamma=y_gamma) + lap = laplacian(affinity, normed=True) + lapK = laplacian(K, normed=True) + embedding, _ = null_space(lap + mu * lapK, n_components, + k_skip=1, eigen_solver=eigen_solver, + tol=tol, max_iter=max_iter, + random_state=random_state) + + return embedding + + +class LER(LocallyLinearEmbedding): + """Scikit-learn compatible class for LER.""" + + def __init__(self, n_components=2, affinity='nearest_neighbors', + n_neighbors=2, gamma=None, mu=1.0, y_gamma=None, + eigen_solver='auto', tol=1E-6, max_iter=100, + random_state=None, neighbors_algorithm='auto'): + + self.n_components = n_components + self.affinity = affinity + self.n_neighbors = n_neighbors + self.gamma = gamma + self.mu = mu + self.y_gamma = y_gamma + self.eigen_solver = eigen_solver + self.tol = tol + self.max_iter = max_iter + self.random_state = random_state + self.neighbors_algorithm = neighbors_algorithm + + def fit_transform(self, X, Y): + self.fit(X, Y) + return self.embedding_ + + def fit(self, X, Y): + # NN necessary for out-of-sample extensions + self.nbrs_ = NearestNeighbors(self.n_neighbors, + algorithm=self.neighbors_algorithm) + self.nbrs_.fit(X) + + self.embedding_ = ler( + X, Y, n_components=self.n_components, + affinity=self.affinity, n_neighbors=self.n_neighbors, + gamma=self.gamma, mu=self.mu, y_gamma=self.y_gamma, + eigen_solver=self.eigen_solver, tol=self.tol, + max_iter=self.max_iter, random_state=self.random_state) + + return self +``` diff --git a/assets/src/DRA/DRA.0.8.md b/assets/src/DRA/DRA.0.8.md new file mode 100644 index 00000000..33f9d169 --- /dev/null +++ b/assets/src/DRA/DRA.0.8.md @@ -0,0 +1,227 @@ +### Deeplearning Algorithms tutorial + +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### t-分布随机近邻嵌入(t-SNE) + +t-分布随机近邻嵌入(t-Distributed Stochastic Neighbor Embedding,t-SNE) 是用于降维的一种机器学习算法,是由 Laurens van der Maaten 和 Geoffrey Hinton在08年提出来。此外,t-SNE 是一种非线性降维算法,非常适用于高维数据降维到2维或者3维,进行可视化。 + +流形(Manifold)是局部具有欧式空间性质的空间,包括各种纬度的曲线曲面,例如球体、弯曲的平面等。流形的局部和欧式空间是同构的。但是在全局尺度下不能简单的用欧式几何计算。一个好理解的例子就是地球,我们在几米的尺度下计算三角形的内角和是180度,但是在几百公里的尺度下会大于180度。因为地球上有意义的数据点是分布在球面上的,此时需要引入黎曼几何来描述问题。可见流形空间在真实世界中其实是大量存在的,所以我们对数据进行了一个假设,假设数据都是在高维欧式空间中的低维流形,如果我们能将其降维到低维,就能直观的发现其本质和一些内在规律。t-SNE就是基于这样的一个假设。 + +降维(dimension reduction)的基本作用: + +* 缓解维数灾难。即提高样本密度,以及使基于欧氏距离的算法重新生效。 + +* 数据预处理。对数据去冗余、降低信噪比。 + +* 方便可视化。 + +降维的概念中有两对直觉性的概念会反复出现:高维/低维空间、高维/低维数据。在文献中他们有若干别称: + +* 高维空间(high-dimensional space),又叫原空间(original space) + +* 高维数据(low-dimensional data),也直接叫数据点(data points),用于和下述的映射点对应。 + +* 低维空间(low-dimensional space),又叫嵌入空间(embedded space)、低维映射(low-dimensional map,map在此做名词用)等。 + +* 低维数据(low-dimensional data),又叫低维嵌入(low-dimensional embeddings)、低维表示(low-dimensional representations)、映射点(map points)等。 + +嵌入(embedding):数学上,嵌入是指一个数学结构经映射包含在另一个结构中。 + +* NLP目前所使用的词嵌入(word embedding)一词的本意可能就是这个意思。最初所使用的词向量是one-hot向量,维度等于词表大小(约几十万)。后来采用分布式表示的词向量,维度一般取几百维。因此我们认为分布式表示的词向量是更高维度语义空间的低维嵌入(embedding)。 + +* "Embed Everything!" 嵌入的思想不仅可以用在词(word)上,还能用于许多其他技术上。如知识图谱中可以把原先的网络结构也做嵌入,有实体嵌入、关系嵌入等。 + +降维技术可以分为线性和非线性两大类. + +线性降维技术。侧重让不相似的点在低维表示中分开。 + +* PCA(Principle Components Analysis,主成分分析). + +* MDS(Multiple Dimensional Scaling,多维缩放)等. + +非线性降维技术(广义上“非线性降维技术”≈“流形学习”,狭义上后者是前者子集)。这类技术假设高维数据实际上处于一个比所处空间维度低的非线性流形上,因此侧重让相似的近邻点在低维表示中靠近。 + +* Sammon mapping. + +* SNE(Stochastic Neighbor Embedding,随机近邻嵌入),t-SNE是基于SNE的。 + +* Isomap(Isometric Mapping,等度量映射). + +* MVU(Maximum Variance Unfolding). + +* LLE(Locally Linear Embedding,局部线性嵌入)等. + +流形(manifold): + +* 机器学习中指的流形指本征维度较低但嵌入在高维空间中的空间(a manifold haslow intrinsic dimensions, and is embedded within a space of much higher dimensionality)。比如上图中的S-curve数据集,本征维度=2(摊开来是一个二维空间),但被嵌在三维空间中。 + +* 数学中提到流形,强调其具有局部欧式空间的性质,可以在局部应用欧几里得距离。但是在机器学习(流形学习)中,这个假设基本不成立。原因是高维空间由于维数灾难的存在,没有足够稠密的数据能在足够小的局部去近似该流形。 + +* 但是流形概念中局部的思想仍可以借鉴。它为降维提供了另一个视角:从微观角度去探索高维数据结构。 + +学习:流形学习之所以叫学习,因为它不像PCA一类的纯线性代数降维方法,而是更像一个类似神经网络的学习算法。 + +* 神经网络大部分是有监督学习;流形学习大部分是无监督学习。 + +* 神经网络拟合一个分类函数;流形学习(以t-SNE为例)拟合高维数据的分布。 + +* 神经网络学习参数;流形学习(以t-SNE为例)直接学习低维数据的表达。 + +* 两者均有损失函数、梯度下降、迭代轮数等学习算法的特点。 + +#### t-分布 + +学生t-分布(t-distribution)用于根据小样本来估计呈正态分布且方差未知的总体的均值。其曲线形态与自由度有关,自由度越小,t分布越平坦;自由度为无穷时,t分布等同于标准正态分布。本文主要目的是理解t-SNE,所以只需要知道t-分布的解析式和曲线形状(见下图)即可,更多的内容请自行Wiki。 + +

+ +

+ +#### SNE + +t-SNE可以看做是SNE的改进,所以我们从SNE开始说起。SNE的核心思路可以概括如下: + +在高维空间相似的数据点,映射到低维空间距离也是相似的。常规的做法是用欧式距离表示这种相似性,而SNE把这种距离关系转换为一种条件概率来表示相似性。并使高维和低维下每个数据点对于其他数据点的相似性分布尽量接近。 + +对于高维空间中每一个数据点 xi来说,xj是剩下的每个数据点,我们可以算出 xi 和每一个 xj 的欧式距离 dj 。但是不同维度下的欧式距离没有可比性,所以SNE的想法是构造一个概率来表征出这种距离的相似度来,一个合适易求导的分布就是高斯分布。构造一个 μ=xi 的高斯分布,并假设 σ=σi 是已知的(方差如何选择会在后面讨论)。那么每个 xj 和 xj 的距离对应的概率就可以作为相似度的度量。如下图,显然距离远的点相似度很底,距离近的点相似度很高。 + +那么这个“高斯相似度”可以定义如下: + +

+ +

+ +另外因为我们只考虑不同数据点之间的相似度,所以定义 sim(xi,xi)=0. + +对 xi 和所有的 xj 计算相似度,我们就可以得到 xi 的相似度分布了,这个分布每一点的概率可以写成条件概率的形式,为了保证概率和为1,需要做归一化。即: + +

+ +

+ + +相应的,在低维度我们做同样的处理,设 xi 在低维的映射是 yi ,则可以得到低维下拟合每对数据点相似度的条件概率 。另外由于我们可以任意假设低维下数据点的分布,为了方便和好看就设置每个数据点的相似度分布(同样是高斯分布)的 。于是有 + + +

+ +

+ +此时就很明朗了,如果 yi 和 yj 能真实反映 xi 和 xj 的关系,那么 pj|i 和 qj|i 就应该是完全相等的。我们对所有j计算条件概率,就能得到这个条件概率的完整分布 Pi 。同理可以得到低维下的分布 Qi 。我们的目标就是使两个分布尽量接近,自然而然想到了KL散度。于是SNE的代价函数就可以写出来了,用梯度下降求解即可。 + +

+ +

+ +求梯度的过程参考softmax函数的梯度,这里不重要,省略过程。对 yi 求梯度得到: + +

+ +

+ +其实这个梯度是有一定物理意义的,可以把 yi 看做一个分子,它最终的受力方向是由所有其他分子对它的合力决定的。对其中一个分子j来说, (pj∣i−qj∣i+pi∣j−qi∣j) 决定了力的大小,(yi−yj) 决定了力的方向。在初始化中,可以用较小的 σ 下的高斯分布来进行初始化。为了加速优化过程和避免陷入局部最优解,梯度中需要使用一个相对较大的动量(momentum)。即参数更新中除了当前的梯度,还要引入之前的梯度累加的指数衰减项,如下: + + +

+ +

+ +这里的 Y(t) 表示迭代t次的解,η 表示学习速率, α(t) 表示迭代t次的动量。另外SNE在超参数的选择上需要做多次优化才可以。 + + +#### 困惑度(Perplexity) + +刚才在构建 qj|i 时,我们假设已知了每个 xi 的高斯相似度分布的 σ 。那 σ 究竟应该怎么设置呢?SNE的唯一参数困惑度就是用来为每个数据点 xi 寻找合适的 σi 的。困惑度可以定义为: + +

+ +

+ +其中 H(Pi) 是 Pi 的香农熵。从直观上是可以理解这个式子的,数据越混乱,熵越大,为了使每个数据点的困惑度都满足给定的困惑度,就需要一个很大的 σi使高斯分布尽量平坦,这样得到的每个 pj|i 就更接近一些。实际上我们经常将Perp设置为近邻数,因为增大 σ 就相当于增加近邻数据点。困惑度通常会被设置为 5 - 50 之间,并且在这个范围内具有良好的鲁棒性。 + +因为 σi 和 Perp(Pi)是线性相关的,所以当设置好Perp后,我们可以简单的用 Binary Search 去为每个高斯分布找一个对应的 σi 。 + +#### Symmetric SNE + +SNE设计出来之后,效果其实并没有想象的那么好。在人们尝试着去寻找优化方案时发现了这样一个问题, pj|i 和 pi|j 是不对称的。这违背了相似度这个概念的初衷,Symmetric SNE 就是来解决这个问题的。 + +Symmetric SNE 把条件概率转换为了联合概率去度量相似度,这样就确保了对称性。在实践中联合概率采用了一种简单直观的定义方式: + +

+ +

+ +其中n为数据点总数。这样定义既保证了对称性,又保证了每个点对总代价的贡献都不会太小(因为 )。此外,由联合分布计算出的梯度拥有更简单的形式,计算效率更高了。 + +

+ +

+ +#### 拥挤问题(The Crowding Problem) + +虽然 Symmetric SNE 解决了不对称问题,但是其得到的结果类边界也还是有一些模糊。这里涉及到了一个从高维降到低维所面临的拥挤问题。举个例子,我们假设在10维空间中有11个点两两距离相等,但是其降到可以可视化的二维后,我们是没有办法保存它们距离两两相等的信息的,因为在二维空间中最多只有三个点的距离可以两两相等。 + +再假设在三维空间里有一个球体,数据点在球体内均匀分布。如果想把它降到二维,根据各个点到球心的距离,会得到一个圆形范围,且越靠近球面的数据点越密集。同理,越是高维的“球体”,降到低维后边缘越拥挤,因为高维球体的体积是呈 rd 增长的。这就是所谓的拥挤问题,降维后的簇会拥挤在一起无法区分,SNE 和 Symmetric SNE 都不能很好地解决这个问题。 + +#### t-SNE + +然后t-SNE出现了,t-SNE在SNE的基础上做出了如下两个改进: + +* 使用联合概率代替条件概率(同 Symmetric SNE) +* 在低维空间使用t分布代替高斯分布(高维空间不变) + +其中第一个改进保证了对称性和代价函数的下限,第二个改进一定程度上解决了拥挤问题。那么t分布是怎么解决拥挤问题的呢? + +

+ +

+ +t分布有一个重要的特点:属于长尾分布。我们看上图,高斯分布在3sigma后的概率密度就变得特别小,因此为了迎合长尾部分的数据,它会主动变得平坦,从而导致拟合不准确。或者可以说,高斯分布对异常值较为敏感。而t分布的长尾特性使其既能兼顾均值周围的数据点,又能兼顾边缘的数据点,更好的捕获了数据的特征。 + +

+ +

+ +除此之外,高斯分布和t分布的差异也有助于缓解拥挤问题。我们看上图,横轴表示距离,纵轴表示相似度, 可以看到,对于较大相似度的点,t分布在低维空间中的距离需要稍小一点;而对于低相似度的点,t分布在低维空间中的距离需要更远。这恰好满足了我们的需求,即同一簇内的点(距离较近)聚合的更紧密,不同簇之间的点(距离较远)更加疏远。 + +使用了自由度为1的t分布后, qij 变成了: + +

+ +

+ +可以看出公式里少了指数函数,计算上会方便很多。最终得到t-SNE的更新梯度(推导见原论文Appendix)是: + +

+ +

+ +然后再利用梯度下降求解 yi 即可。 + +#### t-SNE效果 + +t-SNE降维后的效果,总体是完爆其他可视化降维方法的。 + +

+ +

+ +t-SNE得到的是局部最优解。因为KL散度是一个不对称的度量,从代价函数的公式中可以看出,当 pj|i 较大, qj|i 较小时,代价较高;而当 qj|i 较大, pj|i 较小时,代价较低。什么意思呢?就是当高维空间距离远,低维空间距离近的时候,代价函数会很高,模型会尽量避免这种事情发生,所以会加大低维的距离,这没问题。 + +但是当高维近低维远的时候,代价会变低,模型也就不会在乎这个问题,导致低维空间距离较远的点始终拉不近。换句话说,t-SNE的代价函数更关注局部结构,而忽视了全局结构。所以假设数据集是在高维空间中的低维流形这一点是比较重要的,如果数据集的本征维度本身就很高,那么是不可能完整的映射到2-3维空间的。 + +#### t-SNE优点 + +流形学习中其他方法如Isomap、LLE等,主要用于展开单个连续的低维流形(比如“瑞士卷”数据集),而t-SNE主要用于数据的局部结构,并且会倾向于提取出局部的簇,这种能力对于可视化同时包含多个流形的高维数据(比如MNIST数据集)很有效。 + +#### t-SNE缺点 + +* 时间、空间复杂度为O(n^2),计算代价昂贵。百万量级的数据需要几小时,对于PCA可能只需要几分钟。 + +* 升级版Barnes-Hut t-SNE可以让复杂度降为O(nlogn),但只限于获得二维和三维的嵌入。(sklearn中可以直接使用参数method='barnes_hut') + +* 由于代价函数非凸,多次执行算法的结果是随机的(名字中“Stochatsic”的由来?),需要多次运行选取最好的结果。 + +* 全局结构不能很清楚的保留。这个问题可以通过先用PCA降维到一个合理的维度(如50)后再用t-SNE来缓解,前置的PCA步骤也可以起到去除噪声等功能。(sklearn中可以直接使用参数init='pca'). diff --git a/assets/src/DRA/DRA.0.9.md b/assets/src/DRA/DRA.0.9.md new file mode 100644 index 00000000..c9bf8de9 --- /dev/null +++ b/assets/src/DRA/DRA.0.9.md @@ -0,0 +1,7 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 深度自动编码器(Deep Autoencoder Networks) + +自动编码器是一种无监督的神经网络模型,它可以学习到输入数据的隐含特征,这称为编码(coding),同时用学习到的新特征可以重构出原始输入数据,称之为解码(decoding)。从直观上来看,自动编码器可以用于特征降维,类似主成分分析PCA,但是其相比PCA其性能更强,这是由于神经网络模型可以提取更有效的新特征。除了进行特征降维,自动编码器学习到的新特征可以送入有监督学习模型中,所以自动编码器可以起到特征提取器的作用。作为无监督学习模型,自动编码器还可以用于生成与训练样本不同的新数据,这样自动编码器(变分自动编码器,Variational Autoencoders)就是生成式模型。 diff --git a/assets/src/DT/DT.0.1.md b/assets/src/DT/DT.0.1.md new file mode 100644 index 00000000..35229062 --- /dev/null +++ b/assets/src/DT/DT.0.1.md @@ -0,0 +1,39 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 决策树(Decision Tree) + +决策树(Decision Tree)是应用于分类的一种树结构。其中的每个内部节点(internal node)代表对某个属性的一次测试判别,一个分枝代表一个测试结果,叶子(leaf)代表某个类(class)或者类的分布(class distribution)。最顶层的节点是根结点。可以将决策树理解为一个if-then规则的集合,由决策树的根节点到叶节点的每一条路径构建一条规则。 + +最早的决策树算法是由Hunt等人于1966年提出的CLS。当前最有影响的决策树算法是Quinlan于1986年提出的ID3和1993年提出的C4.5。ID3只能处理离散型描述属性,它选择信息增益最大的属性划分训练样本,其目的是进行分枝时系统的熵最小,从而提高算法的运算速度和精确度。ID3算法的主要缺陷是,用信息增益作为选择分枝属性的标准时,偏向于取值较多的属性,而在某些情况下,这类属性可能不会提供太多有价值的信息。C4.5是ID3算法的改进算法,不仅可以处理离散型描述属性,还能处理连续性描述属性。C4.5采用了信息增益比作为选择分枝属性的标准,弥补了ID3算法的不足。 + +决策树经常在运筹学中使用,特别是在决策分析中,它帮助确定一个能最可能达到目标的策略。如果在实际中,决策不得不在没有完备知识的情况下被在线采用,一个决策树应该平行概率模型作为最佳的选择模型或在线选择模型算法。决策树的另一个使用是作为计算条件概率的描述性手段。 + +决策树(Decision Tree)这里的应用算法有: + +* 分类和回归树(CART) +* ID3算法(Iterative Dichotomiser 3) +* CHAID(Chi-squared Automatic Interaction Detection +* 随机森林(Random Forest) +* 多元自适应回归样条(MARS) +* 梯度推进机(Gradient Boosting Machine, GBM) + +#### 决策树的优点 + +* 便于理解和解释。树的结构可以可视化出来。 +* 训练需要的数据少。其他机器学习模型通常需要数据规范化,比如构建虚拟变量和移除缺失值,不过请注意,这种模型不支持缺失值。 +* 由于训练决策树的数据点的数量导致了决策树的使用开销呈指数分布(训练树模型的时间复杂度是参与训练数据点的对数值)。 +* 能够处理数值型数据和分类数据。其他的技术通常只能用来专门分析某一种变量类型的数据集。详情请参阅算法。 +* 能够处理多路输出的问题。 +* 使用白盒模型。如果某种给定的情况在该模型中是可以观察的,那么就可以轻易的通过布尔逻辑来解释这种情况。相比之下,在黑盒模型中的结果就是很难说明清 楚地。 +* 可以通过数值统计测试来验证该模型。这对事解释验证该模型的可靠性成为可能。 +* 即使该模型假设的结果与真实模型所提供的数据有些违反,其表现依旧良好。 + +#### 决策树的缺点 + +* 决策树模型容易产生一个过于复杂的模型,这样的模型对数据的泛化性能会很差。这就是所谓的过拟合.一些策略像剪枝、设置叶节点所需的最小样本数或设置数的最大深度是避免出现 该问题最为有效地方法。 +* 决策树可能是不稳定的,因为数据中的微小变化可能会导致完全不同的树生成。这个问题可以通过决策树的集成来得到缓解 +* 在多方面性能最优和简单化概念的要求下,学习一棵最优决策树通常是一个NP难问题。因此,实际的决策树学习算法是基于启发式算法,例如在每个节点进 行局部最优决策的贪心算法。这样的算法不能保证返回全局最优决策树。这个问题可以通过集成学习来训练多棵决策树来缓解,这多棵决策树一般通过对特征和样本有放回的随机采样来生成。 +* 有些概念很难被决策树学习到,因为决策树很难清楚的表述这些概念。例如XOR,奇偶或者复用器的问题。 +* 如果某些类在问题中占主导地位会使得创建的决策树有偏差。因此,建议在拟合前先对数据集进行平衡。 diff --git a/assets/src/DT/DT.0.2.md b/assets/src/DT/DT.0.2.md new file mode 100644 index 00000000..f10558ea --- /dev/null +++ b/assets/src/DT/DT.0.2.md @@ -0,0 +1,55 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + + +#### 分类和回归树(CART) + +分类回归树(Classification And Regression Tree, CART)模型是决策树学习方法的一种,CART既可以用于分类计算,也可以用于回归。 + +不同于C4.5,CART本质是对特征空间进行二元划分(即CART生成的决策树是一棵二叉树),并能够对标量属性(nominal attribute)与连续属性(continuous attribute)进行分裂。 +CART决策树是结构简洁的二叉树,采用一种二分递归分割的技术,将当前的样本集分为两个子样本集,使得生成的每个非叶子的节点都有两个分支。 + +CART算法包括两个过程: +1. 决策树的生成:基于训练数据集生成决策树,生成的决策树要尽量的大; +2. 决策树的剪枝:用验证数据集对以生成的树进行剪枝并选择最优子树,此时用损失函数最小作为剪枝的标准。 + +1.决策树的生成 +决策树的生成就是递归的构建二叉决策树的过程。对回归树用平方误差最小化准则,对分类树用基尼指数最小化原则,进行特征选择,生成二叉树。 + +主要的原理如下:(1)分类树原理:分类树采用基尼指数(Gini index, Gini)选择最优特征,同时决定该特征的最优二值切分点。基尼指数定义为: +

+ +

+ +对于给定样本集合D,其基尼指数的计算为: +

+ +

+如果样本集合D根据特征A是否取某一可能值a被分割成D1和D2两部分,即:,D2=D-D1 +则在特征A的条件下,集合D的基尼指数计算公式为: +

+ +

+基尼指数Gini(D)表示集合D的不确定性,基尼指数Gini(D,A)表示经A=a分割后集合D的不确定性。基尼指数值越大,样本集合的不确定性也就越大。 +(2)回归树原理:回归树用平方误差最小化准则,进行特征选择,生成二叉树。将输入空间划分为M个区域R1,R2,…,Rm,则生成的回归树模型表示为: +

+ +

+其中cm表示单元Rm上的最小误差平方的最优解. + +2、决策树的剪枝 + +CART算法对于决策树剪枝方法,采用代价复杂度模型,通过交叉验证来估计对预测样本集的误分类损失,产生最小交叉验证误分类估计树。 + +CART剪枝算法主要由两步组成:首先从生成算法产生的决策树T0底端开始不断剪枝,直到T0的根节点,形成一个子树序列{T0,T1,… ,Tn};然后通过交叉验证法在独立的验证数据集上对子树序列进行测试,从中选择最优子树。 + +#### 相关应用 + +分类回归树本质上也是一种决策树算法;而决策树分类器具有很好的准确性,已被成功的应用于许多的应用领域的分类,如医学、制造和生产、金融分析、天文学与分子生物学等;具体的包括欺诈监测、针对销售、性能预测、制造和医疗整段。决策树是许多商业规则归纳系统的基础。 + +#### 优缺点 + +优点:可以生成易于理解的规则;计算量相对来说不大;可处理连续和离散字段;最终结果可清晰显示字段的重要性程度。 + +缺点:对连续字段难以预测;处理时间序列数据,前期预处理步骤多;当类别太多,错误可能增加的较快。 diff --git a/assets/src/DT/DT.0.3.md b/assets/src/DT/DT.0.3.md new file mode 100644 index 00000000..64e7dda7 --- /dev/null +++ b/assets/src/DT/DT.0.3.md @@ -0,0 +1,122 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### ID3算法(Iterative Dichotomiser 3) + +ID3算法是决策树的一种,它是基于奥卡姆剃刀原理的,即用尽量用较少的东西做更多的事。ID3算法,即Iterative Dichotomiser3,迭代二叉树三代,是Ross Quinlan发明的一种决策树算法,这个算法的基础就是上面提到的奥卡姆剃刀原理,越是小型的决策树越优于大的决策树,尽管如此,也不总是生成最小的树型结构,而是一个启发式算法。 + +ID3算法的核心思想就是以信息增益来度量属性的选择,选择分裂后信息增益最大的属性进行分裂。 +信息增益是属性选择中的一个重要指标,它定义为一个属性能够为分类系统带来多少信息,带来的信息越多,该属性就越重要。而信息量,就是熵。 +熵定义为信息量的期望值。 + +熵越大,一个变量的不确定性越大,它带来的信息量就越大。 计算信息熵的公式为: +

+ +

+ +其中p为出现c分类时的概率。 + +那么如何计算一个属性的信息增益? 首先我们需要先根据信息熵公式计算出系统的平均熵值H(C),然后根据某个属性计算条件熵: +

+ +

+ +这是指属性X被固定时的条件熵。因为X可能的取值有n种,因此在计算条件熵时需要计算n个值,然后取均值(通过概率计算)。通过将某分类的系统熵减去某个属性的条件熵,从而得到该属性的信息增益: +

+ +

+ +在信息论中一个属性的信息增益越大,表明该属性对样本的熵减少能力越强,也就是说确定这个属性会使系统越稳定有序(熵越小系统越稳定),那么该分区的纯度也就越高。 + +机器学习中,决策树是一个预测模型;他代表的是对象属性与对象值之间的一种映射关系。树中每个节点表示某个对象,而每个分叉路径则代表的某个可能的属性值,而每个叶结点则对应从根节点到该叶节点所经历的路径所表示的对象的值。 + +决策树仅有单一输出,若欲有复数输出,可以建立独立的决策树以处理不同输出。 数据挖掘中决策树是一种经常要用到的技术,可以用于分析数据,同样也可以用来作预测。 从数据产生决策树的机器学习技术叫做决策树学习,就是决策树。 + +通常一个决策树会包含三种类型的节点: + +* 决策节点:通常用矩形框来表示 +* 机会节点:通常用圆圈来表示 +* 终结点:通常用三角形来表示 + + + +#### 应用案例 + +```python +import pandas as pd +from math import log +from anytree import Node, RenderTree +from anytree.dotexport import RenderTreeGraph + +def create_decision_tree_id3(df, y_col): + # 计算H(C) + def h_value(): + h = 0 + for v in df.groupby(y_col).size().div(len(df)): + h += -v * log(v, 2) + + return h + + # 计算某一个属性的信息增益 + def get_info_gain_byc(column, df, y_col): + # 计算p(column) + probs = df.groupby(column).size().div(len(df)) + v = 0 + for index1, v1 in probs.iteritems(): + tmp_df = df[df[column] == index1] + tmp_probs = tmp_df.groupby(y_col).size().div(len(tmp_df)) + tmp_v = 0 + for v2 in tmp_probs: + # 计算H(C|X=xi) + tmp_v += -v2 * log(v2, 2) + # 计算H(y_col|column) + v += v1 * tmp_v + return v + + # 获取拥有最大信息增益的属性 + def get_max_info_gain(df, y_col): + d = {} + h = h_value() + for c in filter(lambda c: c != y_col, df.columns): + # 计算H(y_col) - H(y_col|column) + d[c] = h - get_info_gain_byc(c, df, y_col) + + return max(d, key=d.get) + + # 生成决策树 + def train_decision_tree(node, df, y_col): + c = get_max_info_gain(df, y_col) + for v in pd.unique(df[c]): + gb = df[df[c] == v].groupby(y_col) + curr_node = Node('%s-%s' % (c, v), parent=node) + # 如果属性没有用完 + if len(df.columns) > 2: + # 如果分区纯度是100%,则生成类别叶子节点 + if len(gb) == 1: + Node(df[df[c] == v].groupby(c)[y_col].first().iloc[0], parent=curr_node) + else: + # 如果分区不纯则继续递归 + train_decision_tree(curr_node, df[df[c] == v].drop(c, axis=1), y_col) + # 如果属性用完,则选择数量最多的类别实例作为类别叶子结点 + else: + Node(df[df[c] == v].groupby(y_col).size().idxmax(), parent=curr_node) + + root_node = Node('root') + train_decision_tree(root_node, df, y_col) + return root_node + +df = pd.read_csv('~/allele.csv') +root_node = create_decision_tree_id3(df, 'buys_computer') +for pre, fill, node in RenderTree(root_node): + print("%s%s" % (pre, node.name)) + +RenderTreeGraph(root_node).to_picture("decision_tree_id3.png") + +``` + +#### 优缺点 + +优点:决策树ID3算法易于理解,能处理数据型的也能处理常规型的数据,还可以在相对较短的时间内能够对大型的数据集做出可行且较好的结果。 + +缺点:决策树ID3算法比较偏向于选择属性值多的类别。 diff --git a/assets/src/DT/DT.0.4.md b/assets/src/DT/DT.0.4.md new file mode 100644 index 00000000..3b8fc66e --- /dev/null +++ b/assets/src/DT/DT.0.4.md @@ -0,0 +1,27 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 卡方自动交互检测算法 CHAID(Chi-squared Automatic Interaction Detection) + +卡方自动交互检测法(chi-squared automatic interaction detector, CHAID)最早由Kass于1980年提出,是一个用来发现变量之间关系的工具,是一种基于调整后的显着性检验(邦费罗尼检验)决策树技术。 + +其核心思想是:根据给定的反应变量和解释变量对样本进行最优分割,按照卡方检验的显著性进行多元列联表的自动判断分组。利用卡方自动交互检测法可以快速、有效地挖掘出主要的影响因素,它不仅可以处理非线性和高度相关的数据,而且可以将缺失值考虑在内,能克服传统的参数检验方法在这些方面的限制。 + +在实践中,CHAID经常使用在直销的背景下,选择消费者群体,并预测他们的反应,一些变量如何影响其他变量,而其他早期应用是在医学和精神病学的研究领域。 + +CHAID分析构建了一个预测模型,或树,以帮助确定给定因变量,变量如何最好地合来解释结果。CHAID分析,名义,有序和连续数据可以使用,在连续预测类别被分成大致相等的若干观测。CHAID对每个分类预测创建了交叉表,直到达到最好的结果,无法继续分类为止。在CHAID技术中,我们可以直观地看到在树的分割变量和相关因子之间的关系。决策树或分类树的展开,始于确定作为根节点的目标变量或因变量。 CHAID分析将目标变量分割成两个或两个以上的类被称为根节点,或者父节点,然后使用统计算法将节点分为子节点。不同于回归分析,CHAID技术并不要求数据是正态分布. + +CHAID的优势是它的结果是非常直观的易于理解的。由于默认情况下CHAID采用多路分割,需要相当大的样本量,来有效地开展工作,而小样本组受访者可以迅速分为太小了的组,而无法可靠的分析。 + +CHAID决策树的构成包括: +* 根节点:根节点包含因变量或目标变量。例如,CHAID使用于,银行根据年龄,收入,信用卡等,来预测信用卡风险。在这个例子中,信用卡风险是目标变量,其余变量是预测变量。 +* 父节点:该算法将目标变量分割成两个或多个分类。这些分类被称为父节点或者初始节点。在银行的例子中,父节点是高,中,低三个分类。 +* 子节点:CHAID分析树中独立变量分类低于父节点的分类被称为子节点。 +* 终端节点:CHAID分析树最后一个分类被称为终端节点。 CHAID分析树中,主要的影响变量排在前面,次要的排在后面。因此,它被称为终端节点。 + +#### CHAID的优点 +1. 可产生多分枝的决策树 +2. 目标变量可以定距或定类 +3. 从统计显著性角度确定分支变量和分割值,进而优化树的分枝过程 +4. 建立在因果关系探讨中,依据目标变量实现对输入变量众多水平划分 diff --git a/assets/src/DT/DT.0.5.md b/assets/src/DT/DT.0.5.md new file mode 100644 index 00000000..f94d0a38 --- /dev/null +++ b/assets/src/DT/DT.0.5.md @@ -0,0 +1,144 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + + +#### 随机森林(Random Forest) + + +随机森林是一个包含多个决策树的分类器,并且其输出的类别是由个别树输出的类别的众数而定。 Leo Breiman和Adele Cutler发展出推论出随机森林的算法。而"Random Forests"是他们的商标。这个术语是1995年由贝尔实验室的Tin Kam Ho所提出的随机决策森林(random decision forests)而来的。这个方法则是结合Breimans的"Bootstrap aggregating"想法和Ho的"random subspace method" 以建造决策树的集合。 + +随机森林通过集成学习的思想将多棵树集成的一种算法,它的基本单元是决策树,而它的本质属于机器学习的一大分支——集成学习(Ensemble Learning)方法。随机森林的名称中有两个关键词,一个是“随机”,一个就是"森林"。"森林"我们很好理解,一棵叫做树,那么成百上千棵就可以叫做森林了,这样的比喻还是很贴切的,其实这也是随机森林的主要思想--集成思想的体现。其实从直观角度来解释,每棵决策树都是一个分类器(假设现在针对的是分类问题),那么对于一个输入样本,N棵树会有N个分类结果。而随机森林集成了所有的分类投票结果,将投票次数最多的类别指定为最终的输出,这就是一种最简单的 Bagging 思想。 +

+ +

+ + +随机森林是一种很灵活实用的方法,它有如下几个特点: +* 在当前所有算法中,具有极好的准确率; +* 能够有效地运行在大数据集上; +* 能够处理具有高维特征的输入样本,而且不需要降维; +* 能够评估各个特征在分类问题上的重要性; +* 在生成过程中,能够获取到内部生成误差的一种无偏估计; +* 对于缺省值问题也能够获得很好得结果; + + +#### 应用案例 + +```python +import numpy as np +import matplotlib.pyplot as plt +from matplotlib.colors import ListedColormap +from sklearn.cross_validation import train_test_split +from sklearn.preprocessing import StandardScaler +from sklearn.datasets import make_moons, make_circles, make_classification +from sklearn.neighbors import KNeighborsClassifier +from sklearn.svm import SVC +from sklearn.tree import DecisionTreeClassifier +from sklearn.ensemble import RandomForestClassifier, AdaBoostClassifier +from sklearn.naive_bayes import GaussianNB +from sklearn.lda import LDA +from sklearn.qda import QDA + +h = .02 # step size in the mesh + +names = ["Nearest Neighbors", "Linear SVM", "RBF SVM", "Decision Tree", + "Random Forest", "AdaBoost", "Naive Bayes", "LDA", "QDA"] +classifiers = [ + KNeighborsClassifier(3), + SVC(kernel="linear", C=0.025), + SVC(gamma=2, C=1), + DecisionTreeClassifier(max_depth=5), + RandomForestClassifier(max_depth=5, n_estimators=10, max_features=1), + AdaBoostClassifier(), + GaussianNB(), + LDA(), + QDA()] + +X, y = make_classification(n_features=2, n_redundant=0, n_informative=2, + random_state=1, n_clusters_per_class=1) +rng = np.random.RandomState(2) +X += 2 * rng.uniform(size=X.shape) +linearly_separable = (X, y) + +datasets = [make_moons(noise=0.3, random_state=0), + make_circles(noise=0.2, factor=0.5, random_state=1), + linearly_separable + ] + +figure = plt.figure(figsize=(27, 9)) +i = 1 +# iterate over datasets +for ds in datasets: + # preprocess dataset, split into training and test part + X, y = ds + X = StandardScaler().fit_transform(X) + X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.4) + + x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5 + y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5 + xx, yy = np.meshgrid(np.arange(x_min, x_max, h), + np.arange(y_min, y_max, h)) + + # just plot the dataset first + cm = plt.cm.RdBu + cm_bright = ListedColormap(['#FF0000', '#0000FF']) + ax = plt.subplot(len(datasets), len(classifiers) + 1, i) + # Plot the training points + ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright) + # and testing points + ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright, alpha=0.6) + ax.set_xlim(xx.min(), xx.max()) + ax.set_ylim(yy.min(), yy.max()) + ax.set_xticks(()) + ax.set_yticks(()) + i += 1 + + # iterate over classifiers + for name, clf in zip(names, classifiers): + ax = plt.subplot(len(datasets), len(classifiers) + 1, i) + clf.fit(X_train, y_train) + score = clf.score(X_test, y_test) + + # Plot the decision boundary. For that, we will assign a color to each + # point in the mesh [x_min, m_max]x[y_min, y_max]. + if hasattr(clf, "decision_function"): + Z = clf.decision_function(np.c_[xx.ravel(), yy.ravel()]) + else: + Z = clf.predict_proba(np.c_[xx.ravel(), yy.ravel()])[:, 1] + + # Put the result into a color plot + Z = Z.reshape(xx.shape) + ax.contourf(xx, yy, Z, cmap=cm, alpha=.8) + + # Plot also the training points + ax.scatter(X_train[:, 0], X_train[:, 1], c=y_train, cmap=cm_bright) + # and testing points + ax.scatter(X_test[:, 0], X_test[:, 1], c=y_test, cmap=cm_bright, + alpha=0.6) + + ax.set_xlim(xx.min(), xx.max()) + ax.set_ylim(yy.min(), yy.max()) + ax.set_xticks(()) + ax.set_yticks(()) + ax.set_title(name) + ax.text(xx.max() - .3, yy.min() + .3, ('%.2f' % score).lstrip('0'), + size=15, horizontalalignment='right') + i += 1 + +figure.subplots_adjust(left=.02, right=.98) +plt.show() + +``` + +#### 优点 +* 随机森林对于很多种数据,它可以产生高准确度的分类器。 +* 随机森林可以处理大量的输入变量。 +* 随机森林可以在决定类别时,评估变量的重要性。 +* 在建造森林时,它可以在内部对于一般化后的误差产生不偏差的估计。 +* 随机森林包含一个好方法可以估计丢失的数据,并且,如果有很大一部分的数据丢失,仍可以维持准确度。 +* 它提供一个实验方法,可以去侦测variable interactions。 +* 对于不平衡的分类数据集来说,它可以平衡误差。 +* 它计算各例中的亲近度,对于数据挖掘、侦测离群点(outlier)和将数据可视化非常有用。 +* 它可被延伸应用在未标记的数据上,这类数据通常是使用非监督式聚类。也可侦测偏离者和观看数据。 +* 学习过程是很快速的。 diff --git a/assets/src/DT/DT.0.6.md b/assets/src/DT/DT.0.6.md new file mode 100644 index 00000000..1f814a27 --- /dev/null +++ b/assets/src/DT/DT.0.6.md @@ -0,0 +1,12 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + + +#### 多元自适应回归样条(MARS) +多元自适应回归样条(Multivariate Adaptive Regression Splines,MARS)是由美国的统计学家Jerome Friedman于1991年提出的一种数据分析方法。 该方法以样条函数的张量积作为基函数,分为前向过程、后向剪枝过程与模型选取三个步骤。其优点在于能够处理数据量大、维度高的数据,而且计算快捷、模型精确。在一般回归分析理论和样条理论的基础上,系统地研究了MARS的建模过程,提出引入Bernstein基函数建模的思想,并针对冶金工业领域一类数据分析其成分优化问题,应用该方法进行建模和预测。 + +在前向过程中,通过自适应的选取节点对数据进行分割,每选取一个节点就生成两个新的基函数,前向过程结束后生成一个过拟合的模型。后向剪枝过程中在保证模型准确度的前提下,删除过拟合模型中对模型贡献度小的基函数,最后选取一个最优的模型作为回归模型。 研究过程中对采集的原始数据进行了消除负差、剔除异常数据、数据标准化等预处理工作,选取精华样本,分别建立了线性模型、非线性模型、神经网络模型等,并与MARS方法做比较。得到如下结论:由于模型的限制,线性回归模型精度较低,与实际经验不符; 神经网络对部分元素的描述优于线性回归模型,但不能得出相应的显式表达式,同时线性回归与神经网络都未能考虑变量间的交互作用;MARS模型对问题的描述比较符合实际经验,同时能够反映元素间的交互作用,能够对两个变量做可视化处理,并能够给出显式表达式。 论文以数据科学为背景,属于问题驱动的应用数学研究,不仅对多元自适应回归方法进行了理论探索,也为工业领域的数据分析与优化提供了理论依据。 + + +MARS是回归的自适应过程,非常适合高维问题(比如,存在大量的输入)。可以从两个角度来理解它,首先,它可以看成是逐步线性回归的推广,其次,也可以看成是为了提高CART在回归中的效果而进行的改进。我们从第一种观点引入MARS,接着与CART联系起来。 diff --git a/assets/src/DT/DT.0.7.md b/assets/src/DT/DT.0.7.md new file mode 100644 index 00000000..bf60c464 --- /dev/null +++ b/assets/src/DT/DT.0.7.md @@ -0,0 +1,49 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + + +#### 梯度推进机(Gradient Boosting Machine,GBM) + +梯度推进理论核心是梯度推移理论。它认为,不同国家或不同地区间存在着产业梯度和经济梯度,存在梯度地区技术经济势差,就存在着技术经济推移的动力,就会形成生产力的空间推移。梯度推进是一种用于回归和分类问题的机器学习技术,该技术以弱预测模型(通常为决策树)的集合的形式产生预测模型。它像其他增强方法那样以阶段式方式构建模型,并且通过允许优化任意可微损失函数来推广它们。 + +梯度提升通常用于作为基础学习者的固定大小的决策树(特别是CART树)。对于这种特殊情况,弗里德曼提出了对梯度提升方法的修改,该方法可以提高每个基础学习者的适应质量。 + +梯度推进理论梯度提升将弱“学习者”以迭代的方式组合成一个强大的学习者。在最小二乘回归设置中解释最容易,其目标是“教”一个模型F预测表单的值通过最小化均方误差,在输出变量的一些实际值的训练集上进行平均y。 + +在每个阶段 m,,梯度提升,可以假定存在一些不完善的模型(首先,可以使用一个非常弱的模型,它可以预测训练集中的平均值y).梯度提升算法进一步改进通过构建一个新的模型来增加一个估计器h来提供一个更好的模型:.寻找h梯度增强解决方案从观察到完美的h意味着开始 +

+ +

+ +或者等同地, +

+ +

+ +因此,梯度升压将适合h到残余。就像其他增强型变体一样,学会纠正其前任 .把这个想法推广到除了平方误差之外的损失函数 - 以及分类和排序问题 - 从观察残差开始对于给定的模型是平方误差损失函数的负梯度(相对于F(x)) 。所以,梯度增强是一种梯度下降算法; 并推广它需要“插入”不同的损失及其梯度。 + + +#### 梯度提升 + +梯度提升通常用于作为基础学习者的固定大小的决策树(特别是CART树)。对于这种特殊情况,弗里德曼提出了对梯度提升方法的修改,该方法可以提高每个基础学习者的适应质量。 + +第m步中的通用梯度提升将适合决策树伪残差。让是它的叶子的数量。树将输入空间分成不相交的地区,...,并预测每个地区的恒定值。使用指标符号,输出对于输入x可以写成总和: +

+ +

+ +哪里是该地区预测的价值。 + +然后是系数乘以某个值,使用线搜索选择以便最小化损失函数,并且模型更新如下: +

+ +

+ + +弗里德曼提出修改这个算法,以便它选择一个单独的最优值对于每个树的区域,而不是一个 +为整棵树。他称修改后的算法为“TreeBoost”。系数从树形拟合过程可以简单地被丢弃并且模型更新规则变为: +

+ +

+ diff --git a/assets/src/DT/DT.md b/assets/src/DT/DT.md new file mode 100644 index 00000000..4aa52504 --- /dev/null +++ b/assets/src/DT/DT.md @@ -0,0 +1,87 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +机器学习是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。主要研究计算机怎样模拟或实现人类的学习行为,以获取新的知识和技能,重新组织已有的知识结构,不断的改善自身的性能。 + +机器学习理论主要是设计和分析一些让计算机可以自动“学习”的算法。这些算法是一类能从数据中自动分析获得规律,并利用规律对未知数据进行预测的算法。简而言之,机器学习主要以数据为基础,通过大数据本身,运用计算机自我学习来寻找数据本身的规律,而这是机器学习与统计分析的基本区别。 + +机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 + +(1)监督学习:从给定的训练数据集中学习出一个函数,当新的数据输入时,可以根据函数预测相应的结果。监督学习的训练集要求是包括输入和输出,也就是特征和目标。训练集中的目标是有标注的。如今机器学习已固有的监督学习算法有可以进行分类的,例如贝叶斯分类,SVM,ID3,C4.5以及分类决策树,以及现在最火热的人工神经网络,例如BP神经网络,RBF神经网络,Hopfield神经网络、深度信念网络和卷积神经网络等。人工神经网络是模拟人大脑的思考方式来进行分析,在人工神经网络中有显层,隐层以及输出层,而每一层都会有神经元,神经元的状态或开启或关闭,这取决于大数据。同样监督机器学习算法也可以作回归,最常用便是逻辑回归。 +(2)监督学习:与有监督学习相比,无监督学习的训练集的类标号是未知的,并且要学习的类的个数或集合可能事先不知道。常见的无监督学习算法包括聚类和关联,例如K均值法、Apriori算法。 +(3)半监督学习:介于监督学习和无监督学习之间,例如EM算法. + +如今的机器学习领域主要的研究工作在三个方面进行:1.面向任务的研究,研究和分析改进一组预定任务的执行性能的学习系统;2.认知模型,研究人类学习过程并进行计算模拟;3.理论的分析,从理论的层面探索可能的算法和独立的应用领域算法. + +#### 决策树 + +决策树(Decision Tree)是应用于分类的一种树结构。其中的每个内部节点(internal node)代表对某个属性的一次测试判别,一个分枝代表一个测试结果,叶子(leaf)代表某个类(class)或者类的分布(class distribution)。最顶层的节点是根结点。可以将决策树理解为一个if-then规则的集合,由决策树的根节点到叶节点的每一条路径构建一条规则。 + +

+ +

+ +决策树学习算法包含特征选择、决策树的生成和决策树的修剪过程,构造决策树的方法是采用自上而下的递归构造。 + +构造的思路是,如果训练样本集合中的所有样本是同类的,则将之作为叶子节点,节点内容即是该类别标记。否则,根据某种策略(如信息熵或GINI系数)选择一个属性,按照属性的各个取值,把样本集合划分为若干子集合,使得每个子集上的所有样本在该属性上具有同样的属性值,然后再依次递归处理各个子集。这种思路实际上就是“分而治之”的道理。 + +信息增益算法: +设D是s个样本的集合,具有n个不同的类别,设是类的样本数,那么对给定的样本分类所需要的经验熵为: +

+ +

+ + +其中为任意样本属于类的概率,并用估计。 + + +设属性A具有v个不同的值,可以用A属性将集合D划分为v个子集,其中包含D中属性A上取值的一些样本。令是子集中类的样本数。根据A划分成子集的经验熵为: + +

+ +

+ +当熵值越小,子集划分的纯度越高。 + +在属性A上分枝将获得的信息增益为: + +

+ +

+ +通过比较各特征的信息增益值,并比较它们的大小,选择信息增益最大的特征。 + +决策树的剪枝 + +剪枝是决策树停止分支的方法之一,剪枝有分预先剪枝和后剪枝两种。预先剪枝是在树的生长过程中设定一个指标,当达到该指标时就停止生长,这样做容易产生“视界局限”,就是一旦停止分支,使得节点N成为叶节点,就断绝了其后继节点进行“好”的分支操作的任何可能性。 + +后剪枝中树首先要充分生长,直到叶节点都有最小的不纯度值为止,因而可以克服“视界局限”。然后对所有相邻的成对叶节点考虑是否消去它们,如果消去能引起令人满意的不纯度增长,那么执行消去,并令它们的公共父节点成为新的叶节点。这种“合并”叶节点的做法和节点分支的过程恰好相反,经过剪枝后叶节点常常会分布在很宽的层次上,树也变得非平衡。后剪枝技术的优点是克服了“视界局限”效应,而且无需保留部分样本用于交叉验证,所以可以充分利用全部训练集的信息。但后剪枝的计算量代价比预剪枝方法大得多,特别是在大样本集中,不过对于小样本的情况,后剪枝方法还是优于预先剪枝方法。 + + +#### 应用领域 +决策树经常在运筹学中使用,特别是在决策分析中,它帮助确定一个能最可能达到目标的策略。如果在实际中,决策不得不在没有完备知识的情况下被在线采用,一个决策树应该平行概率模型作为最佳的选择模型或在线选择模型算法。决策树的另一个使用是作为计算条件概率的描述性手段。 + +#### 优缺点 + +优点: + +1. 决策树生成的模型很直观、简单、易懂; + +2. 决策树对数据的分布没有特别严格的要求; + +3. 对缺失值很宽容,几乎可以不做处理; + +4. 不容易受离群值影响; + +5. 决策树可以为其他模型算法挑选自变量。 + +缺点: + +1. 决策树最大的缺点是其使用了贪心算法,贪心算法局限于其寻找的不是全局最优解。 + +2. 决策树处理不了连续变量; + +3. 决策树缺乏丰富的监测指标和评价方法; + +4. 当某些自变量的类别数量比较多或者是区间变量时,决策树会产生过拟合的危险。 diff --git a/assets/src/EL/EL.0.1.md b/assets/src/EL/EL.0.1.md new file mode 100644 index 00000000..3cbe8ee5 --- /dev/null +++ b/assets/src/EL/EL.0.1.md @@ -0,0 +1,23 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 集成算法(Ensemble Learning) + +集成学习(Ensemble Learning)是使用一序列学习器进行学习,并使用某种规则把各个学习结果进行整合从而获得比单个学习器更好的学习效果的一种机器学习方法。集成学习中多个学习器被称为“弱学习器”,如果这些弱学习器都是一个种类的,则被称为是同质的;若这些弱学习器不全是一个种类的,则被称为异质的。一般情况下,集成学习中的多个学习器都是同质的“弱学习器” + +集成学习在各个规模的数据集上都有很好的策略。 + +* 数据集大:划分成多个小数据集,学习多个模型进行组合 +* 数据集小:利用Bootstrap方法进行抽样,得到多个数据集,分别训练多个模型再进行组合 + +集成算法(Ensemble Learning)主要包括: + +* Boosting +* Bagging +* AdaBoost +* 堆叠泛化(混合) +* GBM 算法 +* GBRT 算法 +* 随机森林 + diff --git a/assets/src/EL/EL.0.2.md b/assets/src/EL/EL.0.2.md new file mode 100644 index 00000000..b25fa577 --- /dev/null +++ b/assets/src/EL/EL.0.2.md @@ -0,0 +1,20 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### Boosting + +Bagging是Bootstrap aggregating的简写。这里先说一下`bootstrap`,`bootstrap` 也被称为自助法,它是一种有放回的抽样方法,目的为了得到统计量的分布以及置信区间。 + +Baggging 和 Boosting都是模型融合的方法,可以将弱分类器融合之后形成一个强分类器,而且融合之后的效果会比最好的弱分类器更好。 + +Bagging即套袋法,其算法过程如下: + +从原始样本集中抽取训练集。每轮从原始样本集中使用Bootstraping的方法抽取n个训练样本(在训练集中,有些样本可能被多次抽取到,而有些样本可能一次都没有被抽中)。共进行k轮抽取,得到k个训练集。(k个训练集之间是相互独立的) + +* 每次使用一个训练集得到一个模型,k个训练集共得到k个模型。(注:这里并没有具体的分类算法或回归方法,我们可以根据具体问题采用不同的分类或回归方法,如决策树、感知器等) + +* 对分类问题:将上步得到的k个模型采用投票的方式得到分类结果;对回归问题,计算上述模型的均值作为最后的结果。(所有模型的重要性相同) + + +Boosting这其实思想相当的简单,大概是,对一份数据,建立M个模型(比如分类),一般这种模型比较简单,称为弱分类器(weak learner)每次分类都将上一次分错的数据权重提高一点再进行分类,这样最终得到的分类器在测试数据与训练数据上都可以得到比较好的成绩。 diff --git a/assets/src/EL/EL.0.3.md b/assets/src/EL/EL.0.3.md new file mode 100644 index 00000000..758daf19 --- /dev/null +++ b/assets/src/EL/EL.0.3.md @@ -0,0 +1,4 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + diff --git a/assets/src/EL/EL.0.4.md b/assets/src/EL/EL.0.4.md new file mode 100644 index 00000000..758daf19 --- /dev/null +++ b/assets/src/EL/EL.0.4.md @@ -0,0 +1,4 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + diff --git a/assets/src/HPD/HPD.md b/assets/src/HPD/HPD.md new file mode 100644 index 00000000..5df2bb20 --- /dev/null +++ b/assets/src/HPD/HPD.md @@ -0,0 +1,96 @@ +### Deeplearning Algorithms tutorial + +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! + +AI的开发离不开算法那我们就接下来开始学习算法吧! + +所谓的人工神经网络 (Artificial Neural Network,ANN)简称神经网络(NN),是基于生物学中神经网络的基本原理,在理解和抽象了人脑结构和外界刺激响应机制后,以网络拓扑知识为理论基础,模拟人脑的神经系统对复杂信息的处理机制的一种数学模型,根植于神经科学、数学、思维科学、人工智能、统计学、物理学、计算机科学以及工程科学的一门技术,通常用于解决分类和回归问题。具有并行分布的处理能力、高容错性、智能化和自学习等能力的特征,本质上是一个有大量简单元件相互连接而成的复杂网络,具有高度的非线性,能够进行复杂的逻辑操作和非线性关系实现的系统。 + +神经网络由大量的节点(或称神经元)之间相互联接构成,每个节点代表一种特定的输出函数,称为激活函数(activation function);每两个节点间的连接都代表一个对于通过该连接信号的加权值,称之为权重(weight),神经网络就是通过这种方式来模拟人类的记忆。网络的输出则取决于网络的结构、网络的连接方式、权重和激活函数。而网络自身通常都是对自然界某种算法或者函数的逼近,也可能是对一种逻辑策略的表达,是对传统逻辑学演算的进一步延伸。 + +

+ +

+人工神经网络中,神经元处理单元可表示不同的对象,例如特征、字母、概念,或者一些有意义的抽象模式。网络中处理单元的类型分为三类:输入单元、输出单元和隐单元。输入单元接受外部世界的信号与数据;输出单元实现系统处理结果的输出;隐单元是处在输入和输出单元之间,不能由系统外部观察的单元。神经元间的连接权值反映了单元间的连接强度,信息的表示和处理体现在网络处理单元的连接关系中。 + + +算法发展的背景 + +20世纪40年代,人们开始对神经网络研究。 + +1943 年,美国心理学家麦克洛奇(Mcculloch)和数学家皮兹(Pitts)提出了M-P模型,此模型比较简单,但是意义重大。在模型中,通过把神经元看作功能逻辑器件来实现算法,从此开创了神经网络模型的理论研究。 + +1949心理学家赫布(Hebb)提出Hebb法则,为构造有学习功能的神经网络模型奠定了基础。 + +1957 年,罗森勃拉特(Rosenblatt)以M-P 模型为基础,提出了感知器(Perceptron)模型; + +1959年,美国著名工程师威德罗(B.Widrow)和霍夫(M.Hoff)等人提出ADALINE网络模型,ADALINE网络模型是一种连续取值的自适应线性神经元网络模型,可以用于自适应系统。 + +1972年,芬兰的KohonenT.教授,提出了自组织神经网络SOM(Self-Organizing feature map)。 + +1976年,美国Grossberg教授提出了著名的自适应共振理论ART(Adaptive Resonance Theory),其学习过程具有自组织和自稳定的特征。 + +1982年,美国物理学家霍普菲尔德(Hopfield)提出了一种离散神经网络,即离散Hopfield网络,从而有力地推动了神经网络的研究; + +1984年,Hinton与年轻学者Sejnowski等合作提出了Boltzmann机模型; + +1986年,儒默哈特(D.E.Ru melhart)等人在多层神经网络模型的基础上,提出了多层神经网络权值修正的反向传播学习算法----BP算法(Error Back-Propagation); + +1988年,Chua和Yang提出了细胞神经网络(CNN)模型; + +1994年,廖晓昕关于细胞神经网络的数学理论与基础的提出,带来了这个领域新的进展。通过拓广神经网络的激活函数类,给出了更一般的时滞细胞神经网络(DCNN)、Hopfield神经网络(HNN)、双向联想记忆网络(BAM)模型; + +#### Hopfield神经网络 + +Hopfield提出了连续和离散的Hopfield神经网络模型,并采用全互联型神经网络尝试对非多项式复杂度的旅行商问题(Travelling Salesman Problem,TSP)进行了求解,促进神经网络的研究再次进入了蓬勃发展的时期。 + +Hopfield强调工程实践的重要性,他利用电阻、电容和运算放大器等元件组成的模拟电路实现了对网络神经元的描述,把最优化问题的目标函数转换成Hopfield神经网络的能量函数,通过网络能量函数最小化来寻找对应问题的最优解.Hopfield网络是一种循环神经网络,从输出到输入有反馈连接,典型的Hopfield神经网络模型如图所示. +

+ +

+在图中每组运算放大器及其相关的电阻、电容组成的网络代表一个神经元。每个神经元有两组输入,一组是恒定的外部电流,另一组是来自其他运算放大器输出的正向或反向的反馈连接。假设第i个神经元的内部膜电位为Ui(i=1,2,…,n),细胞膜的输入电容和传递电阻分别为Ci和Ri,神经元的输出电位为Vi,外部输入电流为Ii,并用电阻Rij(i,j=1,2,…,n)来模拟第i个和第j个神经元之间的突触特性。由基尔霍夫电流定律(Kirchhoff’s Cureent Law ,KCL)可知,放大器输入节点处的流入电流和流出电流保持平衡,亦即有下式成立: +

+ +

+同时,每一个运算放大器模拟了神经元输入和输出之间的非线性特性,即有 + +

+ +

+其中,fi代表了第i个神经元的传递函数,并定义W=Rij-1 (i,j=1,2,…,n)为网络的权系数矩阵.为证明连续型网络的稳定性,Hopfield定义了如下的能量函数: +

+ +

+ +其中,f-1为神经元传递函数的反函数.经过推导后得出以下两点结论:一是对于具有单调递增传递函数且对称权系数矩阵的网络来说,其能量会随着时间的变化而趋于稳定;二是当且仅当网络中所有神经元的输出不再随时间变化时,则可以认为网络的能量保持不变。在将网络用于求解诸如旅行商的组合优化问题时,Hopfield将优化的目标函数转化为网络的能量函数,对应地将待求解问题的变量用网络中神经元的状态来表示。由这样的表示方式可知当网络的能量衰减到稳定值时,问题的最优解也随之求出。 + +Hopfield网络按网络输入和输出的数字形式不同可分为离散型和连续型两种网络,即:离散型Hopfield神经网络----DHNN(Discrete Hopfield Neural Network);连续型Hopfield神经网络----CHNN(ContinuesHopfield Neural Network)。 + +DHNN结构:它是一种单层全反馈网络,共有n个神经元。每个神经元都通过连接权接收所有其它神经元输出反馈来的信息,其目的是为了让任一神经元的输出能接受所有神经元输出的控制,从而使各神经元能相互制约。 + +DHNN的设计原则:吸引子的分布是由网络的权值(包括阀值)决定的,设计吸引子的核心就是如何设计一组合适的权值。为了使所设计的权值满足要求,权值矩阵应符合以下要求: + +(1)为保证异步方式工作时网络收敛,W应为对称阵; + +(2)为保证同步方式工作时网络收敛,W应为非负定对称阵; + +(3)保证给定的样本是网络的吸引子,并且要有一定的吸引域。 + +具体设计时,可以采用不同的方法: + +(1)联立方程法; + +(2)外积和法。 + +CHNN:在连续型Hopfield神经网络中,所有神经元都随时间t并行更新,网络状态随时间连续改变。 + +#### 应用领域 +Hopfield是反馈归神经网络,主要应用于联想记忆、聚类以及优化计算等方面。 + +#### 优缺点 + +Hopfield网络是一种非线性的动力网络,可通过反复的网络动态迭代来求解问题,这是符号逻辑方法所不具有的特性。在求解某些问题时,其求解问题的方法与人类求解问题的方法很相似,虽然所求得的解不是最佳解,但其求解速度快,更符合人们日常解决问题的策略。 + +Hopfield神经网络的提出就是与其实际应用密切相关。具有联系记忆的功能,具体为: + +联想记忆:输入--输出模式的各元素之间,并不存在一对一的映射关系,输入--输出模式的维数也不要求相同;联想记忆时,只给出输入模式部分信息,就能联想出完整的输出模式。即具有容错性。 diff --git a/assets/src/KBO/KBO.0.1.md b/assets/src/KBO/KBO.0.1.md new file mode 100644 index 00000000..dcad0455 --- /dev/null +++ b/assets/src/KBO/KBO.0.1.md @@ -0,0 +1,25 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 基于核的算法 + +支持向量机通过某非线性变换 φ( x) ,将输入空间映射到高维特征空间。特征空间的维数可能非常高。如果支持向量机的求解只用到内积运算,而在低维输入空间又存在某个函数 K(x, x′) ,它恰好等于在高维空间中这个内积,即K( x, x′) =<φ( x) ⋅φ( x′) > 。那么支持向量机就不用计算复杂的非线性变换,而由这个函数 K(x, x′) 直接得到非线性变换的内积,使大大简化了计算。这样的函数 K(x, x′) 称为核函数。 + +早在1964年Aizermann等在势函数方法的研究中就将该技术引入到机器学习领域,但是直到1992年Vapnik等利用该技术成功地将线性SVMs推广到非线性SVMs时其潜力才得以充分挖掘。而核函数的理论则更为古老,Mercer定理可以追溯到1909年,再生核希尔伯特空间(ReproducingKernel Hilbert Space, RKHS)研究是在20世纪40年代开始的。 + +核函数包括线性核函数、多项式核函数、高斯核函数等,其中高斯核函数最常用,可以将数据映射到无穷维,也叫做径向基函数(Radial Basis Function 简称 RBF),是某种沿径向对称的标量函数。通常定义为空间中任一点x到某一中心xc之间欧氏距离的单调函数 ,可记作 k(||x-xc||), 其作用往往是局部的,即当x远离xc时函数取值很小。 + + 根据模式识别理论,低维空间线性不可分的模式通过非线性映射到高维特征空间则可能实现线性可分,但是如果直接采用这种技术在高维空间进行分类或回归,则存在确定非线性映射函数的形式和参数、特征空间维数等问题,而最大的障碍则是在高维特征空间运算时存在的“维数灾难”。采用核函数技术可以有效地解决这样问题。 + + +基于核里的应用算法有: +* 支持向量机(SVM) +* 径向基函数(Radial Basis Function ,RBF) +* 线性判别分析(Linear Discriminate Analysis ,LDA) + +核函数方法的特点: +* 核函数的引入避免了“维数灾难”,大大减小了计算量。而输入空间的维数n对核函数矩阵无影响,因此,核函数方法可以有效处理高维输入。 +* 无需知道非线性变换函数的形式和参数。 +* 核函数的形式和参数的变化会隐式地改变从输入空间到特征空间的映射,进而对特征空间的性质产生影响,最终改变各种核函数方法的性能。 +* 核函数方法可以和不同的算法相结合,形成多种不同的基于核函数技术的方法,且这两部分的设计可以单独进行,并可以为不同的应用选择不同的核函数和算法。 diff --git a/assets/src/KBO/KBO.0.2.md b/assets/src/KBO/KBO.0.2.md new file mode 100644 index 00000000..577aa70f --- /dev/null +++ b/assets/src/KBO/KBO.0.2.md @@ -0,0 +1,324 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 支持向量机(SVM) + +支持向量机(Support Vector Machine,SVM)是Corinna Cortes和Vapnik在1995年首先提出的,是一种监督式学习的方法,可广泛地应用于统计分类以及回归分析。支持向量机属于一般化线性分类器,这族分类器的特点是他们能够同时最小化经验误差与最大化几何边缘区,因此支持向量机也被称为最大边缘区分类器。 + +在机器学习中,支持向量机(SVM,还支持矢量网络)是与相关的学习算法有关的监督学习模型,可以分析数据,识别模式,用于分类和回归分析。 +支持向量机方法是建立在统计学习理论的VC维理论和结构风险最小原理基础上的,根据有限的样本信息在模型的复杂性(即对特定训练样本的学习精度)和学习能力(即无错误地识别任意样本的能力)之间寻求最佳折中,以求获得最好的推广能力 。 + + +在机器学习中,支持向量机(SVM,还支持矢量网络)是与相关的学习算法有关的监督学习模型,可以分析数据,识别模式,用于分类和回归分析。给定一组训练样本,每个标记为属于两类,一个SVM训练算法建立了一个模型,分配新的实例为一类或其他类,使其成为非概率二元线性分类。一个SVM模型的例子,如在空间中的点,映射,使得所述不同的类别的例子是由一个明显的差距是尽可能宽划分的表示。新的实施例则映射到相同的空间中,并预测基于它们落在所述间隙侧上属于一个类别。 +除了进行线性分类,支持向量机可以使用所谓的核技巧,它们的输入隐含映射成高维特征空间中有效地进行非线性分类。 + + +支持向量机将向量映射到一个更高维的空间里,在这个空间里建立有一个最大间隔超平面。在分开数据的超平面的两边建有两个互相平行的超平面。建立方向合适的分隔超平面使两个与之平行的超平面间的距离最大化。其假定为,平行超平面间的距离或差距越大,分类器的总误差越小。 +

+ +

+ + +#### 应用示例 +```python +# coding: utf8 +# svm/smo.py + +import numpy as np + +from sklearn.metrics.pairwise import rbf_kernel + +""" +svm模型 +""" + +def linearKernel(): + """线性核函数 + """ + def calc(X, A): + return X * A.T + return calc + +def rbfKernel(delta): + """rbf核函数 + """ + gamma = 1.0 / (2 * delta**2) + + def calc(X, A): + return np.mat(rbf_kernel(X, A, gamma=gamma)) + return calc + +def getSmo(X, y, C, tol, maxIter, kernel=linearKernel()): + """SMO + + Args: + X 训练样本 + y 标签集 + C 正规化参数 + tol 容忍值 + maxIter 最大迭代次数 + K 所用核函数 + + Returns: + trainSimple 简化版训练算法 + train 完整版训练算法 + predict 预测函数 + """ + # 存放核函数的转化结果 + K = kernel(X, X) + # Cache存放预测误差,用以加快计算速度 + ECache = np.zeros((m,2)) + + def predict(X, alphas, b, supportVectorsIndex, supportVectors): + """计算权值向量 + + Args: + X 预测矩阵 + alphas alphas + b b + supportVectorsIndex 支持向量坐标集 + supportVectors 支持向量 + Returns: + predicts 预测结果 + """ + Ks = kernel(supportVectors, X) + predicts = (np.multiply(alphas[supportVectorsIndex], y[ + supportVectorsIndex]).T * Ks + b).T + predicts = np.sign(predicts) + return predicts + + def w(alphas, b, supportVectorsIndex, supportVectors): + """计算权值 + + Args: + alphas alphas + b b + supportVectorsIndex 支持向量坐标 + supportVectors 支持向量 + Returns: + w 权值向量 + """ + return (np.multiply(alphas[supportVectorsIndex], y[ + supportVectorsIndex]).T * supportVectors).T + + def E(i, alphas, b): + """计算预测误差 + + Args: + i i + alphas alphas + b b + Returns: + E_i 第i个样本的预测误差 + """ + FXi = float(np.multiply(alphas, y).T * K[:, i]) + b + E = FXi - float(y[i]) + return E + + def updateE(i, alphas, b): + ECache[i] = [1, E(i, alphas, b)] + + def selectJRand(i): + """ + """ + j = i + while j == i: + j = int(np.random.uniform(0, m)) + return j + + def selectJ(i, Ei, alphas, b): + """选择权值 {% math %}\alpha^{(i)}{% endmath %} + """ + maxJ = 0; maxDist=0; Ej = 0 + ECache[i] = [1, Ei] + validCaches = np.nonzero(ECache[:, 0])[0] + if len(validCaches) > 1: + for k in validCaches: + if k==i: continue + Ek = E(k, alphas, b) + dist = np.abs(abs(Ei-Ek)) + if maxDist < dist: + Ej = Ek + maxJ = k + maxDist = dist + return maxJ, Ej + else: + ### 随机选择 + j = selectJRand(i) + Ej = E(j, alphas, b) + return j, Ej + + def select(i, alphas, b): + """alpha对选择 + """ + Ei = E(i, alphas, b) + # 选择违背KKT条件的,作为alpha2 + Ri = y[i] * Ei + if (Ri < -tol and alphas[i] < C) or \ + (Ri > tol and alphas[i] > 0): + # 选择第二个参数 + j = selectJRand(i) + Ej = E(j, alphas, b) + # j, Ej = selectJ(i, Ei, alphas, b) + # get bounds + if y[i] != y[j]: + L = max(0, alphas[j] - alphas[i]) + H = min(C, C + alphas[j] - alphas[i]) + else: + L = max(0, alphas[j] + alphas[i] - C) + H = min(C, alphas[j] + alphas[i]) + if L == H: + return 0, alphas, b + Kii = K[i, i] + Kjj = K[j, j] + Kij = K[i, j] + eta = 2.0 * Kij - Kii - Kjj + if eta >= 0: + return 0, alphas, b + iOld = alphas[i].copy() + jOld = alphas[j].copy() + alphas[j] = jOld - y[j] * (Ei - Ej) / eta + if alphas[j] > H: + alphas[j] = H + elif alphas[j] < L: + alphas[j] = L + if abs(alphas[j] - jOld) < tol: + alphas[j] = jOld + return 0, alphas, b + alphas[i] = iOld + y[i] * y[j] * (jOld - alphas[j]) + # update ECache + updateE(i, alphas, b) + updateE(j, alphas, b) + # update b + bINew = b - Ei - y[i] * (alphas[i] - iOld) * Kii - y[j] * \ + (alphas[j] - jOld) * Kij + bJNew = b - Ej - y[i] * (alphas[i] - iOld) * Kij - y[j] * \ + (alphas[j] - jOld) * Kjj + if alphas[i] > 0 and alphas[i] < C: + bNew = bINew + elif alphas[j] > 0 and alphas[j] < C: + bNew = bJNew + else: + bNew = (bINew + bJNew) / 2 + return 1, alphas, b + else: + return 0, alphas, b + + def train(): + """完整版训练算法 + + Returns: + alphas alphas + w w + b b + supportVectorsIndex 支持向量的坐标集 + supportVectors 支持向量 + iterCount 迭代次数 + """ + numChanged = 0 + examineAll = True + iterCount = 0 + alphas = np.mat(np.zeros((m, 1))) + b = 0 + # 如果所有alpha都遵从 KKT 条件,则在整个训练集上迭代 + # 否则在处于边界内 (0, C) 的 alpha 中迭代 + while (numChanged > 0 or examineAll) and (iterCount < maxIter): + numChanged = 0 + if examineAll: + for i in range(m): + changed, alphas, b = select(i, alphas, b) + numChanged += changed + else: + nonBoundIds = np.nonzero((alphas.A > 0) * (alphas.A < C))[0] + for i in nonBoundIds: + changed, alphas, b = select(i, alphas, b) + numChanged += changed + iterCount += 1 + + if examineAll: + examineAll = False + elif numChanged == 0: + examineAll = True + supportVectorsIndex = np.nonzero(alphas.A > 0)[0] + supportVectors = np.mat(X[supportVectorsIndex]) + return alphas, w(alphas, b, supportVectorsIndex, supportVectors), b, \ + supportVectorsIndex, supportVectors, iterCount + + def trainSimple(): + """简化版训练算法 + + Returns: + alphas alphas + w w + b b + supportVectorsIndex 支持向量的坐标集 + supportVectors 支持向量 + iterCount 迭代次数 + """ + numChanged = 0 + iterCount = 0 + alphas = np.mat(np.zeros((m, 1))) + b = 0 + L = 0 + H = 0 + while iterCount < maxIter: + numChanged = 0 + for i in range(m): + Ei = E(i, alphas, b) + Ri = y[i] * Ei + # 选择违背KKT条件的,作为alpha2 + if (Ri < -tol and alphas[i] < C) or \ + (Ri > tol and alphas[i] > 0): + # 选择第二个参数 + j = selectJRand(i) + Ej = E(j, alphas, b) + # get bounds + if y[i] != y[j]: + L = max(0, alphas[j] - alphas[i]) + H = min(C, C + alphas[j] - alphas[i]) + else: + L = max(0, alphas[j] + alphas[i] - C) + H = min(C, alphas[j] + alphas[i]) + if L == H: + continue + Kii = K[i, i] + Kjj = K[j, j] + Kij = K[i, j] + eta = 2.0 * Kij - Kii - Kjj + if eta >= 0: + continue + iOld = alphas[i].copy(); + jOld = alphas[j].copy() + alphas[j] = jOld - y[j] * (Ei - Ej) / eta + if alphas[j] > H: + alphas[j] = H + elif alphas[j] < L: + alphas[j] = L + if abs(alphas[j] - jOld) < tol: + alphas[j] = jOld + continue + alphas[i] = iOld + y[i] * y[j] * (jOld - alphas[j]) + # update b + bINew = b - Ei - y[i] * (alphas[i] - iOld) * Kii - y[j] * \ + (alphas[j] - jOld) * Kij + bJNew = b - Ej - y[i] * (alphas[i] - iOld) * Kij - y[j] * \ + (alphas[j] - jOld) * Kjj + if alphas[i] > 0 and alphas[i] < C: + b = bINew + elif alphas[j] > 0 and alphas[j] < C: + b = bJNew + else: + b = (bINew + bJNew) / 2.0 + numChanged += 1 + if numChanged == 0: + iterCount += 1 + else: + iterCount = 0 + supportVectorsIndex = np.nonzero(alphas.A > 0)[0] + supportVectors = np.mat(X[supportVectorsIndex]) + return alphas, w(alphas, b, supportVectorsIndex, supportVectors), b, \ + supportVectorsIndex, supportVectors, iterCount + return trainSimple, train, predict +``` +相比于神经网络这样更先进的算法,支持向量机有两大主要优势:更高的速度、用更少的样本(千以内)取得更好的表现。这使得该算法非常适合文本分类问题。 diff --git a/assets/src/KBO/KBO.0.3.md b/assets/src/KBO/KBO.0.3.md new file mode 100644 index 00000000..4e81aaf2 --- /dev/null +++ b/assets/src/KBO/KBO.0.3.md @@ -0,0 +1,148 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 径向基函数(Radial Basis Function ,RBF) + +径向基函数(RBF,Radial Basis Function)神经网络,是一种对局部逼近的神经网络。是由J.Moody 和C.Darken于20世纪80年代末提出的一种神经网络,径向基函数方法在某种程度上利用了多维空间中传统的严格插值法的研究成果。在神经网络的背景下,隐藏单元提供一个“函数”集,该函数集在输入模式向量扩展至隐层空间时为其构建了一个任意的“基”;这个函数集中的函数就被称为径向基函数。径向基函数首先是在实多变量插值问题的解中引入的。径向基函数是目前数值分析研究中的一个主要领域之一。 + +最基本的径向基函数(RBF)神经网络的构成包括三层,其中每一层都有着完全不同的作用。输入层由一些感知单元组成,它们将网络与外界环境连接起来;第二层是网络中仅有的一个隐层,它的作用是从输入空间到隐层空间之间进行非线性变换,在大多数情况下,隐层空间有较高的维数;输出层是线性的,它为作用于输入层的激活模式提供响应。 + +基本的径向基函数RBF网络是具有单稳层的三层前馈网络。由于它模拟了人脑中局部调整、相互覆盖接受域(或称感受域,Receptive Field)的神经网络结构,因此,RBF网络是一种局部逼近网络,现已证明它能以任意精度逼近任一连续函数。 + +RBF 神经网络是一种三层前向网络,通过输入层空间到隐含层空间的非线性变换以及隐含层空间到输出层空间的线性变换,实现输入层空间到输出层空间的映射。这两个层间变换参数的学习可以分别进行,使得 RBF 神经网络的学习速度较快且可避免局部极小问题。 + + +RBF(Radial Basis Function,径向基函数)是某种沿径向对称的标量函数,通常定义为空间中一点到某一中心之间欧氏距离的单调函数,最常用的径向基函数是高斯函数,形式为: + +

+ +

+ +中为函数中心向量,为宽度向量。高斯函数的作用域表现出局部性,即当远离时函数取值较小。 + +如下图所示,RBF 神经网络的结构从左至右分为三层,依次是输入层、隐含层和输出层: + +

+ +

+ +RBF神经网络结构图 + +网络的输出如下式所示: + +

+ +

+ +与BP神经网络类似,理论上RBF神经网络对任何非线性连续映射能够用任意精度近似。但RBF神经网络有其自身的特点: + +RBF 神经网络结构的物理意义比较明确。RBF 网络可以看成是输入层数据空间(通常是低维空间)到隐含层空间(通常是高维空间)的一种非线性映射,以及隐含层空间到输出层的线性映射。通过选择适当的非线性映射变换 RBF 函数,从而将原低维空间非线性不可分的问题转换成高维空间的近似线性可分的问题。 + +RBF 神经网络的学习分成两阶段,自组织学习阶段和监督学习阶段。在自组织学习阶段获取隐含层中心,在监督学习阶段获取隐含层到输出层之间的权值,各部分参数都可以快速学习,因此速度较快。 + +分阶段学习的 RBF 神经网络无局部极小值问题。由于 RBF 神经网络的学习与输入样本聚类中心密切相关,因此 RBF 神经网络比较适合应用于有类别特征的数据。 + +模型隐含层中心个数设定原则: + +由于RBF神经网络的思想是将低维空间非线性不可分问题转换成高维空间线性可分问题,因此隐含层中心个数应该大于输入变量个数,一般设为输入变量个数的 2 倍以上。 + +由于隐含层中心点坐标代表了输入数据的聚类中心,因此隐含层中心个数应该大于输入数据集的按记录划分的类别个数,这样才能有效提取各种类别输入数据的特征。这需要对输入数据集的业务特征有一定了解,然后给出输入数据类别个数的大致范围。一般设隐含层中心个数为输入数据类别个数的 2 倍以上。 + +综合以上两个原则设定隐含层中心个数,然后可以根据训练和测试的效果,对中心个数进行适当调整。一般情况下,中心个数设得越多,训练的效果越好,但所需要的时间越长;而当中心个数多到一定程度的时候,增多中心个数对训练效果的改善已不大。另外,隐含层中心数应该不大于训练数据记录数。 + + +#### 应用示例 +```python +def kernelTrans(X, A, kTup): # calc the kernel or transform data to a higher dimensional space + """ + 核转换函数 + Args: + X dataMatIn数据集 + A dataMatIn数据集的第i行的数据 + kTup 核函数的信息 + + Returns: + + """ + m, n = shape(X) + K = mat(zeros((m, 1))) + if kTup[0] == 'lin': + # linear kernel: m*n * n*1 = m*1 + K = X * A.T + elif kTup[0] == 'rbf': + for j in range(m): + deltaRow = X[j, :] - A + K[j] = deltaRow * deltaRow.T + # 径向基函数的高斯版本 + K = exp(K / (-1 * kTup[1] ** 2)) # divide in NumPy is element-wise not matrix like Matlab + else: + raise NameError('Houston We Have a Problem -- That Kernel is not recognized') + return K + +def smoP(dataMatIn, classLabels, C, toler, maxIter, kTup=('lin', 0)): + """ + Args: + dataMatIn 数据集 + classLabels 类别标签 + C 松弛变量(常量值),允许有些数据点可以处于分隔面的错误一侧。 + 控制最大化间隔和保证大部分的函数间隔小于1.0这两个目标的权重。 + 可以通过调节该参数达到不同的结果。 + toler 容错率 + maxIter 退出前最大的循环次数 + kTup 包含核函数信息的元组 + Returns: + b 模型的常量值 + alphas 拉格朗日乘子 + """ + + # 创建一个 optStruct 对象 + oS = optStruct(mat(dataMatIn), mat(classLabels).transpose(), C, toler, kTup) + iter = 0 + entireSet = True + alphaPairsChanged = 0 + + # 循环遍历:循环maxIter次 并且 (alphaPairsChanged存在可以改变 or 所有行遍历一遍) + while (iter < maxIter) and ((alphaPairsChanged > 0) or (entireSet)): + alphaPairsChanged = 0 + + # 当entireSet=true or 非边界alpha对没有了;就开始寻找 alpha对,然后决定是否要进行else。 + if entireSet: + # 在数据集上遍历所有可能的alpha + for i in range(oS.m): + # 是否存在alpha对,存在就+1 + alphaPairsChanged += innerL(i, oS) + # print("fullSet, iter: %d i:%d, pairs changed %d" % (iter, i, alphaPairsChanged)) + iter += 1 + + # 对已存在 alpha对,选出非边界的alpha值,进行优化。 + else: + # 遍历所有的非边界alpha值,也就是不在边界0或C上的值。 + nonBoundIs = nonzero((oS.alphas.A > 0) * (oS.alphas.A < C))[0] + for i in nonBoundIs: + alphaPairsChanged += innerL(i, oS) + # print("non-bound, iter: %d i:%d, pairs changed %d" % (iter, i, alphaPairsChanged)) + iter += 1 + + # 如果找到alpha对,就优化非边界alpha值,否则,就重新进行寻找,如果寻找一遍 遍历所有的行还是没找到,就退出循环。 + if entireSet: + entireSet = False # toggle entire set loop + elif (alphaPairsChanged == 0): + entireSet = True + print("iteration number: %d" % iter) + return oS.b, oS.alphas +``` + +#### RBF优点 +优点: +1. 它具有唯一最佳的特性,且无局部极小问题存在; +2. RBF神经网络具有较强的输入和输出映射功能,并且理论证明在前向网络中RBF神经网络是完成映射功能的最有效网络; +3. 分类能力好; +4. 学习过程收敛速度快。 + + +#### RBF缺点 +缺点: +1. 没有能力来解释自己的推理过程和推理依据; +2. 当样本数据不足时,预测结果不太准确。 + diff --git a/assets/src/KBO/KBO.0.4.md b/assets/src/KBO/KBO.0.4.md new file mode 100644 index 00000000..6bf36dbe --- /dev/null +++ b/assets/src/KBO/KBO.0.4.md @@ -0,0 +1,227 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 线性判别分析(Linear Discriminate Analysis ,LDA) + +线性判别式分析(Linear Discriminant Analysis, LDA),也叫做Fisher线性判别(Fisher Linear Discriminant ,FLD),是模式识别的经典算法,它是在1996年由Belhumeur引入模式识别和人工智能领域的。线性判别分析是一种经典的线性分类方法。它设法将数据集投影到一条直线上,使得同类样例的投影点尽可能接近,异类样例的投影点尽可能远。这样,在分类时,新样本同样投影到这条直线上,根据投影点的位置来确定类别。 + +由于LDA把原来N维的样本投影到了N-1维空间,因而也常被视为一种经典的降维技术。 + +预使得同类样例的投影点尽可能接近,可以让同类样例投影点的协方差尽可能小,即尽可能小。预使得异类样例的投影点尽可能远,可以让不同类样例的投影点尽可能远,即让类中心距离尽可能大,即 尽可能大。这样,目标函数为. + +其中类内散度矩阵,类间散度矩阵. + +使用拉格朗日乘子法可以求解得到. + +对多分类情况,,W的解是的N−1 个最大广义特征值所对应的特征向量组成的矩阵。 + +线性判别分析降维一般分为5个步骤: +* 计算数据集中每个类别样本的均值向量。 +* 通过均值向量,计算类间散度矩阵和类内散度矩阵。 +* 对进行特征值求解, 求出的特征向量和特征值。 +* 对特征向量按照特征值的大小降序排列,并选择前K个特征向量组成投影矩阵W。 +* 通过D*K维的特征值矩阵将样本点投影到新的子空间中,. + + +#### 应用示例 +```python +# coding: utf-8 +import pandas as pd + +# u may download data from (https://archive.ics.uci.edu/ml/datasets/Iris). +df = pd.read_csv('iris.data', header=None) + +feature_dict = {i:label for i,label in zip( + range(4), + ('sepal length in cm', + 'sepal width in cm', + 'petal length in cm', + 'petal width in cm', ))} +df.columns = [l for i,l in sorted(feature_dict.items())] + ['class label'] +df.dropna(how="all", inplace=True) # to drop the empty line at file-end + +df.tail() + + +from sklearn.preprocessing import LabelEncoder + +X = df[[0,1,2,3]].values +y = df['class label'].values + +enc = LabelEncoder() +label_encoder = enc.fit(y) +y = label_encoder.transform(y) + 1 + +label_dict = {1: 'Setosa', 2: 'Versicolor', 3:'Virginica'} + + +from matplotlib import pyplot as plt +import numpy as np +import math + +fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(12,6)) + +for ax,cnt in zip(axes.ravel(), range(4)): + + # set bin sizes + min_b = math.floor(np.min(X[:,cnt])) + max_b = math.ceil(np.max(X[:,cnt])) + bins = np.linspace(min_b, max_b, 25) + + # plottling the histograms + for lab,col in zip(range(1,4), ('blue', 'red', 'green')): + ax.hist(X[y==lab, cnt], + color=col, + label='class %s' %label_dict[lab], + bins=bins, + alpha=0.5,) + ylims = ax.get_ylim() + + # plot annotation + leg = ax.legend(loc='upper right', fancybox=True, fontsize=8) + leg.get_frame().set_alpha(0.5) + ax.set_ylim([0, max(ylims)+2]) + ax.set_xlabel(feature_dict[cnt]) + ax.set_title('Iris histogram #%s' %str(cnt+1)) + + # hide axis ticks + ax.tick_params(axis="both", which="both", bottom="off", top="off", + labelbottom="on", left="off", right="off", labelleft="on") + + # remove axis spines + ax.spines["top"].set_visible(False) + ax.spines["right"].set_visible(False) + ax.spines["bottom"].set_visible(False) + ax.spines["left"].set_visible(False) + +axes[0][0].set_ylabel('count') +axes[1][0].set_ylabel('count') + +fig.tight_layout() + +plt.show() + +# 因此在实际应用中,我们对特征进行降维,除了使用类似于LDA的特征投影方法(或者叫extraction),特征选择(selection)也是一种较好的方式。 +# 像上图这种低纬度的数据集,看一眼直方图我们就可以做出一定的判断。 + + +# step1:计算D维特征样本的均值向量 +np.set_printoptions(precision=4) + +mean_vectors = [] +for cl in range(1,4): + mean_vectors.append(np.mean(X[y==cl], axis=0)) + print('Mean Vector class %s: %s\n' %(cl, mean_vectors[cl-1])) + + +# step2: 计算散度矩阵 +# 计算类内散度矩阵:Sw +S_W = np.zeros((4,4)) +for cl,mv in zip(range(1,4), mean_vectors): + class_sc_mat = np.zeros((4,4)) # scatter matrix for every class + for row in X[y == cl]: + row, mv = row.reshape(4,1), mv.reshape(4,1) # make column vectors + class_sc_mat += (row-mv).dot((row-mv).T) + S_W += class_sc_mat # sum class scatter matrices + + +# 计算类间三度矩阵:Sb +overall_mean = np.mean(X, axis=0) + +S_B = np.zeros((4,4)) +for i,mean_vec in enumerate(mean_vectors): + n = X[y==i+1,:].shape[0] + mean_vec = mean_vec.reshape(4,1) # make column vector + overall_mean = overall_mean.reshape(4,1) # make column vector + S_B += n * (mean_vec - overall_mean).dot((mean_vec - overall_mean).T) + +print('between-class Scatter Matrix:\n', S_B) + + + +# step3:求解S?1WSB的特征值问题: +eig_vals, eig_vecs = np.linalg.eig(np.linalg.inv(S_W).dot(S_B)) + +for i in range(len(eig_vals)): + eigvec_sc = eig_vecs[:,i].reshape(4,1) + print('\nEigenvector {}: \n{}'.format(i+1, eigvec_sc.real)) + print('Eigenvalue {:}: {:.2e}'.format(i+1, eig_vals[i].real)) +print('within-class Scatter Matrix:\n', S_W) + + + +# step4:选择新的特征空间 +# 先将特征向量按照特征值的大小降序排列,线代中告诉我我们,矩阵乘法可以看做一种线性变换,而特征向量和特征值代表了变换后的方向以及该方向上的 +# 缩放比例,因此特征值越大,说明这个方向在变换中越显著,也就是信息量最大。因此我们需要抛弃的是特征值较小的方向,因此我们只需要选取前topk个特征值 +# 对应的特征向量,就得到了映射矩阵W + +# Make a list of (eigenvalue, eigenvector) tuples +eig_pairs = [(np.abs(eig_vals[i]), eig_vecs[:,i]) for i in range(len(eig_vals))] + +# Sort the (eigenvalue, eigenvector) tuples from high to low +eig_pairs = sorted(eig_pairs, key=lambda k: k[0], reverse=True) + +# Visually confirm that the list is correctly sorted by decreasing eigenvalues + +print('Eigenvalues in decreasing order:\n') +for i in eig_pairs: + print (i[0], i[1]) + +# 从上面的特征值可以看到有2个特征值非常接近0,这2个值之所以接近0,一是代表了他们不包含信息量,第二是因为浮点运算的精确度问题。 +# 实际上这2分特征值应该就是0, 因为在LDA中,如果有C类,线性判别式最多只有C-1个,因此对于之前3类的数据集,最多只有2个特征值。 +# 由于类间散度矩阵S_B是不同类别C矩阵的和,而C矩阵的秩是1,对于最特殊的完美共线性情况(即所有样本点都在一条直线上),协方差矩阵的秩就会是1, +# 这就导致了只会有一个非0的特征值。 +# 我们通过特征值的比例来体现方差的分布: +print('Variance explained:\n') +eigv_sum = sum(eig_vals) +for i,j in enumerate(eig_pairs): + print('eigenvalue {0:}: {1:.2%}'.format(i+1, (j[0]/eigv_sum).real)) + +W = np.hstack((eig_pairs[0][1].reshape(4,1), eig_pairs[1][1].reshape(4,1))) + + +# step5:将样本投影到新的空间 +X_lda = X.dot(W) +assert X_lda.shape == (150,2), "The matrix is not 150x2 dimensional." + + +from matplotlib import pyplot as plt + +def plot_step_lda(): + + ax = plt.subplot(111) + for label,marker,color in zip( + range(1,4),('^', 's', 'o'),('blue', 'red', 'green')): + + plt.scatter(x=X_lda[:,0].real[y == label], + y=X_lda[:,1].real[y == label], + marker=marker, + color=color, + alpha=0.5, + label=label_dict[label] + ) + + plt.xlabel('LD1') + plt.ylabel('LD2') + + leg = plt.legend(loc='upper right', fancybox=True) + leg.get_frame().set_alpha(0.5) + plt.title('LDA: Iris projection onto the first 2 linear discriminants') + + # hide axis ticks + plt.tick_params(axis="both", which="both", bottom="off", top="off", + labelbottom="on", left="off", right="off", labelleft="on") + + # remove axis spines + ax.spines["top"].set_visible(False) + ax.spines["right"].set_visible(False) + ax.spines["bottom"].set_visible(False) + ax.spines["left"].set_visible(False) + + plt.grid() + plt.tight_layout + plt.show() + +plot_step_lda() +``` diff --git a/assets/src/KNN/KNN.md b/assets/src/KNN/KNN.md new file mode 100644 index 00000000..3978c689 --- /dev/null +++ b/assets/src/KNN/KNN.md @@ -0,0 +1,49 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +机器学习是一门多领域交叉学科,涉及概率论、统计学、逼近论、凸分析、算法复杂度理论等多门学科。主要研究计算机怎样模拟或实现人类的学习行为,以获取新的知识和技能,重新组织已有的知识结构,不断的改善自身的性能。 + +机器学习理论主要是设计和分析一些让计算机可以自动“学习”的算法。这些算法是一类能从数据中自动分析获得规律,并利用规律对未知数据进行预测的算法。简而言之,机器学习主要以数据为基础,通过大数据本身,运用计算机自我学习来寻找数据本身的规律,而这是机器学习与统计分析的基本区别。 + +机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 + +#### KNN +K最近邻算法是一种基于类比的分类方法,主要通过给定的检验组与和它相似的训练组进行比较来学习。训练组用n个属性来描述,每个元组代表n维空间上的点。当给定一个未知元组时,K最近邻分类法搜索该模式空间,找出最接近未知元组的k个训练组,并将未知元组指派到模式空间中它的k个最近邻中的多数类中。 + +其中“最近邻”主要是以距离来度量的,一般使用欧几里得距离度量两个点或元组的距离,也可以使用曼哈顿距离或其他距离;欧几里得距离的主要计算公式如下: +

+ +

+ +注意:为了防止具有较大初始值域的属性比较小初始值域的属性的权重过大,在计算距离之前,需对每个属性值进行规范化。一般的规划方法有最小-最大规范化,零均值规范化,小数定标规范化等。 + +最小-最大规范化:将原始数据值映射到[0,1]空间中,假定minA和maxA分别是属性A的最小值和最大值,则规范化的公式为: +

+ +

+零均值规范化:基于属性A的均值和标准差上的规范化方法,具体计算如下: +

+ +

+ +小数定标规范化:通过移动属性A的小数点位置进行规范化,小数点的移动位数依赖于A的最大绝对值。具体计算如下:(其中j是使得MAX( v’ )<1的最小整数) +

+ +

+ +最近邻数K的确定,主要原理是选取产生最小误差率的k值。每次从k=1开始,使用检验集估计分类器的误差率;每次都允许增加一个近邻,重复该过程,选择误差率最小的k值。 + +#### 算法背景 + +KNN算法是由Cover和Hart提出来的,是一种懒惰的、有监督的、基于实例的机器学习方法。同时是向量空间模型下最好的分类算法之一。 + +#### 算法应用 +K最近邻算法是一种基本的分类方法,主要对数据进行分类处理。分类时,对新的记录,根据其K个最邻近的训练记录,这K个记录的多数属于某个类,就把该新的记录分为这个类。K值一般选取比较小的数值。通常采用交叉验证法来选取最优的K值。 + + +#### 优缺点 +优点:简单,有效;重新训练的代价低;计算时间和空间训练集的规模;对于数据集的交叉或重叠较多的待分样本集来说,KNN算法比其他算法合适;比较适用于样本容量较大的类域的自动分类,而对样本容量小的类域会产生较大的误分。 + +缺点:输出的可解释性不强;计算量较大;对数据样本容量相差较大的,应该先进行规范化处理。 + diff --git a/assets/src/LLM/img.png b/assets/src/LLM/img.png new file mode 100644 index 00000000..d5c17b3c Binary files /dev/null and b/assets/src/LLM/img.png differ diff --git a/assets/src/LLM/img_1.png b/assets/src/LLM/img_1.png new file mode 100644 index 00000000..d5c17b3c Binary files /dev/null and b/assets/src/LLM/img_1.png differ diff --git a/assets/src/LLM/llm.md b/assets/src/LLM/llm.md new file mode 100644 index 00000000..1f32b023 --- /dev/null +++ b/assets/src/LLM/llm.md @@ -0,0 +1,172 @@ +#### 什么是大型语言模型? + +大型语言模型(LLM)是基于大量数据进行预训练的超大型深度学习模型。底层转换器是一组神经网络,这些神经网络由具有自注意力功能的编码器和解码器组成。编码器和解码器从一系列文本中提取含义,并理解其中的单词和短语之间的关系。 + +转换器 LLM 能够进行无监督的训练,但更精确的解释是转换器可以执行自主学习。通过此过程,转换器可学会理解基本的语法、语言和知识。 + +与早期按顺序处理输入的循环神经网络(RNN)不同,转换器并行处理整个序列。这可让数据科学家使用 GPU 训练基于转换器的 LLM,从而大幅度缩短训练时间。 + +借助转换器神经网络架构,您可使用非常大规模的模型,其中通常具有数千亿个参数。这种大规模模型可以摄取通常来自互联网的大量数据,但也可以从包含 500 多亿个网页的 Common Crawl 和拥有约 5700 万个页面的 Wikipedia 等来源摄取数据。 + +#### 为什么大型语言模型如此重要? + +大型语言模型非常灵活。一个模型可以执行完全不同的任务,例如回答问题、总结文档、翻译语言和完成语句。LLM 有可能破坏内容创作以及人们使用搜索引擎和虚拟助手的方式。 + +尽管并不完美,但 LLM 表现出根据相对较少量的提示或输入做出预测的非凡能力。LLM 可用于生成式人工智能,以根据采用人类语言的输入提示生成内容。 + +LLM 非常庞大。它们可以考虑数十亿个参数,并且有许多可能的用途。下面是一些示例: + +Open AI 的 GPT-3 模型有 1750 亿个参数。类似的产品 ChatGPT 可以从数据中识别模式并生成自然且可读的输出。 + +虽然我们不知道 Claude 2 的规模,但该模型可以在每个提示中输入多达 10 万个令牌,这意味着它可以处理数百页的技术文档,甚至可以处理整本书。 + +AI21 Labs 的 Jurassic-1 模型具有 1780 亿个参数和由 25 万单词部分组成的令牌词汇表以及类似的对话功能。 + +Cohere 的 Command 模型具有类似的功能,并且可以使用 100 多种不同的语言开展工作。 + +LightOn 的 Paradigm 提供根基模型,并且宣称该模型的功能超过 GPT-3。所有这些 LLM 都带有 API,可让开发人员打造独特的生成式人工智能应用程序。 + + +Timeline of LLMs: + +

+ +

+ +#### 大型语言模型如何运作? + +LLM 运作原理的一个关键因素是它们表示单词的方式。 + +早期的机器学习使用数字表来表示每个单词。但是,这种表示形式无法识别单词之间的关系,例如具有相似含义的单词。 + +人们采用如下方式克服此限制:使用多维向量(通常称为单词嵌入)来表示单词,从而使具有相似上下文含义或其他关系的单词在向量空间中彼此接近。 + +使用单词嵌入,转换器可以通过编码器将文本预处理为数字表示,并理解含义相似的单词和短语的上下文以及单词之间的其他关系,例如语音部分。然后,LLM 就可以通过解码器应用这些语言知识来生成独特的输出。 + +#### 大型语言模型有哪些应用? + +LLM 有很多实际应用。 + +* 文案写作 + +除了 GPT-3 和 ChatGPT 之外,Claude、Llama 2、Cohere Command 和 Jurassic 也可编写原件。 + +AI21 Wordspice 建议修改原始语句以改善风格和语音。 + +* 知识库回答 + +该技术通常称为知识密集型自然语言处理(KI-NLP),是指可以根据数字存档中的信息帮助回答特定问题的 LLM。AI21 Studio playground 能够回答常识性问题就是此类示例。 + +* 文本分类 + +使用集群,LLM 可以对含义或情绪相似的文本进行分类。用途包括衡量客户情绪、确定文本之间的关系和文档搜索。 + +* 代码生成 + +LLM 擅长根据自然语言提示生成代码。示例包括 Amazon CodeWhisperer 和 GitHub Copilot 中使用的 Open AI Codex,它们可以用 Python、JavaScript、Ruby 和其他几种编程语言编码。其他编码应用包括创建 SQL 查询、编写 Shell 命令和进行网站设计。 + +* 文本生成 + +与代码生成类似,文本生成可以完成不完整的语句,编写产品文档,或者像 Alexa Create 一样创作简短的儿童故事。 + +#### 如何训练大型语言模型? + +基于转换器的神经网络非常庞大。这些网络包含多个节点和层。层中的每个节点都有指向后续层中所有节点的连接,并且每个节点都有权重和偏差。权重和偏差以及嵌入称为模型参数。基于转换器的大型神经网络可以有数十亿个参数。模型的大小通常由模型大小、参数数量和训练数据规模之间的经验关系决定。 + +使用大量高质量数据执行训练。在训练过程中,模型会迭代调整参数值,直到模型可根据前一个输入令牌序列正确预测下一个令牌。为此,模型使用自学技术,这些技术教导模型调整参数,以最大限度地提高训练示例中正确预测下一个令牌的可能性。 + +经过训练,LLM 可以很容易地适应使用相对较小的有监督数据集执行多项任务,这一过程称为微调。 + +存在三种常见的学习模型: + +* 零样本学习;Base LLM 无需明确训练即可响应各种请求,通常是通过提示,但是答案的准确性各不相同。 +* 少量样本学习:通过提供一些相关的训练示例,基础模型在该特定领域的表现显著提升。 +* 微调:这是少量样本学习的扩展,其中数据科学家训练基础模型,使模型使用与特定应用相关的其他数据来调整其参数。 + +#### LLM 的未来前景是什么? + +随着 ChatGPT、Claude 2 和 Llama 2 等可以回答问题和生成文本的大型语言模型的引入,我们可以预见令人兴奋的未来前景。可以肯定的是,LLM 会越来越接近人性化的表现,尽管这一过程会较为漫长。这些 LLM 即时取得的成功表明人们对机器人类型 LLM 的浓厚兴趣,这些 LLM 可模仿人类大脑的思维,在某些情况下表现甚至优于人类大脑。以下是一些关于 LLM 未来前景的想法: + +* 增强的功能 + +尽管 LLM 给人们留下了深刻的印象,但当前的技术水平并不完善,LLM 也并非绝对可靠。然而,随着开发人员学习如何在减少偏见和消除错误答案的同时提高性能,较新的 LLM 版本将提高准确性和增强功能。 + +* 视听训练 + +开发人员使用文本训练大多数 LLM,但有些人已经开始使用视频和音频输入来训练模型。这种形式的训练应该可以加快模型开发速度,并为将 LLM 用于自动驾驶汽车开辟新的可能性。 + +* 工作场所转型 + +LLM 是颠覆性的因素,它将转变工作场所。LLM 可能会采用机器人处理重复性制造任务的相同方式来减少单调和重复的任务。可能减少的任务包括重复的文书任务、客户服务聊天机器人和简单的自动文案写作。 + +* 对话式人工智能 + +LLM 无疑将提高 Alexa、Google Assistant 和 Siri 等自动虚拟助手的性能。这些虚拟助手将能够更妥善地解释用户意图并响应复杂的命令。 + +#### 学习大语言模型指南 + +1. 入门篇: + +* 了解大语言模型的基础知识和常见术语。 +* 学会使用编程语言访问 OpenAI API 等常见大语言模型接口。 + +2. 提高篇: + +* 了解机器学习、神经网络、NLP 的基础知识。 +* 了解 Transformer 以及典型 Decoder-only 语言模型的基础结构和简单原理。 +* 了解大语言模型发展历史,以及业界主流模型(含开源模型)进展。 + +3. 应用篇: + +* 可以在本地环境搭建开源模型的推理环境。 +* Prompt 工程。 +* 使用已有框架(如Langchain)或自行开发,结合大语言模型结果,开发生产应用。 + +4. 深入篇: + +* 掌握 Continue Pre-train、Fine-tuning 已有开源模型的能力。 +* 掌握 Lora、QLora 等低资源高效模型训练的能力。 +* 掌握大语言模型微调以及预训练数据准备的能力。 +* 深入了解大模型背后的技术原理。 +* 了解生产环境部署大模型的相关技术点。 + +#### 学习资料 + +1. 入门篇 + +* [大语言模型](https://github.com/RUCAIBox/LLMSurvey) +* [ChatGPT Prompt Engineering for Developers](https://learn.deeplearning.ai/courses/chatgpt-prompt-eng/lesson/1/introduction) +* [Prompt中英双语字幕](https://github.com/GitHubDaily/ChatGPT-Prompt-Engineering-for-Developers-in-Chinese) +* [OpenAI 官方 Quickstart 文档](https://platform.openai.com/docs/api-reference) +* [GPT的训练和应用](https://www.youtube.com/watch?v=bZQun8Y4L2A) +* [GPT的训练和应用稳定](https://karpathy.ai/stateofgpt.pdf) + + +2. 提高篇 + +* [清华大模型公开课:从NLP到大模型的综合课程](https://www.bilibili.com/video/BV1UG411p7zv/?vd_source=66c6e275fb1f3c8315a531e1a1b051d8) +* [深度学习:台湾大学李宏毅](https://www.bilibili.com/video/BV1J94y1f7u5/) +* [The Illustrated GPT-2 (Visualizing Transformer Language Models](https://jalammar.github.io/illustrated-gpt2/) +* [图解 GPT2 中文翻译](https://zhuanlan.zhihu.com/p/139840113) +* [InstructGPT: Training language models to follow instructions with human feedback](https://cdn.openai.com/papers/Training_language_models_to_follow_instructions_with_human_feedback.pdf) +* [RLHF技术详解](https://huggingface.co/blog/zh/rlhf) +* [NLP 入门课程](https://huggingface.co/learn/nlp-course/chapter1/1) + +3. 应用篇 + +* [Building Systems with the ChatGPT API](https://learn.deeplearning.ai/courses/chatgpt-building-system/lesson/1/introduction) +* [使用ChatGPT API构建系统](https://www.bilibili.com/video/BV1gj411X72B/) +* [Langchain 是大语言模型框架](https://python.langchain.com/docs/get_started/introduction) +* [LangChain for LLM Application Development](https://learn.deeplearning.ai/courses/langchain/lesson/1/introduction) +* [LLM应用开发实践](https://www.bilibili.com/video/BV1Ku411x78m/?vd_source=66c6e275fb1f3c8315a531e1a1b051d8) +* [OpenAI 官方出的最佳实践](https://platform.openai.com/docs/guides/gpt-best-practices/gpt-best-practices) +* [OpenAI 官方 Cookbook](https://github.com/openai/openai-cookbook) +* [Prompt 工程简介](https://github.com/brexhq/prompt-engineering) + + +4. 深入篇 + +* [Transformer 官方文档](https://huggingface.co/docs/transformers/index) +* [大语言模型的北极星能力](https://yaofu.notion.site/6dafe3f8d11445ca9dcf8a2ca1c5b199) +* [GPT,GPT-2,GPT-3 论文精读](https://www.bilibili.com/video/BV1AF411b7xQ/) +* [在生产环境中构建 LLM 应用](https://huyenchip.com/2023/04/11/llm-engineering.html) \ No newline at end of file diff --git a/assets/src/LLM/llm01.md b/assets/src/LLM/llm01.md new file mode 100644 index 00000000..8bdfcd04 --- /dev/null +++ b/assets/src/LLM/llm01.md @@ -0,0 +1,288 @@ +#### 什么是大型语言模型? + +大型语言模型(LLM)是基于大量数据进行预训练的超大型深度学习模型。底层转换器是一组神经网络,这些神经网络由具有自注意力功能的编码器和解码器组成。编码器和解码器从一系列文本中提取含义,并理解其中的单词和短语之间的关系。 + +转换器 LLM 能够进行无监督的训练,但更精确的解释是转换器可以执行自主学习。通过此过程,转换器可学会理解基本的语法、语言和知识。 + +与早期按顺序处理输入的循环神经网络(RNN)不同,转换器并行处理整个序列。这可让数据科学家使用 GPU 训练基于转换器的 LLM,从而大幅度缩短训练时间。 + +借助转换器神经网络架构,您可使用非常大规模的模型,其中通常具有数千亿个参数。这种大规模模型可以摄取通常来自互联网的大量数据,但也可以从包含 500 多亿个网页的 Common Crawl 和拥有约 5700 万个页面的 Wikipedia 等来源摄取数据。 + + +#### 大型语言模型工作原理 + +LLM 通过利用深度学习技术和大量文本数据来运行。这些模型通常基于转换器架构,如生成式预训练转换器,它擅长处理文本输入等顺序数据。LLM 由多层神经网络组成,每层神经网络的参数都可以在训练过程中进行微调,而被称为注意力机制的众多神经网络层则进一步增强了这些神经网络的功能,这些神经网络层可以对数据集的特定部分进行调整。 + +在训练过程中,这些模型学习根据前面单词提供的上下文来预测句子中的下一个单词。该模型通过将概率分数归因于重复的已标记单词(分解为较小的字符序列)来实现这一点。然后,这些标记被转换为嵌入,嵌入是该上下文的数字表示。 + +为了确保准确性,这个过程涉及在大量文本语料库(数十亿页)上训练 LLM,使 LLM 能够通过零样本和自我监督学习来学习语法、语义和概念关系。经过这些训练数据的训练后,LLM 就可以根据它们收到的输入自动预测下一个单词,并利用它们获得的模式和知识来生成文本。其结果是生成连贯且与上下文相关的语言,可用于广泛的 NLU 和内容生成任务。 + +还可以通过即时工程、即时调优、微调和其他策略来提高模型性能,例如基于人类反馈的强化学习 (RLHF),以消除偏见、仇恨言论和被称为“幻觉”的事实错误答案,这些通常是对如此多的非结构化数据进行训练的有害副产品。这是确保企业级 LLM 随时可用,不会使组织承担不必要的责任或对组织声誉造成损害的最重要的方面之一。 + +#### LLM 用例 + +LLM 正在重新定义越来越多的业务流程,并已在各个行业的无数用例和任务中证明了它们的多功能性。LLM 可以增强聊天机器人和虚拟助理(例如 IBM watsonx Assistant 和 Google 的 BARD)中的会话式 AI,以增强支持卓越客户服务的交互,提供模仿与人工客服交互的情境感知响应。 + +LLM 还擅长内容生成,可以自动创建内容,包括博客文章、营销或销售资料以及其他写作任务。在研究和学术界,它们帮助从大量数据集中总结和提取信息,加速知识发现。LLM 在语言翻译中也发挥着至关重要的作用,通过提供准确且与上下文相关的翻译来打破语言障碍。它们甚至可以用来编写代码,或者在编程语言之间进行“翻译”。 + +此外,它们还通过提供文字转语音应用以及以无障碍格式生成内容等功能,帮助残障人员,为无障碍访问功能做出了贡献。从医疗保健到金融,LLM 正在通过简化流程、改善客户体验以及实现更高效和数据驱动的决策来推动行业发展和变革。 + +最令人兴奋的是,所有这些功能都很容易访问,在某些情况下,实际上只需 API 集成即可。 + +以下是 LLM 为组织带来益处的一些最重要的领域: + +* 文本生成:语言生成能力,如根据提示撰写电子邮件、博客文章或其他中长篇内容,并加以提炼和润色。检索增强生成 (RAG) 就是一个很好的例子。 + +* 内容摘要:将长文章、新闻报道、研究报告、公司文档甚至客户历史记录汇总成根据输出格式定制长度的完整文本。 + +* AI 助手:聊天机器人,可以回答客户询问、执行后端任务并以自然语言提供详细信息,作为集成式自助客户服务解决方案的一部分。 + +* 代码生成:帮助开发人员构建应用程序,查找代码中的错误并发现多种编程语言中的安全问题,甚至在它们之间进行“翻译”。 + +* 情感分析:分析文本,确定客户的语气,以便大规模了解客户反馈并帮助进行品牌声誉管理。 + +* 语言翻译:通过流畅的翻译和多语言功能,为各语言和地域的组织提供更广泛的覆盖范围。 + +LLM 将通过实现客户自助服务自动化、加快对越来越多任务的响应以及提高准确性、增强路由和智能上下文收集,影响从金融到保险、人力资源到医疗保健等各个行业。 + +#### 增加大语言模型推理能力的方案 + +目前,推理的方案与构建通用大型语言模型和聊天机器人的方案密切相关。总共有三个阶段: + +- 预训练或持续训练:在这个阶段,我们通常在大型数据集(如科学文献或代码数据)上训练大型模型。 +- 有监督微调:在这个阶段,我们对模型进行微调,以便完成复杂任务的指令。 +- 强化学习:在这个阶段,我们使用诸如任务是否已全部/部分完成的信号作为奖励。 + +因此,在我们的文献分析中,我们同时考虑推理和编码。我们将看到,就学习方法而言,这两者之间存在惊人的相关性。 + +* 预训练与持续训练 + +分析以下几项研究: + +1. Lewkowycz et. al. 2022. Minerva: [Solving Quantitative Reasoning Problems with Language Models](https://arxiv.org/abs/2206.14858) + +* 在来自 Arxiv 论文的 38.5B 的 token 上继续训练 PaLM 540B。 +* 在 MATH (一个需要使用 LaTeX 格式回答问题的困难数据集),上的得分为 33.6([GPT-4 的得分是 42.5](https://github.com/FranxYao/chain-of-thought-hub)) + +2. Taylor et. al. 2022. [Galactica: A Large Language Model for Science](https://arxiv.org/abs/2211.09085) + +* 在包含论文、代码、参考资料、知识库和其他内容的 106B token 上预训练一个120B语言模型。 +* 在MATH上的表现为 20.4(Minerva 33.6,GPT-4 42.5) + +3. Chen et. al. 2021. [Codex: Evaluating Large Language Models Trained on Code](https://arxiv.org/abs/2107.03374) + +* 在159GB代码数据上继续训练 12B GPT-3 模型,提高了 HumanEval 数据集上的代码性能。 + +这些研究发现,在大量科学文献代码上进行训练可以显著提高基础模型的推理编码能力。 + +#### 监督微调 + +1. Chung et. al. 2022. [Scaling Instruction-Finetuned Language Models](https://arxiv.org/abs/2210.11416) + +- 使用多样化的指令显著提高了模型零样本泛化的能力 +- 在指令集合中混合思维链数据([the flan collection](https://arxiv.org/abs/2301.13688) 文章中进一步讨论了这个问题)明显提高了模型的思维链能力 +- 注意:尽管 the flan collection 数据集从多个维度激发了基础模型的能力,但这些指令并非来自真实的聊天机器人用户互动,因此可能[无法直接转化为更好的聊天性能](https://www.yitay.net/blog/flan-ul2-20b)。 + +2. Fu et. al. 2023. [Specializing Smaller Language Models towards Multi-Step Reasoning](https://arxiv.org/abs/2301.12726) + +- 将思维链推理能力提炼到较小规模(小于或等于 10B)的模型。通常,10B 规模的模型非常适合部署(更大的模型太贵了,更小的模型太弱了)。 +- 本文讨论了很多工程细节,如数据工程、能力平衡以及小型和大型模型之间的差异 + +3. [Li et. al. 2022. Competition-Level Code Generation with AlphaCode](https://arxiv.org/abs/2203.07814) + +- 在 715GB 的 GitHub 代码上预训练一个 41B 模型,然后在包含 13k 问题的 CodeContest 数据集上进行微调 +- 在测试期间,使用采样并根据是否通过示例测试来过滤解决方案。从某种意义上说,这种做法类似于推理问题中的 [self-consistency](https://arxiv.org/abs/2203.11171) 方法。 + + +目前关于指令微调的理解是: + +- 通过使用对话格式的数据,将基本模型调优为聊天机器人相对容易(参见像 Alpaca 和 MOSS 这样的优秀示例)。然而,闲聊的能力并不能转化为执行复杂任务的能力。从这个角度来看,模型就像人类一样:说得多不如干得好,代码见真章。 +- 实际上,指令调优问题是一个数据混合问题:如何最好地混合来自不同来源的指令数据,以便从所有角度均匀地提高模型性能(而不是像在 [CoT specialization](https://arxiv.org/abs/2301.12726) 和 [the flan collection](https://arxiv.org/abs/2301.13688) 中讨论的那样,增加一个维度但降低另一个维度)。 +- 数据混合的简单起点是:使用 10-20 个非思维链的数据点(以平衡不同维度的能力),但尽可能多地使用链式思维数据(以最大化推理能力)。 + +#### 强化学习 + +我们分析: + +- Uesato. et. al. 2022. [Solving math word problems with process- and outcome-based feedback](https://arxiv.org/abs/2211.14275) + - 基于中间推理和最终推理结果构建奖励模型。 +- Le et. al. 2022. [CodeRL: Mastering Code Generation through Pretrained Models and Deep Reinforcement Learning](https://arxiv.org/abs/2207.01780) + - 根据诸如编译错误、运行时错误或是否通过测试等信号训练奖励模型。 + +这两项工作都使用中间信号(对于推理,看中间步骤是否正确;对于编码,看代码是否编译)和最终信号作为奖励。 需要注意的是,这种类型的强化学习与基于人类反馈的强化学习(RLHF)有所不同,因为它不需要人类反馈。 + +#### 推理能力和代码能力的耦合 + +这里我们提出了一个假设,即在代码上进行训练可能会提高推理能力,原因如下: + +|-----------------|-----------|-----------| +| | 推理 | 代码 | +|数据格式 | 思维链 |逐行注释 | +|简单和中等难度的任务 | 一步一步推理|面向过程编程 | +|困难任务 | 问题分解 |面向对象编程 | + +- 代码注释是自然存在的链式思维数据。 +- 面向过程编程类似于逐步解决任务。这适用于简单和中等复杂度的任务。 +- 面向对象编程类似于将任务分解为较小的任务,然后分别解决它们。这适用于较高复杂度的任务。 + +从这个显著的一致性中,我们看到提高推理能力与提高编程能力非常相似。在此,我们通过强调训练大型语言模型进行推理或编码的配方相似性,深化了这个假设: + +|------------------|-----------------------------------------------------------------------------------|----------------------------------------------------------------| +| 持续训练 | 在科学文献上持续训练,数据格式 = 文本 + latex ,例子: Minerva / Galactica | 在代码上持续训练,数据格式 = 文本 + 编程语言 ,例子: Codex | +| 监督微调 | 使用思维链指令做监督微调,数据格式 = 思维链,例子: CoT specialization | 使用代码指令做监督微调, 数据格式 = 代码 例子: AlphaCode | +| 强化学习 | 使用思维链指令做监督微调,数据格式 = 思维链,例子: CoT specialization | 使用代码指令做监督微调, 数据格式 = 代码 例子: AlphaCode | +| 监督微调 | 使用中间过程和推理结果作为反馈,格式:是否推理正确,例子: process and outcome based reward | 使用编译率和通过率作为反馈,格式 = 代码是否正确执行 例子: CodeRL | +| 采样和解码 | Self-consistency:采样多个解决方案,然后进行多数投票 | Sampling and filtering: ,采样多个解决方案,然后过滤并聚类这些解决方案 | + +看到推理和代码都经历了: + +- 在连续训练阶段,可以在基础模型上增加代码和科学文献数据。 +- 在有监督的微调阶段,可以根据要求完成复杂任务的指令或编写代码对模型进行微调。 +- 在强化学习阶段,将中间推理步骤 / 编译率和最终推理结果 / 代码通过率作为奖励。 +- 在解码过程中,推理和编码都会采样多个解决方案,然后从解码空间中选择最佳方案。 + +#### 复杂推理的提示工程 + +* 基础思维链提示工程 + +推荐给初学者: + +- Wei et. al. 2022. [Chain-of-Thought Prompting Elicits Reasoning in Large Language Models](https://arxiv.org/abs/2201.11903). + - 本文是第一篇发现当使用链式思维进行提示时,存在一个相变现象,表明大型模型在很大程度上优于较小的模型,这进一步导致了[涌现能力](https://arxiv.org/abs/2206.07682)的发现。 +- Wang et. al. 2022. [Self-Consistency Improves Chain of Thought Reasoning in Language Models](https://arxiv.org/abs/2203.11171) + - 对采样的 CoT 推理路径进行多数投票,显著提高了推理性能。 +- Suzgun et. al. 2022. [Challenging BIG-Bench Tasks and Whether Chain-of-Thought Can Solve Them](https://arxiv.org/abs/2210.09261) + - 使用 CoT 处理 big-bench 中困难的任务。这篇论文的一个有意义的副产品是 BigBench Hard 数据集,它在测试模型推理能力方面非常有效。 + + +* 进阶技巧及分析 + +高级 CoT 提示实践: + +- Fu et. al. 2023. [Complexity-Based Prompting for Multi-Step Reasoning](https://arxiv.org/abs/2210.00720) + - 使用复杂链代替简单链作为上下文示例。 +- Khot et. al. 2023. [Decomposed Prompting: A Modular Approach for Solving Complex Tasks](https://arxiv.org/abs/2210.02406) + - 将复杂任务分解为更简单的任务,然后逐个解决。 + +通常,对于复杂任务,首先将其分解为更简单的任务,然后逐步解决更简单的任务。 + +以下论文讨论了上下文学习为什么起作用: + +- Xie et. al. 2021. [An Explanation of In-context Learning as Implicit Bayesian Inference](https://arxiv.org/abs/2111.02080) + - 语言模型在提示中的示例之间推断出一个潜在概念,并进入相应的任务模式 +- Wei et. al. 2023. [Larger language models do in-context learning differently](https://arxiv.org/abs/2303.03846) + - 当出现与先验知识相矛盾的上下文示例时,尽管大型模型可能具有更强的语义先验,大型模型可以根据提示词来覆盖语义先验。 + +简而言之,上下文学习的要点是提示中的示例使模型进入相应的任务模式,然后执行任务。 + + +以下论文讨论了**模型在进行思维链推理时的行为**: + +- Min et. al. 2022. [Rethinking the Role of Demonstrations: What Makes In-Context Learning Work](https://arxiv.org/abs/2202.12837) + - 当某些标签错误时,模型仍然可以做出正确的预测。这表明模型更受提示的 [格式] 影响,而不是提示的 [意义] 。 +- Wang et. al. 2022. [Towards Understanding Chain-of-Thought Prompting: An Empirical Study of What Matters](https://arxiv.org/abs/2212.10001) + - 即使提示中的推理错误,模型仍然可以正确推理,但提示的相关性和推理步骤的顺序更为重要 —— 这再次表明,模型更受提示的 [格式] 影响,而不是提示的[意义]。 +- Madaan and Yazdanbakhsh. 2022. [Text and Patterns: For Effective Chain of Thought, It Takes Two to Tango](https://arxiv.org/abs/2209.07686). + - 详细分析显示,提示的格式可以改善 CoT 推理(虽然内容的正确性可能不起到强烈作用) + +因此呢,模型只关注提示的格式,但可能不会受到提示正确性的显著影响。然而,模型在多大程度上会受到提示正确性的影响,或者提示可以在[多大程度上覆盖模型的先验信念](https://arxiv.org/abs/2303.03846),还是一个尚待研究的问题。 + +以下论文讨论了如何**通过改进和反馈来提高模型性能**: + +- Madaan. et. al. 2023. [Self-refine: Iterative refinement with self-feedback](https://arxiv.org/abs/2303.17651) + - 模型可以在多个场景中(包括代码优化、数学推理、对话响应生成等)对自身的推理进行优化和改进。 +- Madaan et. al. 2023. [Learning Performance-Improving Code Edits](https://arxiv.org/abs/2302.07867) + - 在程序轨迹上进行训练可以改善编码。 + +因此,以自然语言形式(而非强化学习中的奖励形式)对模型进行改进和反馈非常有效,可以进一步提高语言模型的性能(无论是通过上下文学习还是微调)。 + +#### 评价大语言模型的推理能力 + +#### 评价方法的基础知识 + +在谈论评估时,有三个重要因素需要考虑:数据格式、能力类型和模型类型。 + +首先,提示时有四种数据格式: + +

+ +

+ +其中: + +- In-context 指的是在测试问题之前附加一系列上下文示例。 +- Zero-shot 是指在没有上下文示例的情况下直接将测试问题输入给模型。 +- Chain-of-thought 是指在回答之前生成推理。 +- Answer-only 是指没有链式思维,直接给答案。 + +对于模型能力,有两种大致正交的能力类型: + +- 知识 knowledge:模型是否了解世界 +- 推理 reasoning:模型是否可以根据其知识进行推理。 + +这两个方面并不是严格正交的,因为一些推理规则也可以被视为某种形式的知识。然而,在评估时,这两种能力有明显的差异: + +- 一些数据集更注重对知识的评估,如 [MMLU](https://arxiv.org/abs/2009.03300),它测试模型是否具有高达大学水平的知识。 +- 一些数据集更注重对推理的评估,如 [BBH](https://arxiv.org/abs/2210.09261),它测试模型是否具有逐步解决问题的能力。 +- 对于知识,链式思维与仅回答的表现相似(参见 FlanPaLM 论文)。 +- 对于推理,链式思维比仅回答表现得更好(参见原始 [CoT 论文](https://arxiv.org/abs/2201.11903),然后参见 [FlanPaLM论文](https://arxiv.org/abs/2210.11416) + +在实践中,因为 CoT 在达到或优于 Answer-only 的表现,而且 CoT 更加用户友好(因为它告诉用户思考过程),现代聊天机器人总是部署 CoT(无论你问 ChatGPT 什么,它都会告诉你一堆它的想法)。 + +最后,在评估方面,我们区分了两种类型的模型:预训练之后的 checkpoint 和指令微调之后的 checkpoint。 + +1. 预训练 checkpoint 具有 in-context learning 的能力。大多数预训练模型可以进行 in-context answer-only,一些更好的模型可以进行 in-context chain-of-thought(但目前尚不清楚为什么某些预训练模型可以进行 CoT 而其他模型却不能)。然而,预训练 checkpoint 可能无法进行 zero-shot,因为它们没有经过这方面的训练(但某些预训练检查点仍然可以进行 zero-shot CoT,请参阅 “[让我们逐步思考(https://arxiv.org/abs/2205.11916)” 的论文)。 +2. 指令微调过后的 checkpoint 既具有 zero-shot 又有 in-context 的能力。这里需要注意的是,如果没调好,指令微调之后 in-context 性能可能会[稍有下降](https://arxiv.org/abs/2203.02155)。 + +最后,在评估方面,这里区分了两种类型的模型:预训练之后的 checkpoint 和指令微调之后的 checkpoint。 + +- 预训练 checkpoint 具有 in-context learning 的能力。大多数预训练模型可以进行 in-context answer-only,一些更好的模型可以进行 in-context chain-of-thought(但目前尚不清楚为什么某些预训练模型可以进行 CoT 而其他模型却不能)。然而,预训练 checkpoint 可能无法进行 zero-shot,因为它们没有经过这方面的训练(但某些预训练检查点仍然可以进行 zero-shot CoT,请参阅 “让我们逐步思考” 的论文)。 +- 指令微调过后的 checkpoint 既具有 zero-shot 又有 in-context 的能力。这里需要注意的是,如果没调好,指令微调之后 in-context 性能可能会稍有下降。 + +综上所述,我们建议使用 in-context 和 chain-of-thought 进行评估: + +- In-context 是评估 pretrained checkpoint 的更好方法,因为它更好地揭示了模型潜力。Zero-shot 可能低估模型性能,尤其是对于不支持 Zero-shot chain-of-thought 的(“让我们逐步思考”)的模型。 +- Chain-of-thought prompting 是评估推理能力的更好方法,因为它比 answer-only prompting 更充分地发挥了模型的推理性能。 + +#### Chain-of-thought Hub 简介 + +在讨论了所有评估基础知识之后,这里在介绍 Chain-of-thought Hub,这是一个正在进行的工作,希望成为评估语言模型推理能力的统一平台。他们汇编了一个包括数学(GSM8K)、科学(MATH)、符号(BBH)、知识(MMLU)等复杂推理任务的列表,以衡量哪些模型确实更好。 + +下面是当前的排行榜。尽管许多数字还没跑出来,但当前的内容仍然能给一个大概的模型排名: + +

+ +

+ + +总的来说: + +- 根据 GSM8K 对模型性能进行排名,这是一个经典的基准测试,用于衡量链式思维数学推理性能。这不是唯一的度量标准,但一个很好的解释是 “在保持其他通用能力的同时,模型在数学方面的表现如何” —— 这也非常困难。 +- GPT-4 在 GSM8K 和 MMLU 上明显优于所有其他模型。 +- 65B LLaMA 与 text/code-davinci-002 非常接近,这意味着基于它,如果 SFT 和 RLHF 操作正确,我们很有可能基于 65B LLaMA 复现 ChatGPT。 +- Claude 是唯一可以与 GPT 系列相媲美的模型家族。 +- 较小的模型,如 FlanT5 11B 和 LLaMA 7B,明显落后于排行榜,这意味着复杂推理可能只是大型模型的能力。 + +在 github 中,进一步地分析和了解: + +- 详细的实验设置和结果分析。 +- 用于重现 GPT 和 Claude 所有结果的脚本。 + +因此,在上面我们讨论了大型语言模型的推理能力。复杂推理不仅仅是因为它是更强模型与更弱模型之间的核心区分点,而且它还是模型成为下一代计算平台或者操作系统的基础能力,从而有可能在大模型上建立一个新的生态系统。 + +我们讨论了构建具有强大推理能力的模型的方法:预训练、有监督的微调和强化学习。我们发现提高推理能力的方法与提高代码能力的方法密切相关,这加深了我们先前关于推理与代码之间密切关系的假设。我们进一步讨论了高级提示工程技巧和在执行复杂推理时模型行为的分析。 + +最后,我们讨论了如何评估模型的推理能力,并介绍了 chain-of-thought hub,这是一个正在进行的项目,旨在统一评估语言模型的推理性能。 + +希望这篇文章能成为构建具有强大推理能力的开源模型的路线图。 + + +人世间数百万个闲暇的小时流逝过去,方始出现一个真正的历史性时刻,人类星光闪耀的时刻 —— 《人类群星闪耀时》斯蒂芬·茨威格 + + +#### 更多大语言模型推理的相关资源 + +* [Prompt Engineering](https://lilianweng.github.io/posts/2023-03-15-prompt-engineering/) +* [Microsoft Semantic Kernel ](https://github.com/microsoft/semantic-kernel) +* [Prompt Engineering Guide](https://github.com/dair-ai/Prompt-Engineering-Guide) +* [Towards Reasoning in Large Language Models: A Survey](https://arxiv.org/abs/2212.10403) \ No newline at end of file diff --git a/assets/src/LLM/llm02.md b/assets/src/LLM/llm02.md new file mode 100644 index 00000000..ea675909 --- /dev/null +++ b/assets/src/LLM/llm02.md @@ -0,0 +1,55 @@ +#### 什么是大型语言模型? + +大型语言模型(LLM)是基于大量数据进行预训练的超大型深度学习模型。底层转换器是一组神经网络,这些神经网络由具有自注意力功能的编码器和解码器组成。编码器和解码器从一系列文本中提取含义,并理解其中的单词和短语之间的关系。 + +转换器 LLM 能够进行无监督的训练,但更精确的解释是转换器可以执行自主学习。通过此过程,转换器可学会理解基本的语法、语言和知识。 + +与早期按顺序处理输入的循环神经网络(RNN)不同,转换器并行处理整个序列。这可让数据科学家使用 GPU 训练基于转换器的 LLM,从而大幅度缩短训练时间。 + +借助转换器神经网络架构,您可使用非常大规模的模型,其中通常具有数千亿个参数。这种大规模模型可以摄取通常来自互联网的大量数据,但也可以从包含 500 多亿个网页的 Common Crawl 和拥有约 5700 万个页面的 Wikipedia 等来源摄取数据。 + +#### 大语言模型综述 + +语言是人类表达和交流的突出能力,它在儿童早期发展 并在一生中不断演变。然而,机器不能自然地掌握以人类语言形式理解和交流的能力,除非配备了强大的人工智能算法。实现这一目标,让机器像人类一样阅读、写作和交流一直是一个长期的研究挑战。 + +从技术上讲,语言建模是提高机器语言智能的主要方法之一。一般来说,语言建模旨在对词序列的生成概率进行建模,以预测未来(或缺失)单词的概率。语言建模的研究在文献中受到了广泛关注,可以分为四个主要发展阶段: + +1. 统计语言模型 (SLM) + +SLMs 基于统计学习方法 开发,并在 20 世纪 90 年代兴起。其基本思想是基于马尔可夫 假设建立词预测模型,例如根据最近的上下文预测下一个词。 +具有固定上下文长度 n 的 SLM 也称为 n-gram 语言模型,例 如 bigram 和 trigram 语言模型。SLM 已被广泛应用于提高信 息检索和自然语言处理的任务性能。然而,它们通常受到维数灾难的困扰:由于需要估计指数级数量的转 换概率,因此很难准确估计高阶语言模型。因此,专门设计的平滑策略,如回退估计和 Good–Turing 估计已被引入以缓解数据稀疏问题。 + +2. 神经语言模型(NLM) + +使用神经网络(例 如循环神经网络)来刻画词序列的概率。作为一个显著贡献,的工作引入了词的分布式表示概念,并在聚合上下文特征(即分布式词向量)的条件下构建词预测函数。通过扩展学习词或句子有效特征的想法,已有研究开发了一种通用神经 + +此外,word2vec被提出来构建一个简化的浅层神经网用于学习分布式词表示,这些表示在各种自然语言处理任务中被证明非常有效。这些研究开创了将语言模型用于表示学习(超越词序列建模),对自然语言处理领域产生了重要影响。 + +3. 预训练语言模型 (PLM) + +作为早期尝试,ELMo被提出来通过预训练一个双向 LSTM(biLSTM)网络(而不是 学习固定的词表示)来捕捉上下文感知的词表示,然后根据特定的下游任务微调 biLSTM 网络。进一步,基于自注意力机制的高度并行化 Transformer 架构,BERT作为双向语言模型,在大规模无标签语料库上使用专门设计的预训练任务。 + +这些预训练的上下文感知词表示作为通用语义特征非常有效,极大地提高了自然语言处理任务的性能。这项研究激发了大量后续工作,确立了“预训练和微调”学习范式。 +遵循这一范式,已经建立了大量关于预训练语言模型的研究引入了不同的架构(例如 GPT-2和 BART),或者改进的预训练策略。在这个范式中,通常需要对预训练语言模型进行微调以适应不同的下游任务。 + + +4. 大语言模型 (LLM) + +研究人员发现,扩展预训练语言模型(例如扩展模型大小或数据大小)通常会提高下游任务的模型容量(即遵循扩展定律)。许多研究通过训练越来越大的 PLM(例如 175B 参数的 GPT-3 和 540B 参数的 PaLM)来探索性能极限。尽管扩展主要在模型大小方面进行(具有类似的架构和预训练任务),但这些大尺寸的预训练语言模型表现出与较小的预训练语言模型(如 330M 参数的 BERT和 1.5B 参数的 GPT-2)不同的行为, +并在解决一系列复杂任务中展示了惊人的能力(称为涌现能力)。例如,GPT-3 可以通过上下文学习解决少样本任务,而 GPT-2 则表现不佳。因此,研究界为这些大型预训练语言模型命名为“大语言模型 (LLM)”1。LLM 的一个显著应用是 ChatGPT2,它将 GPT 系列的 LLM 应用于对话,展现了惊人的与人类对话的能力。 + +在现有文献中,PLM 已经得到了广泛的讨论和调研,而很少有研究对 LLM 以系统的方式进行回顾。为了激发我们的调研,我们首先强调 LLM 和 PLM 之间的三个主要区别。首先,LLM 表现出一些令人惊讶的涌现能力,这些能力可能在以前较小的 PLM 中没有观察到。这些能力是语言模型 可能在以前较小的 PLM 中没有观察到。这些能力是语言模型 的强大和有效性。其次,LLM 将彻底改变人类开发和使用人 工智能算法的方式。与小型 PLM 不同,访问 LLM 的主要方法是通过提示接口(例如 GPT-4 API)。 +人们必须了解 LLM的工作原理,并以 LLM 能够遵循的方式形式化他们的任务。第三,LLM 的发展不再明确区分研究和工程。训练 LLM 需要在大规模数据处理和分布式并行训练方面具有丰富的实践经验。为了开发出有能力的 LLM,研究人员必须解决复杂的工程问题,与工程师合作或成为工程师。 + + +如今,LLM 对 AI 社区产生了重大影响,ChatGPT 和GPT-4 的出现促使人们重新思考通用人工智能(AGI)的可能性。OpenAI 已经发布了一篇名为“Planning for AGI and beyond”的技术文章,讨论了实现 AGI 的短期和长期计划而一篇更近期的论文认为 GPT-4 可能被视为 AGI 系统的早期版本。AI 研究领域正因 LLM 的迅速发展而发生革命性变革。在自然语言处理领域,LLM 可以在一定程度上作为通用语言任务解决器,其研究范式已经转向使用 LLM。 +在信 息检索领域,传统搜索引擎正受到通过 AI 聊天机器人(即ChatGPT)搜索新信息的挑战,而 New Bing3展示了一个初步的基于 LLM 增强搜索结果的研究尝试。在计算机视觉领域,研究人员试图开发类似 ChatGPT 的视觉-语言模型,以更好地为多模态对话提供服务GPT-4已经通过整合视觉信息支持多模态输入。这一新技术浪潮可能会带来 例如GPT-3、PaLM、Galactica和LLaMA。 + + +具体而言,LLM 基于 Transformer 架构构建,其中多头注意力层堆叠在非常深的神经网络中。现有的 LLM 主要采用与小语言模型类似的模型架构(即 Transformer)和预训练目标(即语言建模)。作为主要区别,LLM 大幅扩展了模型大小、预训练数据和总计算量(若干数量级),可以更好地根据上下文(即提示)理解自然语言并生成高质量的文本。这一能力提升可以部分通过扩展定律来描述,即任务性能大致随着模型大小的增加而显著提高然而,一些能力(例如上下文学习)是不可预测的,只有当模型大小超过一定水平时才能观察到。 + +大语言模型的涌现能力: 在文献中,LLM 的“涌现能力”被正式定义为“在小模型中不存在但在大模型中出现的能力”,这是区分 LLM 与以前的 PLM 最突出的特征之一。它进一步介绍了一个显著的特征,即当规模达到一定水平时,性能显著提高超过随机水平。类比地,这种涌现模式与物理学中的相变”现象有着密切的联系。原则上,涌现能力可以定义为与某些复杂任务相关的能力,而我们更关注能够应用于解决各种任务的通用能力。这里,我们简要介绍三个代表性的 LLM 涌现能力。 + +* 上下文学习:上下文学习能力由 GPT-3 正式引入,假设提供给语言模型自然语言指令和/或多个任务演示,它可以通过完成输入文本的单词序列来为测试实例生成期望的输出,而无需额外的训练或梯度更新。 +* 指令遵循:通过使用自然语言描述的多任务数据集进行微调(称为指令微调),LLM 可以在同样使用指令形式化描述的未见任务上表现良好。通过指令微调,LLM 能够在没有使用显式示例的情况下遵循任务指令,从而具有更好的泛化能力。 +* 逐步推理:对于小语言模型来说,通常难以解决涉及多个推理步骤的复杂任务,例如数学问题。然而,通过采用“思维链”推理策略,LLM 可以利用包含中间推理步骤的提示机制来解决这些任务,得出最终答案。这种能力被认为可能通过在代码上进行训练来获得。 \ No newline at end of file diff --git a/assets/src/OTR/OTR.md b/assets/src/OTR/OTR.md index 35606c69..47213017 100644 --- a/assets/src/OTR/OTR.md +++ b/assets/src/OTR/OTR.md @@ -1,4 +1,5 @@ ### Deeplearning Algorithms tutorial + 谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! AI的开发离不开算法那我们就接下来开始学习算法吧! @@ -10,7 +11,7 @@ AI的开发离不开算法那我们就接下来开始学习算法吧! 机器学习主要有三种方式:监督学习,无监督学习与半监督学习。 -(1)监督学习:从给定的训练数据集中学习出一个函数,当新的数据输入时,可以根据函数预测相应的结果。监督学习的训练集要求是包括输入和输出,也就是特征和目标。训练集中的目标是有标注的。如今机器学习已固有的监督学习算法有可以进行分类的,例如贝叶斯分类,SVM,ID3,C4.5以及分类决策树,以及现在最火热的人工神经网络,例如BP神经网络,RBF神经网络,Hopfield神经网络、深度信念网络和卷积神经网络等。人工神经网络是模拟人大脑的思考方式来进行分析,在人工神经网络中有显层,隐层以及输出层,而每一层都会有神经元,神经元的状态或开启或关闭,这取决于大数据。同样监督机器学习算法也可以作回归,最常用便是逻辑回归。 +(1)监督学习:从给定的训练数据集中学习出一个函数,当新的数据输入时,可以根据函数预测相应的结果。监督学习的训练集要求是包括输入和输出,也就是特征和目标。训练集中的目标是有标注的。如今机器学习已固有的监督学习算法有可以进行分类的,例如贝叶斯分类,`SVM`,ID3,`C4.5` 以及分类决策树,以及现在最火热的人工神经网络,例如BP神经网络,RBF神经网络,Hopfield神经网络、深度信念网络和卷积神经网络等。人工神经网络是模拟人大脑的思考方式来进行分析,在人工神经网络中有显层,隐层以及输出层,而每一层都会有神经元,神经元的状态或开启或关闭,这取决于大数据。同样监督机器学习算法也可以作回归,最常用便是逻辑回归。 (2)无监督学习:与有监督学习相比,无监督学习的训练集的类标号是未知的,并且要学习的类的个数或集合可能事先不知道。常见的无监督学习算法包括聚类和关联,例如K均值法、Apriori算法。 @@ -27,6 +28,7 @@ AI的开发离不开算法那我们就接下来开始学习算法吧! Hawkins(1980)给出孤立点(outlier)的定义:孤立点是在数据集中与众不同的数据,使人怀疑这些数据并非随机孤立点,而是产生于完全不同的机制。孤立点可能在聚集运行或者检测的时候被发现,比如一个人的年龄是999,这在对数据库进行检测的时候就会被发现。还有就是outlier可能是本身就固有的,而不是一个错误,比如CEO的工资就比一般员工的工资高出很多。 2.算法原理 +

@@ -34,20 +36,24 @@ Hawkins(1980)给出孤立点(outlier)的定义:孤立点是在数据集中 孤立点的挖掘方法主要有:基于统计学的、基于距离的、基于密度的局部离群点方法和基于深度偏差的方法。 马克威孤立点算法是基于距离的:设表示p点和它的第k个最近邻居的距离。直观地看,越大,p越有可能成为孤立点。 + 给定d维空间中包含N个点的数据集、参数N(孤立点个数)和k(偏差距离),如果满足的点不超过n-1个,那么称p为孤立点。 + 如果对所有数据点根据其距离进行从大到小排序,那么前n个点就被看作是孤立点。 算法步骤如下,对每个p点,计算它的第k个最近邻居的距离,把具有极大值的前个n点作为孤立点。该算法每次处理一个点p,就需要扫描一遍数据库,总共需要扫描N遍(N为数据点数)。 #### 算法应用 + 孤立点分析被广泛地应用于各种行业,如电信和信用卡欺骗(如检查购买金额或购买次数异常等)、贷款审批、药物研究(如用于发现对多种治疗方式的不寻常的反应)、气象预报、金融领域(如检查洗钱等异常行为)、客户分类(如确定极低或极高收入的客户的消费行为)、网络入侵检测等。 #### 相关应用 + 聚类分析、异常监测、异常欺诈、行为异常 #### 优点和缺点 + 优点:应用领域广泛,对异常检测、极端情况的事件发生尤其有用。 缺点:孤立点分析时,有时候得到的结果并不是我们想要的,是数据本身固有的一种属性,如总经理的工资待遇比员工高很多;在时间序列中寻找孤立点时,难度比较大,因为时间序列的数据可能隐藏在趋势、季节性或者其他循环规则变化中。对非整型的数值型数据,孤立点定义及分析需要特殊考虑。 - diff --git a/assets/src/RAM/RAM.0.1.md b/assets/src/RAM/RAM.0.1.md new file mode 100644 index 00000000..1d1d0311 --- /dev/null +++ b/assets/src/RAM/RAM.0.1.md @@ -0,0 +1,32 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 回归算法 + +回归方法是对数值型连续随机变量进行预测和建模的监督学习算法。其特点是标注的数据集具有数值型的目标变量。回归的目的是预测数值型的目标值。 +最直接的办法是依据输入写出一个目标值的计算公式,该公式就是所谓的回归方程(regression equation)。求回归方程中的回归系数的过程就是回归。 + +常用的回归方法包括: +* 线性回归:使用超平面拟合数据集 +* 最近邻算法:通过搜寻最相似的训练样本来预测新样本的值 +* 决策树和回归树:将数据集分割为不同分支而实现分层学习 +* 集成方法:组合多个弱学习算法构造一种强学习算法,如随机森林(RF)和梯度提升树(GBM)等 +* 深度学习:使用多层神经网络学习复杂模型 + + +#### 如何应用 + +* 收集数据:可以使用任何方法。 +* 准备数据:回归需要数值型数据,标称型数据将被转换成二值型数据。 +* 分析数据:绘出数据的可视化二维图将有助于对数据做出理解和分析,在采用缩减法求得新回归系数之后,可以将新拟合线绘在图上作为对比。 +* 训练算法:找到回归系数。 +* 测试算法:使用 R2 或者预测值和数据的拟合度,来分析模型的效果。 +* 使用算法:使用回归,可以在给定输入的时候预测出一个数值,这是对分类方法的提升,因为这样可以预测连续型数据而不仅仅是离散的类别标签。 + + +#### 优缺点 + +* 优点:结果容易理解,计算上不复杂。 +* 缺点:对非线性的数据拟合不好。 +* 适用数据范围:数值型和标称型。 \ No newline at end of file diff --git a/assets/src/RAM/RAM.0.2.md b/assets/src/RAM/RAM.0.2.md new file mode 100644 index 00000000..66416a4a --- /dev/null +++ b/assets/src/RAM/RAM.0.2.md @@ -0,0 +1,383 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! +回归方法是对数值型连续随机变量进行预测和建模的监督学习算法。其特点是标注的数据集具有数值型的目标变量。回归的目的是预测数值型的目标值。 + + +常用的回归方法包括: +* 线性回归:使用超平面拟合数据集 +* 最近邻算法:通过搜寻最相似的训练样本来预测新样本的值 +* 决策树和回归树:将数据集分割为不同分支而实现分层学习 +* 集成方法:组合多个弱学习算法构造一种强学习算法,如随机森林(RF)和梯度提升树(GBM)等 +* 深度学习:使用多层神经网络学习复杂模型 + +#### 线性回归 + +线性回归是最简单的回归方法,它的目标是使用超平面拟合数据集,即学习一个线性模型以尽可能准确的预测实值输出标记。 +线性回归是利用数理统计中回归分析,来确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法,运用十分广泛。其表达形式为y = w'x+e,e为误差服从均值为0的正态分布。 +回归分析中,只包括一个自变量和一个因变量,且二者的关系可用一条直线近似表示,这种回归分析称为一元线性回归分析。如果回归分析中包括两个或两个以上的自变量,且因变量和自变量之间是线性关系,则称为多元线性回归分析。 + +#### 单变量模型 +模型 +

+ +

+线性模型(linear model) +简单, 易于建模, 但却蕴含着机器学习的重要思想.由于w直观地表达了各属性在预测中的重要性, 所以线性模型有着很好的可解释性(comprehensibility). + +目标函数(最小二乘参数估计) +

+ +

+ +#### 多变量模型 + +多变量时可以表示为矩阵 +

+ +

+ +目标函数为 +

+ +

+ +当$X^TX$为满秩矩阵时,可以得到最优解 +

+ +

+ +注意: + + 1.多变量时需要对输入数据作归一化,如 + + 2.实际计算过程中(如使用梯度下降算法)学习率的选择方法 + * 收敛慢时,增大学习率 + * 不收敛时,减小学习率 + * 学习率的选择范围一般为..., 0.001, 0.01, 0.1, 1, 10, ... + + + +#### 代码例子 + +```python + #Indicate the matplotlib to show the graphics inline + %matplotlib inline + import matplotlib.pyplot as plt # import matplotlib + import numpy as np # import numpy + import tensorflow as tf + import numpy as np + + trX = np.linspace(-1, 1, 101) #Create a linear space of 101 points between 1 and 1 + trY = 2 * trX + np.random.randn(*trX.shape) * 0.4 + 0.2 #Create The y function based on the x axis + plt.figure() # Create a new figure + plt.scatter(trX,trY) #Plot a scatter draw of the random datapoints + plt.plot (trX, .2 + 2 * trX) # Draw one line with the line function +``` + +

+ +

+ +#### 单变量示例 +

+ +

+ +```python +#!/usr/bin/env python +# h(X)= b + wX +%matplotlib inline +import tensorflow as tf +import numpy as np +import matplotlib.pyplot as plt + +def model(X, w, b): + return tf.mul(X, w) + b + +trX = np.linspace(-1, 1, 101).astype(np.float32) +# create a y value which is approximately linear but with some random noise +trY = 2 * trX + np.random.randn(*trX.shape) * 0.33 + 10 + +# create a shared variable (like theano.shared) for the weight matrix +w = tf.Variable(tf.random_uniform([1], -1.0, 1.0)) +b = tf.Variable(tf.zeros([1])) +cost = tf.reduce_mean(tf.square(trY-model(trX, w, b))) + +# construct an optimizer to minimize cost and fit line to my data +train_op = tf.train.GradientDescentOptimizer(0.01).minimize(cost) + +# Launch the graph in a session +with tf.Session() as sess: + # you need to initialize variables (in this case just variable W) + tf.initialize_all_variables().run() + + for i in range(1000): + sess.run(train_op) + + print "w should be something around [2]: ", sess.run(w) + print "b should be something around [10]:", sess.run(b) + + plt.plot(trX, trY, "ro", label="Orinal data") + plt.plot(trX, w.eval()*trX + b.eval(), label="Fitted line") + plt.legend() + plt.show() + + # Plot with pandas + #import pandas as pd + #fig, axes = plt.subplots(nrows=1, ncols=1) + #pd.DataFrame({'x':trX,'y':trY}).plot.scatter(x='x', y='y', ax=axes, color='red') + #pd.DataFrame({'x':trX,'y':w.eval()*trX + b.eval()}).plot.scatter(x='x', y='y', ax=axes, color='blue') +``` + +```python + w should be something around [2]: [ 2.00981951] + b should be something around [10]: [ 9.98865509] +``` + +

+ +

+ +#### 多变量示例 +多变量其实就是输入变成了矩阵: + +```python +#!/usr/bin/env python +# h(X)= B + WX +%matplotlib inline +import tensorflow as tf +import numpy as np +import matplotlib.pyplot as plt + +def model(X, w, b): + return tf.mul(w, X) + b + +trX = np.mgrid[-1:1:0.01, -10:10:0.1].reshape(2, -1).T +trW = np.array([3, 5]) +trY = trW*trX + np.random.randn(*trX.shape) + [20, 100] + +w = tf.Variable(np.array([1., 1.]).astype(np.float32)) +b = tf.Variable(np.array([[1., 1.]]).astype(np.float32)) +cost = tf.reduce_mean(tf.square(trY-model(trX, w, b))) + +# construct an optimizer to minimize cost and fit line to my data +train_op = tf.train.GradientDescentOptimizer(0.05).minimize(cost) + +# Launch the graph in a session +with tf.Session() as sess: + # you need to initialize variables (in this case just variable W) + tf.initialize_all_variables().run() + + for i in range(1000): + if i % 99 == 0: + print "Cost at step", i, "is:", cost.eval() + sess.run(train_op) + +print "w should be something around [3, 5]: ", sess.run(w) +print "b should be something around [20,100]:", sess.run(b) +Cost at step 0 is: 5329.87 +Cost at step 99 is: 1.22204 +Cost at step 198 is: 0.998043 +Cost at step 297 is: 0.997083 +Cost at step 396 is: 0.997049 +Cost at step 495 is: 0.997049 +Cost at step 594 is: 0.997049 +Cost at step 693 is: 0.997049 +Cost at step 792 is: 0.997049 +Cost at step 891 is: 0.997049 +Cost at step 990 is: 0.997049 +w should be something around [3, 5]: [ 3.00108743 5.00054932] +b should be something around [20,100]: [[ 20.00317383 100.00382233]] +tensorflow示例 +import tensorflow as tf + +# initialize variables/model parameters +W = tf.Variable(tf.zeros([2, 1]), name="weights") +b = tf.Variable(0., name="bias") + +def inference(X): + # compute inference model over data X and return the result + return tf.matmul(X, W) + b + +def loss(X, Y): + # compute loss over training data X and expected outputs Y + Y_predicted = inference(X) + return tf.reduce_sum(tf.squared_difference(Y, Y_predicted)) + +def inputs(): + # read/generate input training data X and expected outputs Y + weight_age = [[84, 46], [73, 20], [65, 52], [70, 30], [76, 57], [69, 25], [63, 28], [72, 36], [79, 57], [75, 44], [27, 24], [89, 31], [65, 52], [57, 23], [59, 60], [69, 48], [60, 34], [79, 51], [75, 50], [82, 34], [59, 46], [67, 23], [85, 37], [55, 40], [63, 30]] + blood_fat_content = [354, 190, 405, 263, 451, 302, 288, 385, 402, 365, 209, 290, 346, 254, 395, 434, 220, 374, 308, 220, 311, 181, 274, 303, 244] + + return tf.to_float(weight_age), tf.to_float(blood_fat_content) + +def train(total_loss): + # train / adjust model parameters according to computed total loss + learning_rate = 0.000001 + return tf.train.GradientDescentOptimizer(learning_rate).minimize(total_loss) + + +def evaluate(sess, X, Y): + # evaluate the resulting trained model + print sess.run(inference([[80., 25.]])) # ~ 303 + print sess.run(inference([[65., 25.]])) # ~ 256 + +# Create a saver. +# saver = tf.train.Saver() + +# Launch the graph in a session, setup boilerplate +with tf.Session() as sess: + tf.initialize_all_variables().run() + + X, Y = inputs() + + total_loss = loss(X, Y) + train_op = train(total_loss) + + coord = tf.train.Coordinator() + threads = tf.train.start_queue_runners(sess=sess, coord=coord) + + # actual training loop + training_steps = 1000 + for step in range(training_steps): + sess.run([train_op]) + # for debugging and learning purposes, see how the loss gets decremented + # through training steps + if step % 10 == 0: + print "loss at step ", step, ":", sess.run([total_loss]) + # save training checkpoints in case loosing them + # if step % 1000 == 0: + # saver.save(sess, 'my-model', global_step=step) + + evaluate(sess, X, Y) + coord.request_stop() + coord.join(threads) + # saver.save(sess, 'my-model', global_step=training_steps) +``` +#### 输出: + + +```python +loss at step 0 : [54929292.0] +loss at step 10 : [14629748.0] +loss at step 20 : [7090800.0] +loss at step 30 : [5680201.0] +loss at step 40 : [5416011.0] +loss at step 50 : [5366280.5] +loss at step 60 : [5356678.0] +loss at step 70 : [5354588.0] +loss at step 80 : [5353913.0] +loss at step 90 : [5353510.0] +loss at step 100 : [5353166.0] +loss at step 110 : [5352839.5] +loss at step 120 : [5352525.0] +loss at step 130 : [5352218.5] +loss at step 140 : [5351921.0] +loss at step 150 : [5351631.5] +loss at step 160 : [5351349.0] +loss at step 170 : [5351075.0] +loss at step 180 : [5350808.0] +loss at step 190 : [5350549.5] +loss at step 200 : [5350297.0] +loss at step 210 : [5350050.5] +loss at step 220 : [5349814.0] +loss at step 230 : [5349580.5] +loss at step 240 : [5349356.0] +loss at step 250 : [5349134.0] +loss at step 260 : [5348922.0] +loss at step 270 : [5348712.5] +loss at step 280 : [5348511.5] +loss at step 290 : [5348313.5] +loss at step 300 : [5348123.5] +loss at step 310 : [5347935.0] +loss at step 320 : [5347753.5] +loss at step 330 : [5347577.5] +loss at step 340 : [5347405.0] +loss at step 350 : [5347237.0] +loss at step 360 : [5347073.0] +loss at step 370 : [5346915.0] +loss at step 380 : [5346761.0] +loss at step 390 : [5346611.0] +loss at step 400 : [5346464.5] +loss at step 410 : [5346320.5] +loss at step 420 : [5346182.5] +loss at step 430 : [5346047.5] +loss at step 440 : [5345914.0] +loss at step 450 : [5345786.0] +loss at step 460 : [5345662.0] +loss at step 470 : [5345539.5] +loss at step 480 : [5345420.5] +loss at step 490 : [5345305.5] +loss at step 500 : [5345193.0] +loss at step 510 : [5345082.5] +loss at step 520 : [5344976.5] +loss at step 530 : [5344871.0] +loss at step 540 : [5344771.0] +loss at step 550 : [5344670.5] +loss at step 560 : [5344574.5] +loss at step 570 : [5344480.5] +loss at step 580 : [5344388.0] +loss at step 590 : [5344298.0] +loss at step 600 : [5344212.0] +loss at step 610 : [5344127.0] +loss at step 620 : [5344042.5] +loss at step 630 : [5343962.0] +loss at step 640 : [5343882.0] +loss at step 650 : [5343805.5] +loss at step 660 : [5343729.5] +loss at step 670 : [5343657.0] +loss at step 680 : [5343584.0] +loss at step 690 : [5343514.5] +loss at step 700 : [5343446.5] +loss at step 710 : [5343380.0] +loss at step 720 : [5343314.5] +loss at step 730 : [5343250.0] +loss at step 740 : [5343187.5] +loss at step 750 : [5343128.0] +loss at step 760 : [5343067.5] +loss at step 770 : [5343010.5] +loss at step 780 : [5342952.5] +loss at step 790 : [5342897.5] +loss at step 800 : [5342843.0] +loss at step 810 : [5342791.5] +loss at step 820 : [5342738.5] +loss at step 830 : [5342688.5] +loss at step 840 : [5342638.5] +loss at step 850 : [5342589.5] +loss at step 860 : [5342543.0] +loss at step 870 : [5342496.5] +loss at step 880 : [5342449.5] +loss at step 890 : [5342406.0] +loss at step 900 : [5342363.0] +loss at step 910 : [5342319.5] +loss at step 920 : [5342277.5] +loss at step 930 : [5342236.0] +loss at step 940 : [5342197.5] +loss at step 950 : [5342157.0] +loss at step 960 : [5342118.5] +loss at step 970 : [5342080.5] +loss at step 980 : [5342043.0] +loss at step 990 : [5342007.5] +[[ 318.77984619]] +[[ 266.52853394]] +``` + + +#### sklearn示例 + +```python +import tensorflow.contrib.learn.python.learn as learn +from sklearn import datasets, metrics, preprocessing + +boston = datasets.load_boston() +x = preprocessing.StandardScaler().fit_transform(boston.data) +feature_columns = learn.infer_real_valued_columns_from_input(x) +regressor = learn.LinearRegressor(feature_columns=feature_columns) +regressor.fit(x, boston.target, steps=200, batch_size=32) +boston_predictions = list(regressor.predict(x, as_iterable=True)) +score = metrics.mean_squared_error(boston_predictions, boston.target) +print ("MSE: %f" % score) +``` + + diff --git a/assets/src/RAM/RAM.0.3.md b/assets/src/RAM/RAM.0.3.md new file mode 100644 index 00000000..649fc75c --- /dev/null +++ b/assets/src/RAM/RAM.0.3.md @@ -0,0 +1,341 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! +回归方法是对数值型连续随机变量进行预测和建模的监督学习算法。其特点是标注的数据集具有数值型的目标变量。回归的目的是预测数值型的目标值。 + +常用的回归方法包括: +* 线性回归:使用超平面拟合数据集 +* 最近邻算法:通过搜寻最相似的训练样本来预测新样本的值 +* 决策树和回归树:将数据集分割为不同分支而实现分层学习 +* 集成方法:组合多个弱学习算法构造一种强学习算法,如随机森林(RF)和梯度提升树(GBM)等 +* 深度学习:使用多层神经网络学习复杂模型 + +#### 逻辑回归 + +逻辑回归对应线性回归,但旨在解决分类问题,即将模型的输出转换为0/1值。逻辑回归直接对分类的可能性进行建模,无需事先假设数据的分布。 + +最理想的转换函数是单位阶跃函数(也称Heaviside函数),但单位阶跃函数是不连续的,没法在实际计算中使用。故而,在分类过程中更常使用对数几率函数(即sigmoid函数): + +

+ +

+ +这样,模型就变成了 +

+ +

+ +如果将$y$看作是样本$x$作为正例的可能性,那么可以得到反应$x$作为正例的相对可能性对数几率(logit) +

+ +

+ +#### 逻辑回归算法 + +可以使用极大似然估计法来估计参数$w$和$b$ + +假设,似然函数为,那么对数似然函数为, + +然后就可以使用梯度下降算法、牛顿法或者BFGS等拟牛顿法来求解了。 + + +#### 正则化 + +在模型过于复杂的情况下,模型会学习到很多特征,从而导致可能把所有训练样本都拟合到,这样就导致了过拟合。解决过拟合可以从两个方面入手,一是减少模型复杂度,一是增加训练集个数。而正则化就是减少模型复杂度的一个方法。 + +一般是在目标函数(经验风险)中加上一个正则化项,即 + + +而这个正则化项一般会采用L1范数或者L2范数。其形式分别为: + + +#### 类别不均衡问题 + +类别不均衡是指分类任务中不同类别的训练样例数目差别很大的情况。解决这类问题的基本思路是“再缩放(rescaling)”,即令 + + 其中,$m^-$为反例数目,$m^+$为正例数目) + +然而,这个方法的实际操作却很难。实际使用上通常使用的方法: + +* 欠采样:去除一些样例使得不同类别的训练样例数目平衡。注意随机丢弃样例可能会导致丢失一些重要信息。 +* 过采样:增加一些样例使得不同类别的训练样例数目平衡。注意不能简单对原样本重复采样,否则会导致严重的过拟合 +* 直接基于原始训练集进行学习,但在使用最终模型预测时使用再缩放(也称为阈值移动) + + +#### 示例代码 + +```python + +import os +import tensorflow as tf + +# initialize variables/model parameters +W = tf.Variable(tf.zeros([5, 1]), name="weights") +b = tf.Variable(0., name="bias") + +def read_csv(batch_size, file_name, record_defaults): + filename_queue = tf.train.string_input_producer( + [os.path.dirname(__file__) + "/" + file_name]) + + reader = tf.TextLineReader(skip_header_lines=1) + key, value = reader.read(filename_queue) + + # decode_csv will convert a Tensor from type string (the text line) in + # a tuple of tensor columns with the specified defaults, which also + # sets the data type for each column + decoded = tf.decode_csv(value, record_defaults=record_defaults) + + # batch actually reads the file and loads "batch_size" rows in a single + # tensor + return tf.train.shuffle_batch(decoded, + batch_size=batch_size, + capacity=batch_size * 50, + min_after_dequeue=batch_size) + +def inference(X): + # compute inference model over data X and return the result + return tf.sigmoid(tf.matmul(X, W) + b) + +def loss(X, Y): + # compute loss over training data X and expected outputs Y + return tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits( + tf.matmul(X, W) + b, Y)) + +def inputs(): + # data is downloaded from https://www.kaggle.com/c/titanic/data. + passenger_id, survived, pclass, name, sex, age, sibsp, parch, ticket, fare,\ + cabin, embarked = read_csv(100, + "train.csv", + [[0.0], [0.0], [0], [""], + [""], [0.0], [0.0], [0.0], + [""], [0.0], [""], [""]]) + + # convert categorical data + is_first_class = tf.to_float(tf.equal(pclass, [1])) + is_second_class = tf.to_float(tf.equal(pclass, [2])) + is_third_class = tf.to_float(tf.equal(pclass, [3])) + gender = tf.to_float(tf.equal(sex, ["female"])) + + # Finally we pack all the features in a single matrix; + # We then transpose to have a matrix with one example per row and one + # feature per column. + features = tf.transpose( + tf.pack([is_first_class, + is_second_class, + is_third_class, + gender, + age])) + survived = tf.reshape(survived, [100, 1]) + + return features, survived + + +def train(total_loss): + # train / adjust model parameters according to computed total loss + learning_rate = 0.01 + return tf.train.GradientDescentOptimizer(learning_rate).minimize( + total_loss) + + +def evaluate(sess, X, Y): + # evaluate the resulting trained model + predicted = tf.cast(inference(X) > 0.5, tf.float32) + + print sess.run(tf.reduce_mean(tf.cast(tf.equal(predicted, Y), tf.float32))) + +# Create a saver. +# saver = tf.train.Saver() + +# Launch the graph in a session, setup boilerplate +with tf.Session() as sess: + tf.initialize_all_variables().run() + + X, Y = inputs() + + total_loss = loss(X, Y) + train_op = train(total_loss) + + coord = tf.train.Coordinator() + threads = tf.train.start_queue_runners(sess=sess, coord=coord) + + # actual training loop + training_steps = 1000 + for step in range(training_steps): + sess.run([train_op]) + # for debugging and learning purposes, see how the loss gets decremented + # through training steps + if step % 100 == 0: + print "loss at step ", step, ":", sess.run([total_loss]) + # save training checkpoints in case loosing them + # if step % 1000 == 0: + # saver.save(sess, 'my-model', global_step=step) + + evaluate(sess, X, Y) + coord.request_stop() + coord.join(threads) + # saver.save(sess, 'my-model', global_step=training_steps) + +``` + + + +```python + +loss at step 0 : [1.0275139] +loss at step 100 : [1.389969] +loss at step 200 : [1.4667224] +loss at step 300 : [0.67178178] +loss at step 400 : [0.568793] +loss at step 500 : [0.48835525] +loss at step 600 : [1.0899736] +loss at step 700 : [0.84278578] +loss at step 800 : [1.0500686] +loss at step 900 : [0.89417559] +0.72 +``` + +#### minst回归示例 + + +```python +import tensorflow as tf +import numpy as np +import input_data + +# Import MINST data +mnist = input_data.read_data_sets("../MNIST_data/", one_hot=True) +Extracting ../MNIST_data/train-images-idx3-ubyte.gz +Extracting ../MNIST_data/train-labels-idx1-ubyte.gz +Extracting ../MNIST_data/t10k-images-idx3-ubyte.gz +Extracting ../MNIST_data/t10k-labels-idx1-ubyte.gz + + +# Parameters +learning_rate = 0.01 +training_epochs = 25 +batch_size = 100 +display_step = 1 + +# tf Graph Input +x = tf.placeholder("float", [None, 784]) # mnist data image of shape 28*28=784 +y = tf.placeholder("float", [None, 10]) # 0-9 digits recognition => 10 classes + +# Create model +def init_weights(shape): + return tf.Variable(tf.random_normal(shape, stddev=0.01)) + +def model(X, w): + return tf.matmul(X, w) + +# like in linear regression, we need a shared variable weight matrix +# for logistic regression +w = init_weights([784, 10]) + +# Construct model +# compute mean cross entropy (softmax is applied internally) +cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(model(x, w), y)) +train_op = tf.train.GradientDescentOptimizer(learning_rate).minimize(cost) # construct optimizer +predict_op = tf.argmax(model(x, w), 1) # at predict time, evaluate the argmax of the logistic regression + +# Launch the graph +with tf.Session() as sess: + tf.initialize_all_variables().run() + + # Training cycle + for epoch in range(training_epochs): + avg_cost = 0. + total_batch = int(mnist.train.num_examples/batch_size) + # Loop over all batches + for i in range(total_batch): + batch_xs, batch_ys = mnist.train.next_batch(batch_size) + # Fit training using batch data + sess.run(train_op, feed_dict={x: batch_xs, y: batch_ys}) + # Compute average loss + avg_cost += sess.run(cost, feed_dict={x: batch_xs, y: batch_ys})/total_batch + # Display logs per epoch step + if epoch % display_step == 0: + print "Epoch:", '%04d' % (epoch+1), "cost=", "{:.9f}".format(avg_cost) + + print "Optimization Finished!" + + # Test model + correct_prediction = tf.equal(predict_op, tf.argmax(y, 1)) + # Calculate accuracy + accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) + print "Accuracy:", accuracy.eval({x: mnist.test.images, y: mnist.test.labels}) + +``` + +```python +Epoch: 0001 cost= 1.181141054 +Epoch: 0002 cost= 0.664358092 +Epoch: 0003 cost= 0.553026987 +Epoch: 0004 cost= 0.499294951 +Epoch: 0005 cost= 0.466518660 +Epoch: 0006 cost= 0.443856266 +Epoch: 0007 cost= 0.427351894 +Epoch: 0008 cost= 0.414347254 +Epoch: 0009 cost= 0.403219846 +Epoch: 0010 cost= 0.394844531 +Epoch: 0011 cost= 0.387121435 +Epoch: 0012 cost= 0.380693078 +Epoch: 0013 cost= 0.375634897 +Epoch: 0014 cost= 0.369904718 +Epoch: 0015 cost= 0.365776612 +Epoch: 0016 cost= 0.361626607 +Epoch: 0017 cost= 0.358361928 +Epoch: 0018 cost= 0.354674878 +Epoch: 0019 cost= 0.351685582 +Epoch: 0020 cost= 0.349124772 +Epoch: 0021 cost= 0.346287186 +Epoch: 0022 cost= 0.344134942 +Epoch: 0023 cost= 0.341778976 +Epoch: 0024 cost= 0.340130984 +Epoch: 0025 cost= 0.337454195 +Optimization Finished! +Accuracy: 0.9122 + +``` + +#### sklearn示例 + +```python +from sklearn import datasets +from sklearn import metrics +import tensorflow as tf +import tensorflow.contrib.layers.python.layers as layers +import tensorflow.contrib.learn.python.learn as learn + +iris = datasets.load_iris() + +def my_model(features, labels): + """DNN with three hidden layers.""" + # Convert the labels to a one-hot tensor of shape (length of features, 3) and + # with a on-value of 1 for each one-hot vector of length 3. + labels = tf.one_hot(labels, 3, 1, 0) + + # Create three fully connected layers respectively of size 10, 20, and 10. + features = layers.stack(features, layers.fully_connected, [10, 20, 10]) + + # Create two tensors respectively for prediction and loss. + prediction, loss = ( + tf.contrib.learn.models.logistic_regression(features, labels) + ) + + # Create a tensor for training op. + train_op = tf.contrib.layers.optimize_loss( + loss, tf.contrib.framework.get_global_step(), optimizer='Adagrad', + learning_rate=0.1) + + return {'class': tf.argmax(prediction, 1), 'prob': prediction}, loss, train_op + +classifier = learn.Estimator(model_fn=my_model) +classifier.fit(iris.data, iris.target, steps=1000) + +y_predicted = [ + p['class'] for p in classifier.predict(iris.data, as_iterable=True)] +score = metrics.accuracy_score(iris.target, y_predicted) +print('Accuracy: {0:f}'.format(score)) +``` + + diff --git a/assets/src/RAM/RAM.0.4.md b/assets/src/RAM/RAM.0.4.md new file mode 100644 index 00000000..2ab6f60d --- /dev/null +++ b/assets/src/RAM/RAM.0.4.md @@ -0,0 +1,25 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! +回归方法是对数值型连续随机变量进行预测和建模的监督学习算法。其特点是标注的数据集具有数值型的目标变量。回归的目的是预测数值型的目标值。 + + +常用的回归方法包括: +* 线性回归:使用超平面拟合数据集 +* 最近邻算法:通过搜寻最相似的训练样本来预测新样本的值 +* 决策树和回归树:将数据集分割为不同分支而实现分层学习 +* 集成方法:组合多个弱学习算法构造一种强学习算法,如随机森林(RF)和梯度提升树(GBM)等 +* 深度学习:使用多层神经网络学习复杂模型 + +#### 多元自适应回归样条 + +多元自适应回归样条(Multivariate Adaptive Regression Splines,MARS)是由美国的统计学家Jerome Friedman于1991年提出的一种数据分析方法。 +该方法以样条函数的张量积作为基函数,分为前向过程、后向剪枝过程与模型选取三个步骤。其优势在于能够处理数据量大、维度高的数据,而且计算快捷、模型精确。 +文章在一般回归分析理论和样条理论的基础上,系统地研究了MARS的建模过程,提出引入Bernstein基函数建模的思想,并针对冶金工业领域一类数据分析其成分优化问题,应用该方法进行建模和预测。 + +在前向过程中,通过自适应的选取节点对数据进行分割,每选取一个节点就生成两个新的基函数,前向过程结束后生成一个过拟合的模型。后向剪枝过程中在保证模型准确度的前提下,删除过拟合模型中对模型贡献度小的基函数,最后选取一个最优的模型作为回归模型。 +研究过程中对采集的原始数据进行了消除负差、剔除异常数据、数据标准化等预处理工作,选取精华样本,分别建立了线性模型、非线性模型、神经网络模型等,并与MARS方法做比较。得到如下结论:由于模型的限制,线性回归模型精度较低,与实际经验不符; +神经网络对部分元素的描述优于线性回归模型,但不能得出相应的显式表达式,同时线性回归与神经网络都未能考虑变量间的交互作用;MARS模型对问题的描述比较符合实际经验,同时能够反映元素间的交互作用,能够对两个变量做可视化处理,并能够给出显式表达式。 +论文以数据科学为背景,属于问题驱动的应用数学研究,不仅对多元自适应回归方法进行了理论探索,也为工业领域的数据分析与优化提供了理论依据。 + +MARS是回归的自适应过程,非常适合高维问题(比如,存在大量的输入)。可以从两个角度来理解它,首先,它可以看成是逐步线性回归的推广,其次,也可以看成是为了提高CART在回归中的效果而进行的改进。我们从第一种观点引入MARS,接着与CART联系起来。 diff --git a/assets/src/RAM/RAM.0.5.md b/assets/src/RAM/RAM.0.5.md new file mode 100644 index 00000000..74285dc5 --- /dev/null +++ b/assets/src/RAM/RAM.0.5.md @@ -0,0 +1,28 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! +回归方法是对数值型连续随机变量进行预测和建模的监督学习算法。其特点是标注的数据集具有数值型的目标变量。回归的目的是预测数值型的目标值。 + + +常用的回归方法包括: +* 线性回归:使用超平面拟合数据集 +* 最近邻算法:通过搜寻最相似的训练样本来预测新样本的值 +* 决策树和回归树:将数据集分割为不同分支而实现分层学习 +* 集成方法:组合多个弱学习算法构造一种强学习算法,如随机森林(RF)和梯度提升树(GBM)等 +* 深度学习:使用多层神经网络学习复杂模型 + +#### 本地散点平滑估计 + +本地散点平滑估计(Locally Estimated Scatterplot Smoothing,LOESS),事先不用确定参数数量,每次预测的时候,用指定的样本点周围的样本点进行临时训练,确定参数。 + + + + + + + +#### 优缺点 + +优点:直接、快速 知名度高。 + +缺点:要求严格的假设,需要处理异常值。 diff --git a/assets/src/RGN/RGN.0.1.md b/assets/src/RGN/RGN.0.1.md new file mode 100644 index 00000000..780a5a16 --- /dev/null +++ b/assets/src/RGN/RGN.0.1.md @@ -0,0 +1,14 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 正则化算法 + +监督机器学习问题就是“minimizeyour error while regularizing your parameters”,在规则化参数的同时最小化误差。最小化误差是为了让我们的模型拟合我们的训练数据,而规则化参数是防止我们的模型过分拟合我们的训练数据。 + +正则化算法包括: + +* 岭回归(Ridge Regression) +* LASSO(Least Absolute Shrinkage and Selection Operator) +* Elastic Net +* 最小角回归(LARS) diff --git a/assets/src/RGN/RGN.0.2.md b/assets/src/RGN/RGN.0.2.md new file mode 100644 index 00000000..74fd1a51 --- /dev/null +++ b/assets/src/RGN/RGN.0.2.md @@ -0,0 +1,107 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### 岭回归(Ridge Regression) + +岭回归(ridge regression, Tikhonov regularization)是一种专用于共线性数据分析的有偏估计回归方法,实质上是一种改良的最小二乘估计法,通过放弃最小二乘法的无偏性,以损失部分信息、降低精度为代价获得回归系数更为符合实际、更可靠的回归方法,对病态数据的拟合要强于最小二乘法。 + +岭回归,又称脊回归、吉洪诺夫正则化(Tikhonov regularization),是对不适定问题(ill-posed problem)进行回归分析时最经常使用的一种正则化方法。 +对于有些矩阵,矩阵中某个元素的一个很小的变动,会引起最后计算结果误差很大,这种矩阵称为“病态矩阵”。有些时候不正确的计算方法也会使一个正常的矩阵在运算中表现出病态。对于高斯消去法来说,如果主元(即对角线上的元素)上的元素很小,在计算时就会表现出病态的特征。 + +岭回归分析核心思想是采用最小二乘法原理来求解回归系数,最小二乘法思想背景:1801年,意大利天文学家朱赛普·皮亚齐发现了第一颗小行星谷神星。经过40天的跟踪观测后,由于谷神星运行至太阳背后,使得皮亚齐失去了谷神星的位置。随后全世界的科学家利用皮亚齐的观测数据开始寻找谷神星,但是根据大多数人计算的结果来寻找谷神星都没有结果。时年24岁的高斯计算了谷神星的轨道并进行了分析。奥地利天文学家海因里希·奥伯斯根据高斯计算出来的轨道重新发现了谷神星。 + +高斯使用的最小二乘法的方法发表于1809年他的著作《天体运动论》中,而法国科学家勒让德于1806年独立发现“最小二乘法”,但因不为世人所知而默默无闻。两人曾为谁最早创立最小二乘法原理发生争执。 + +1829年,高斯提供了最小二乘法的优化效果强于其他方法的证明,见高斯-马尔可夫定理。 + + +回归分析中常用的最小二乘法是一种无偏估计。对于一个适定问题,X通常是列满秩的: +

+ +

+采用最小二乘法,定义损失函数为残差的平方,最小化损失函数: +

+ +

+也可以采用梯度下降法进行求解优化,也可以采用如下公式进行直接求解: + +

+ +

+ +当X不是列满秩时,或者某些列之间的线性相关性比较大时,的行列式接近于0,即接近于奇异,上述问题变为一个不适定问题,此时,计算时误差会很大,传统的最小二乘法缺乏稳定性与可靠性。 + +因而,我们需要将不适定问题转化为适定问题:我们为上述损失函数加上一个正则化项,变为 +

+ +

+ +其中,我们定义,于是: +

+ +

+其中I是单位矩阵。 + +随着的增大,各元素的绝对值均趋于不断变小,它们相对于正确值的偏差也越来越大。趋于无穷大时,趋于0。其中,的改变而变化的轨迹,就称为岭迹。实际计算中可选非常多的 值,做出一个岭迹图,看看这个图在取哪个值的时候变稳定了,那就确定值了。 +岭回归是对最小二乘回归的一种补充,它损失了无偏性,来换取高的数值稳定性,从而得到较高的计算精度。 + + +#### 相关应用 +岭回归是在自变量组成的信息矩阵的主对角线元素上人为的加入一个非负因子k,使得矩阵行列式不为零,以降低对回归系数估计的误差,提高估计精确度以及模型的平稳性。它是最小二乘法的补充,岭回归可以修复病态矩阵,达到较好的效果。 + +近年来,岭回归在经济、工业生产、工程技术、环境保护等方面已有一定的应用。 + +#### 应用案例 +```python +import matplotlib.pyplot as plt +import numpy as np +from sklearn import datasets, linear_model, discriminant_analysis, cross_validation + +def load_data(): + diabetes = datasets.load_diabetes() + return cross_validation.train_test_split(diabetes.data, diabetes.target, test_size=0.25, random_state=0) + +def test_ridge(*data): + X_train, X_test, y_train, y_test = data + ridgeRegression = linear_model.Ridge() + ridgeRegression.fit(X_train, y_train) + print("权重向量:%s, b的值为:%.2f" % (ridgeRegression.coef_, ridgeRegression.intercept_)) + print("损失函数的值:%.2f" % np.mean((ridgeRegression.predict(X_test) - y_test) ** 2)) + print("预测性能得分: %.2f" % ridgeRegression.score(X_test, y_test)) + +#测试不同的α值对预测性能的影响 +def test_ridge_alpha(*data): + X_train, X_test, y_train, y_test = data + alphas = [0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000] + scores = [] + for i, alpha in enumerate(alphas): + ridgeRegression = linear_model.Ridge(alpha=alpha) + ridgeRegression.fit(X_train, y_train) + scores.append(ridgeRegression.score(X_test, y_test)) + return alphas, scores + +def show_plot(alphas, scores): + figure = plt.figure() + ax = figure.add_subplot(1, 1, 1) + ax.plot(alphas, scores) + ax.set_xlabel(r"$\alpha$") + ax.set_ylabel(r"score") + ax.set_xscale("log") + ax.set_title("Ridge") + plt.show() + +if __name__ == '__main__': + #X_train, X_test, y_train, y_test = load_data() + #test_ridge(X_train, X_test, y_train, y_test) + + #使用自己设置的alpha + X_train, X_test, y_train, y_test = load_data() + alphas, scores = test_ridge_alpha(X_train, X_test, y_train, y_test) + show_plot(alphas, scores) +``` + +#### 优缺点 +优点:可对变量之间共线性比较严重或病态数据偏多的数据类型作回归分析,对这类数据作回归得到的回归系数更符合实际,更可靠。另外,岭回归能让估计参数的波动范围变小,变的更稳定。 + +缺点:对系数的估计时,会损失部分信息、降低精度。同时岭回归方程的R平方值会稍低于普通的回归方法。 diff --git a/assets/src/RGN/RGN.0.3.md b/assets/src/RGN/RGN.0.3.md new file mode 100644 index 00000000..b38b7b41 --- /dev/null +++ b/assets/src/RGN/RGN.0.3.md @@ -0,0 +1,65 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + +#### Lasso算法(least absolute shrinkage and selection operator) + +Lasso算法(least absolute shrinkage and selection operator,又译最小绝对值收敛和选择算子、套索算法)是一种同时进行特征选择和正则化(数学)的回归分析方法,旨在增强统计模型的预测准确性和可解释性,最初由斯坦福大学统计学教授Robert Tibshirani于1996年基于Leo Breiman的非负参数推断(Nonnegative Garrote, NNG)提出[1][2]。 + +Lasso算法最初用于计算最小二乘法模型,这个简单的算法揭示了很多估计量的重要性质,如估计量与岭回归(Ridge regression,也叫Tikhonov regularization)和最佳子集选择的关系,Lasso系数估计值(estimate)和软阈值(soft thresholding)之间的联系。它也揭示了当协变量共线时,Lasso系数估计值不一定唯一(类似标准线性回归)。Lasso是一种缩减方法,将回归系数收缩在一定的区域内。Lasso的主要思想是构造一个一阶惩罚函数获得一个精确的模型, 通过最终确定一些变量的系数为0进行特征筛选。以两个变量为例,标准线性回归的cost function还是可以用二维平面的等值线表示,而约束条件则与岭回归的圆不同,Lasso的约束条件可以用方形表示,如图: + +

+ +

+ +相比圆,方形的顶点更容易与抛物面相交,顶点就意味着对应的很多系数为0,而岭回归中的圆上的任意一点都很容易与抛物面相交很难得到正好等于0的系数。这也就意味着,lasso起到了很好的筛选变量的作用。 + +#### 应用案例 + + +```python +import matplotlib.pyplot as plt +import numpy as np +from sklearn import datasets, linear_model, discriminant_analysis, cross_validation + +def load_data(): + diabetes = datasets.load_diabetes() + return cross_validation.train_test_split(diabetes.data, diabetes.target, test_size=0.25, random_state=0) + +def test_lasso(*data): + X_train, X_test, y_train, y_test = data + lassoRegression = linear_model.Lasso() + lassoRegression.fit(X_train, y_train) + print("权重向量:%s, b的值为:%.2f" % (lassoRegression.coef_, lassoRegression.intercept_)) + print("损失函数的值:%.2f" % np.mean((lassoRegression.predict(X_test) - y_test) ** 2)) + print("预测性能得分: %.2f" % lassoRegression.score(X_test, y_test)) + +#测试不同的α值对预测性能的影响 +def test_lasso_alpha(*data): + X_train, X_test, y_train, y_test = data + alphas = [0.01, 0.02, 0.05, 0.1, 0.2, 0.5, 1, 2, 5, 10, 20, 50, 100, 200, 500, 1000] + scores = [] + for i, alpha in enumerate(alphas): + lassoRegression = linear_model.Lasso(alpha=alpha) + lassoRegression.fit(X_train, y_train) + scores.append(lassoRegression.score(X_test, y_test)) + return alphas, scores + +def show_plot(alphas, scores): + figure = plt.figure() + ax = figure.add_subplot(1, 1, 1) + ax.plot(alphas, scores) + ax.set_xlabel(r"$\alpha$") + ax.set_ylabel(r"score") + ax.set_xscale("log") + ax.set_title("Ridge") + plt.show() + +if __name__=='__main__': + X_train, X_test, y_train, y_test = load_data() + # 使用默认的alpha + #test_lasso(X_train, X_test, y_train, y_test) + # 使用自己设置的alpha + alphas, scores = test_lasso_alpha(X_train, X_test, y_train, y_test) + show_plot(alphas, scores) +``` diff --git a/assets/src/RGN/RGN.0.4.md b/assets/src/RGN/RGN.0.4.md new file mode 100644 index 00000000..c5168890 --- /dev/null +++ b/assets/src/RGN/RGN.0.4.md @@ -0,0 +1,110 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + + +#### 弹性网络(Elastic Net) + +弹性网络是一种使用 L1,L2范数作为先验正则项训练的线性回归模型.这种组合允许学习到一个只有少量参数是非零稀疏的模型,就像 Lasso一样,但是它仍然保持一些像Ridge的正则性质。我们可利用 l1_ratio 参数控制L1和L2的凸组合。弹性网络是一不断叠代的方法。 + +

+ + +

+弹性网络最妙的地方是它永远可以产生有效解。由于它不会产生交叉的路径,所以产生的解都相当不错。举例来说,对一个随机产生的50个城市的推销员问题,弹性网络的解只有比德宾和威尔萧的论文中所提的最具竞争力的演算法长2%(什么是最具竞争力的演算法?有人说是林-克尼根(Lin-Kernighan)演算法,也有人说是SA+OP)。但是弹性网络最吸引人的地方不在它的有效解,而在它收敛的速度。许多人试着去改善弹性网络收敛的速度,都有不错的结果。举例来说,柏尔(Burr)所提出的改良版可令50个城市的推销员问题的收敛次数由1250大幅降为30次。一个最佳化的弹性网络的速度会比林-克尼根快两倍。 + +弹性网络在很多特征互相联系的情况下是非常有用的。Lasso 很可能只随机考虑这些特征中的一个,而弹性网络更倾向于选择两个。 +在实践中,Lasso 和 Ridge 之间权衡的一个优势是它允许在循环过程(Under rotate)中继承 Ridge 的稳定性。 + +在这里,最小化的目标函数是: +

+ +

+ + +#### 应用案例 +```python +print(__doc__) + +# Author: Alexandre Gramfort +# License: BSD 3 clause + +from itertools import cycle +import numpy as np +import matplotlib.pyplot as plt + +from sklearn.linear_model import lasso_path, enet_path +from sklearn import datasets + +diabetes = datasets.load_diabetes() +X = diabetes.data +y = diabetes.target + +X /= X.std(axis=0) # Standardize data (easier to set the l1_ratio parameter) + +# Compute paths + +eps = 5e-3 # the smaller it is the longer is the path + +print("Computing regularization path using the lasso...") +alphas_lasso, coefs_lasso, _ = lasso_path(X, y, eps, fit_intercept=False) + +print("Computing regularization path using the positive lasso...") +alphas_positive_lasso, coefs_positive_lasso, _ = lasso_path( + X, y, eps, positive=True, fit_intercept=False) +print("Computing regularization path using the elastic net...") +alphas_enet, coefs_enet, _ = enet_path( + X, y, eps=eps, l1_ratio=0.8, fit_intercept=False) + +print("Computing regularization path using the positive elastic net...") +alphas_positive_enet, coefs_positive_enet, _ = enet_path( + X, y, eps=eps, l1_ratio=0.8, positive=True, fit_intercept=False) + +# Display results + +plt.figure(1) +ax = plt.gca() + +colors = cycle(['b', 'r', 'g', 'c', 'k']) +neg_log_alphas_lasso = -np.log10(alphas_lasso) +neg_log_alphas_enet = -np.log10(alphas_enet) +for coef_l, coef_e, c in zip(coefs_lasso, coefs_enet, colors): + l1 = plt.plot(neg_log_alphas_lasso, coef_l, c=c) + l2 = plt.plot(neg_log_alphas_enet, coef_e, linestyle='--', c=c) + +plt.xlabel('-Log(alpha)') +plt.ylabel('coefficients') +plt.title('Lasso and Elastic-Net Paths') +plt.legend((l1[-1], l2[-1]), ('Lasso', 'Elastic-Net'), loc='lower left') +plt.axis('tight') + + +plt.figure(2) +ax = plt.gca() +neg_log_alphas_positive_lasso = -np.log10(alphas_positive_lasso) +for coef_l, coef_pl, c in zip(coefs_lasso, coefs_positive_lasso, colors): + l1 = plt.plot(neg_log_alphas_lasso, coef_l, c=c) + l2 = plt.plot(neg_log_alphas_positive_lasso, coef_pl, linestyle='--', c=c) + +plt.xlabel('-Log(alpha)') +plt.ylabel('coefficients') +plt.title('Lasso and positive Lasso') +plt.legend((l1[-1], l2[-1]), ('Lasso', 'positive Lasso'), loc='lower left') +plt.axis('tight') + + +plt.figure(3) +ax = plt.gca() +neg_log_alphas_positive_enet = -np.log10(alphas_positive_enet) +for (coef_e, coef_pe, c) in zip(coefs_enet, coefs_positive_enet, colors): + l1 = plt.plot(neg_log_alphas_enet, coef_e, c=c) + l2 = plt.plot(neg_log_alphas_positive_enet, coef_pe, linestyle='--', c=c) + +plt.xlabel('-Log(alpha)') +plt.ylabel('coefficients') +plt.title('Elastic-Net and positive Elastic-Net') +plt.legend((l1[-1], l2[-1]), ('Elastic-Net', 'positive Elastic-Net'), + loc='lower left') +plt.axis('tight') +plt.show() +``` diff --git a/assets/src/RGN/RGN.0.5.md b/assets/src/RGN/RGN.0.5.md new file mode 100644 index 00000000..06595fc8 --- /dev/null +++ b/assets/src/RGN/RGN.0.5.md @@ -0,0 +1,59 @@ +### Deeplearning Algorithms tutorial +谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! +AI的开发离不开算法那我们就接下来开始学习算法吧! + + +#### 最小角回归(LARS) + +最小角回归(LARS)是对高维数据的回归算法, 由 Bradley Efron, Trevor Hastie, Iain Johnstone 和 Robert Tibshirani 开发完成。 LARS 和逐步回归很像。在每一步,它寻找与响应最有关联的 预测。当有很多预测有相同的关联时,它没有继续利用相同的预测,而是在这些预测中找出应该等角的方向。 + + +#### 示例应用 +```python +print(__doc__) + +# Author: Fabian Pedregosa +# Alexandre Gramfort +# License: BSD 3 clause + +import numpy as np +import matplotlib.pyplot as plt + +from sklearn import linear_model +from sklearn import datasets + +diabetes = datasets.load_diabetes() +X = diabetes.data +y = diabetes.target + +print("Computing regularization path using the LARS ...") +alphas, _, coefs = linear_model.lars_path(X, y, method='lasso', verbose=True) + +xx = np.sum(np.abs(coefs.T), axis=1) +xx /= xx[-1] + +plt.plot(xx, coefs.T) +ymin, ymax = plt.ylim() +plt.vlines(xx, ymin, ymax, linestyle='dashed') +plt.xlabel('|coef| / max|coef|') +plt.ylabel('Coefficients') +plt.title('LASSO Path') +plt.axis('tight') +plt.show() +``` + + + +#### 优点和缺点 + +优点: + +1. 当 p >> n,该算法数值运算上非常有效。(例如当维度的数目远超点的个数) +2. 它在计算上和前向选择一样快,和普通最小二乘法有相同的运算复杂度。 +3. 它产生了一个完整的分段线性的解决路径,在交叉验证或者其他相似的微调模型的方法上非常有用。 +4. 如果两个变量对响应几乎有相等的联系,则它们的系数应该有相似的增长率。因此这个算法和我们直觉 上的判断一样,而且还更加稳定。 +5. 它很容易修改并为其他估算器生成解,比如Least Absolute Shrinkage and Selection Operator。 + +缺点: + +1. 因为 LARS 是建立在循环拟合剩余变量上的,所以它对噪声非常敏感。 diff --git a/assets/src/RST/RST.md b/assets/src/RST/RST.md index 426b31da..69c8d75b 100644 --- a/assets/src/RST/RST.md +++ b/assets/src/RST/RST.md @@ -1,4 +1,5 @@ ### Deeplearning Algorithms tutorial + 谷歌的人工智能位于全球前列,在图像识别、语音识别、无人驾驶等技术上都已经落地。而百度实质意义上扛起了国内的人工智能的大旗,覆盖无人驾驶、智能助手、图像识别等许多层面。苹果业已开始全面拥抱机器学习,新产品进军家庭智能音箱并打造工作站级别Mac。另外,腾讯的深度学习平台Mariana已支持了微信语音识别的语音输入法、语音开放平台、长按语音消息转文本等产品,在微信图像识别中开始应用。全球前十大科技公司全部发力人工智能理论研究和应用的实现,虽然入门艰难,但是一旦入门,高手也就在你的不远处! AI的开发离不开算法那我们就接下来开始学习算法吧! @@ -39,9 +40,9 @@ D在C上的依赖度定义为: + +

+ +支持向量 +

+ +

+

+ +

+ +求出⍵和b的最优解。 + +从而得到分离的超平面: +

+ +

+分类决策函数 +

+ +

+ +其中,C>0为惩罚参数。 + + +#### 算法背景 +支持向量机的第一篇论文由Vladimir Vapnik 和他的同事Bernhard Boser 及Isabelle Guyon 于1992年发表,前期基础工作早在20世纪60年代就已经出现,虽然SVM的训练非常缓慢,但由于其对复杂的非线性边界的建模能力,他们是非常准确的,并且和其他模型相比,他们不太容易发生过拟合,因此在手写数字识别、对象识别以及基准时间序列预测检验等方面成功应用。 + +#### 应用领域 +1.于文本和超文本的分类,在归纳和直推方法中都可以显著减少所需要的有类标的样本数。 + +2.图像分类。实验结果显示:在经过三到四轮相关反馈之后,比起传统的查询优化方案,支持向量机能够取得更好的搜索准确度。 + +3.用于医学中分类蛋白质,超过90%的化合物能够被正确分类。用于手写字体识别。 + +#### 优缺点 + +SVM的优点 + +1. 可以解决小样本情况下的机器学习问题。 + +2. 可以提高泛化性能。 + +3. 可以解决高维问题。 + +4. 可以解决非线性问题。 + +5. 可以避免神经网络结构选择和局部极小点问题。 + +SVM的缺点: + +1. 对缺失数据敏感。 + +2. 对非线性问题没有通用解决方案,必须谨慎选择Kernelfunction来处理。 +