Category Archives: 0和1

Neural Networks and Deep Learning(三·一)梯度消失

原文的第三章内容较多,本博客将分四个部分进行介绍:梯度消失、正则化、权重初始化、超参数和其他,首先介绍梯度消失问题。

为简单起见,假设网络只包含一个输入和一个神经元,网络的损失是均方误差损失MSE,激活函数是Sigmoid函数。则该网络的参数只包含权重w和偏移量b。我们想训练这个网络,使得当输入为1时,输出0。

Continue reading

Neural Networks and Deep Learning(二)BP网络

这一讲介绍误差反向传播(backpropagation)网络,简称BP网络。

以上一讲介绍的MNIST手写数字图片分类问题为研究对象,首先明确输入输出:输入就是一张28×28的手写数字图片,展开后可以表示成一个长度为784的向量;输出可以表示为一个长度为10的one-hot向量,比如输入是一张“3”的图片,则输出向量为(0,0,0,1,0,0,0,0,0,0,0)。

然后构造一个如下的三层全连接网络。第一层为输入层,包含784个神经元,正好对应输入的一张28×28的图片。第二层为隐藏层,假设隐藏层有15个神经元。第三层为输出层,正好10个神经元,对应该图片的one-hot结果。

全连接网络表示上一层的每个神经元都和下一层的每个神经元有连接,即每个神经元的输入来自上一层所有神经元的输出,每个神经元的输出连接到下一层的所有神经元。每条连边上都有一个权重w。

Continue reading

Neural Networks and Deep Learning(一)MNIST数据集介绍

最近开始学习神经网络和深度学习,使用的是网上教程:http://neuralnetworksanddeeplearning.com/,这是学习心得第一讲,介绍经典的MNIST手写数字图片数据集。

MNIST(Modified National Institute of Standards and Technology database)数据集改编自美国国家标准与技术研究所收集的更大的NIST数据集,该数据集来自250个不同人手写的数字图片,一半是人口普查局的工作人员,一半是高中生。该数据集包括60000张训练集图片和10000张测试集图片,训练集和测试集都提供了正确答案。每张图片都是28×28=784大小的灰度图片,也就是一个28×28的矩阵,里面每个值是一个像素点,值在[0,1]之间,0表示白色,1表示黑色,(0,1)之间表示不同的灰度。下面是该数据集中的一些手写数字图片,可以有一个感性的认识。

Continue reading

Ubuntu下使用VSCode连接Github

VSCode是微软开源的一个很强大的IDE,可以支持几乎所有编程语言,而且是跨平台的,Linux用户终于可以用上宇宙最强IDE了。我最近在使用VSCode编写调试Python项目,其调试功能很强大,和VS上调试C++的感觉是一样的,强烈推荐。

VSCode还可以连接Github,进行版本控制。下面以我最近学习的深度学习项目为例,介绍下怎样在Ubuntu下使用VSCode连接Github。以我fork的repo为例:https://github.com/01joy/neural-networks-and-deep-learningContinue reading

逻辑回归之Python应用实例

上一篇博客主要介绍了逻辑回归的理论知识,这篇博客咱们用Python机器学习包sklearn中的LogisticRegression做一个分类的实例。

数据还是学生样本,只有两个特征,分别是两门课的分数score1和score2,类标号y表示这个学生是否能被录取。先上分类效果图:

Continue reading

初探逻辑回归

最近实验室在组织学习NG的机器学习视频,我也跟进了一下。讲到逻辑回归那一课,一直想不明白,逻辑回归到底是怎样分类的?逻辑回归的分类面在哪里?逻辑回归有像SVM的max margin那样清晰的推导过程吗?为什么需要Sigmoid函数?今天就让我们来一窥逻辑回归的始末。

假设有一堆学生样本,为了简单起见,只有两个特征,分别是两门课的分数score1和score2,类标号y表示这个学生是否能被录取。可视化如下图,黑点表示y=1即被录取,红点表示y=0即未被录取,可以看到黑点处在score1和score2都比较高的区域。我们的任务就是给定这些训练样本,需要确定一个分类面来划分这两类数据。

Continue reading

Gperftools性能分析工具使用教程

上一篇博客简单介绍了Linux平台下不同性能分析工具的特点,最后是Google出品的gperftools胜出。今天我们将举一个用gperftools对链接库进行性能分析的例子。

假设我们创建了一个TestGperftools项目,其中包括一个动态链接库模块complex和主程序main,build文件夹用于存放动态链接库和可执行程序,文件结构如下所示。

czl@ubuntu:~/czl/TestGperftools$ tree
.
├── build
├── complex
│   ├── complex.cpp
│   ├── complex.h
│   └── Makefile
├── main
│   ├── main.cpp
│   └── Makefile
└── Makefile

3 directories, 6 files

Continue reading

Linux性能分析工具简介

这半年一直在研究pLink 2的加速策略,了解了相关的性能分析工具,现记录如下。

对软件进行加速的技术路线一般为:首先对代码进行性能分析( performance analysis,也称为 profiling),然后针对性能瓶颈提出优化方案,最后在大数据集上评测加速效果。所以进行性能优化的前提就是准确地测量代码中各个模块的时间消耗。听起来很简单,不就是测量每行代码的运行时间吗,直接用time_t t=clock();不就好了,但是事情并没有那么简单。如果只进行粗粒度的性能分析,比如测量几个大的模块的运行时间,clock()还比较准确,但是如果测量的是运算量比较小的函数调用,而且有大量的小函数调用,clock()就不太准确了。

比如下面的一段代码,我最开始的性能分析方法是在fun1()~fun3()前后添加time_t t=clock(),然后作差求和的。但是3个fun()加起来的时间居然不等于整个while循环的时间,有将近50%的时间不翼而飞了!

while(true) {
	if(fun1()) {
		for(int i=0;i<k;++k) {
			if(flag1) {
				fun2();
			}
		}
	} else {
		fun3();
	}
}

一种可能是while循环以及内部的for循环本身占用了较多的时间,但是好像不太可能呀。还有一种可能是clock()测量有误,time_t只能精确到秒,clock_t只能精确到毫秒,如果一次fun*()的时间太短,导致一次测量几乎为0,那么多次的while和for循环调用累加的时间也几乎为0,导致实际测量到的fun*()时间远小于真实时间。所以自己用代码进行性能分析可能会有较大的误差,最好借助已有的性能分析工具。 Continue reading

C++基本数据类型备忘

今天阅读《C++ Primer, 5e》的第二章,介绍C++的基本内置类型,觉得有一些平时工作容易出错的知识点,现摘录如下:


unsigned char c = -1; // 假设char占8比特,c的值为255

当我们赋给无符号类型一个超出它表示范围的值时,结果是初始值对无符号类型表示数值总数取模后的余数。例如,8比特大小的unsigned char可以表示0至255区间内的值,如果我们赋了一个区间以外的值,则实际的结果是该值对256取模后所得的余数。因此,把-1赋给8比特大小的unsigned char所得的结果是255。


signed char c2 = 256; // 假设char占8比特,c2的值是未定义的

当我们赋给带符号类型一个超出它表示范围的值时,结果是未定义的(undefined)。此时,程序可能继续工作、可能崩溃,也可能生成垃圾数据。 Continue reading

随机矩阵及其特征值

随机矩阵是这样一类方阵,其元素为非负实数,且行和或列和为1。如果行和为1,则称为行随机矩阵;如果列和为1,则称为列随机矩阵;如果行和和列和都为1,则称为双随机矩阵。

前面我们介绍的谷歌矩阵HMM中的转移矩阵都属于随机矩阵,所以随机矩阵也称为概率矩阵、转移矩阵、或马尔可夫矩阵。

随机矩阵有一个性质,就是其所有特征值的绝对值小于等于1,且其最大特征值为1。下面通过两种方法证明这个结论。

首先,随机矩阵A肯定有特征值1,即

\begin{equation}A\vec 1=1\times\vec 1\end{equation}

其中的单位向量\vec 1=(\frac{1}{n},...,\frac{1}{n})^T,因为A的行和为1,所以上述等式成立。即1是A的特征值。 Continue reading