Git问题汇总

因为有多次重装系统后配置系统环境的经历,因此笔者认为有必要总结其中的经验,节省下一次配置时使用搜索引擎的时间。

安装以及基本配置

Windows系统的Git下载地址,依据默认配置一路下一步即可,进阶用户当然可以定制其中的配置,例如新增以VS Code为默认编辑器的选项。

进入git提供的命令行界面,建议配置基本信息:

1
2
$ git config --global user.name "${你的用户名}"
$ git config --global user.email ${GitHub用户邮箱}

常用GitHub托管代码时,笔者倾向于使用SSH免密登录,因此使用:

1
$ ssh-keygen -t rsa -C "${邮箱地址}"

然后一路回车就行了,生成的公私钥文件位于~/.ssh/(Windows 10为C:\Users\${用户名}\.ssh)文件夹内,打开其中id_rsa.pub文件,复制其中文本到GitHub SSH配置中,完成该步骤。

测试配置结果可以使用:

1
$ ssh -T git@github.com

第一次测试成功会发现类似以下的信息:

1
2
3
The authenticity of host 'github.com (207.97.227.239)' can't be established.
RSA key fingerprint is 16:27:ac:a5:76:28:2d:36:63:1b:56:4d:eb:df:a6:48.
Are you sure you want to continue connecting (yes/no)?

回车即可,若并未成功并且出现超时结果,可以参考本文的下一节。

使用SSH拉取远程仓库超时问题

笔者在最近一次(2019-07-05)配置git中发现,按上一节配置后并未成功拉取仓库代码,出现了超时:

1
ssh: connect to host github.com port 22: Connection timed out

结合个人使用经验以及谷歌搜索结果,使用以下命令测试:

1
$ ssh -T -p 443 git@github.com

发现可以成功连接GitHub,因此判定为Git客户端的配置与GitHub服务器开放的端口不符。在此前安装Git时候并未出现过该问题,不过那时GitHub还没有被微软收购,其中原因暂不深究,解决问题为先。虽然有将仓库链接改为https://开头的解决方案,但是笔者不倾向于该方案,因此选择了以下方案:

~/.ssh/(Windows 10为C:\Users\${用户名}\.ssh)文件夹内新建一个config文件(注意不要有后缀,仅一英文单词),向其中写入:

1
2
3
Host github.com
Hostname ssh.github.com
Port 443

即改变SSH的默认连接,再次运行:

1
$ ssh -T git@github.com

测试通过,问题解决,让新配置的Git也可以通过SSH方式拉取仓库代码。

逻辑斯谛回归模型

逻辑斯谛回归模型(Logistic Regression,以下简称LR)是统计学习中的经典分类方法。读过《统计学习方法》之后,笔者才知道该模型是一种概率分布模型,从此理解为何该模型不但可以预测分类,还可以预测属于该类的概率。

逻辑斯谛分布

是连续随机变量,若服从逻辑斯谛分布,则有如下分布函数和密度函数:

下面两张是时的概率密度分布以及累计概率分布:

可以看到PDF关于Y轴对称,CDF关于对称。

曲线在中心附近增长速度较快,在两端增长速度较慢。形状参数越小,曲线在中心附近增长越快。

二项逻辑斯谛回归模型

二项逻辑斯谛回归模型(Binomial Logistic Regression Model)是一种分类模型,由条件概率分布表示,随机变量取值0或1,

故二项逻辑斯谛回归模型是如下的条件概率分布:

逻辑斯谛回归模型的特点

定义一个事件的几率(odds)是指该事件发生的概率与该事件不发生的概率的比值。设事件发生的概率为,则该事件的几率是,事件的对数几率(logit odds)或logit函数:

将上述的代入到中,则有:

即,在逻辑斯谛回归模型中,输出的对数几率是输入的线性函数。

从另外一个角度看,考虑对输入进行分类的线性函数,其值域为实数域。此时,线性函数的值越接近于正无穷,概率值越接近1;线性函数的值越接近负无穷,概率值越接近0.

模型参数估计

利用极大似然估计法可以估计模型的参数,设:

似然函数:

对数似然函数:

问题就转变为了以对数似然函数为目标函数的最优化问题。逻辑斯谛回归学习中通常采用梯度下降法或拟牛顿法。

对权重向量求偏导则可得:

采用,则偏导可以表示为:

这篇文章仅仅介绍逻辑斯谛回归模型,不介绍最优化常用的方法,读者可以寻找各类最优化方法,将上述提到的目标函数以及一阶偏导代入到各类优化方法中。

决策树之ID3与C4.5

笔者最近开始学习李航的《统计学习方法》,将以前零散学习的数据挖掘/机器学习算法系统整理一遍,而决策树则可以说是一个入门级的内容了。

李航将机器学习方法等价为:模型+策略+算法,笔者认为这个总结十分受用,便于拆解一些经典的算法逐步理解。这种自上而下将任务拆解的方法则很合适工程类人士学习。

根据李航给出的框架,首先将决策树分解为:

1
2
3
模型:决策树,归根结底就是一个条件概率分布函数。
策略:选择模型的准则,在决策树中则为决策树的损失函数。
算法:求解决策树的算法,在此是生成决策树的算法。

决策树学习的三个步骤:特征选择、决策树生成、决策树剪枝。

模型

在此语境下,模型即是决策树。分类决策树模型是一种描述对实例进行分类的树形结构。决策树由结点(node)和有向边(directed edge)组成。结点有两种类型:内部结点(internal node)和叶结点(leaf node)。内部结点表示一个特征或属性,叶结点表示一个类。

策略

在生成决策树时是不需要损失函数的,但是不经过剪枝的决策树会有过于复杂以及过拟合的情况,而剪枝在某种程度上解决该问题,于是便在生成决策树后进行一个剪枝的操作,而剪枝所用的损失函数:

其中,表示决策树叶子节点个数,表示叶子节点下有个样本,其中第类样本点个。参数影响惩罚力度,越大则对叶子节点数量越敏感,此时算法倾向于选择叶子节点少的决策树。

算法

生成一颗决策树核心的问题是,如何选取特征作为分裂当前节点的依据?ID3使用信息增益作为特征选择的依据,C4.5则采用信息增益比

经验熵与条件经验熵(点击展开细节) 在信息论与概率统计中,`熵(Entropy)`是表示随机变量不确定性的度量。设X是一个取有限值的`离散随机变量`,其概率分布为:

则随机变量X的熵定义为:

时,定义

设有随机变量,其联合概率分布为:

条件熵表示在已知随机变量X的条件下随机变量Y的不确定性。随机变量X给定的条件下随机变量Y的条件熵(Conditional Entropy),定义为X给定条件下Y的条件概率分布的熵对X的数学期望:

其中,

当熵和条件熵中的概率由数据估计(尤其是极大似然估计)得到时,所对应的熵与条件熵分别成为经验熵(Empirical Entropy)和经验条件熵(Empirical Conditional Entropy)。

ID3采用的信息增益公式:

其中D为训练数据集,A为特征。

也被称为互信息(mutual information)。决策树学习中的信息增益等价于训练数据中类与特征的互信息。

根据信息增益准则的特征选择方法:对训练数据集(或子集)D,计算其每个特征的信息增益,并比较它们的大小,选择最大值者为当前节点分裂的依据。

具体的特征增益算法:

  1. 计算数据集D中的经验熵:
  2. 计算特征A对数据集D的经验条件熵:
  3. 计算信息增益:

ID3的信息增益存在一个缺点,易偏向选择取值较多的特征。而C4.5ID3的不同之处是划分训练数据集的特征的方法不同,C4.5使用信息增益比(information gain ratio)矫正信息增益存在的问题:

其中,n是特征A的取值个数。

按照李航介绍机器学习的方法模型+策略+算法,已经把两个经典的决策树的算法在较为高层的角度讲述了,然而到落实为代码仍需要更为详细的伪代码来讲述。

ID3的伪代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
输入: 训练数据集D,特征集A,阈值e
输出: 决策树T
if D中所有实例属于同一类C[k] then
return new TreeNode(class = C[k])
if A为空集 then
找出D中实例数最多的类C
return new TreeNode(class = C)
classes = D中各类的统计数
entropy_d = Entropy(classes)
for k in 1..A.length
cnt = 0
stats_ak = 统计A[k]的取值情况
entropy_ak[k] = 0
for val in A[k]
for c in 1..classes.length
stats_ak[k][val][c] = 统计取值A[k]=vak,时D[c]的取值情况
entropy_ak[k] = Entropy(stats_ak[k], entropy_d)
gain_ak = gain(entropy_d, entropy_ak)
从gain_ak获得最大取值时的k
if gain_ak[k] < e then
找出D中实例数最多的类C
return new TreeNode(class = C)
for val in A[k]
通过val作为识别,将A[k]=val时的实例归到新数据集D_sub[val]
A_new[val] = A[k]=val并且去掉A[k]特征后的特征集
T_sub[i] = 递归生成子节点algo(D_sub[val], A_new[val], e)
return new TreeNode(child = T_sub)

C4.5则是更对计算entropy_ak时的公式小更改,笔者认为给出的伪代码已经很细节了。很久之前用Ruby写过ID3的第一版,虽然之前打算重写,但是发现要学习的东西太多,所以重写计算暂时延后,先把没有学到的经典算法实现了再回头做这里。

Spark配置笔记

环境支持

  1. RHEL 7.x
  2. JDK 1.8或以上

JDK的安装

这一步相信经常使用Java的人都有一定的配置经验,无非在RHEL下安装:

1
yum install ${jdk发行版本}.rpm

有一些rpm包不支持在安装时自动配置JAVA_HOME等环境变量,可以使用:

1
rpm -qa | grep -i java

找出安装包的完整名称,随后:

1
rpm -ql ${上一句命令输出的jdk完整名称}

找到JDK的安装路径,随后在/etc/profile或其他脚本下加入:

1
2
3
4
5
6
JAVA_HOME=${找到的JDK安装路径}
CLASSPATH=.:$JAVA_HOME/lib:$JAVA_HOME/lib/tools.jar
export JAVA_HOME
export CLASSPATH
... # 省略中间的其他命令
PATH=.:$PATH:$JAVA_HOME/bin

然后就是经典的测试是否成功配置:

1
java -version

Hadoop安装配置

由于笔者仅关注成功配置Spark后运行一些程序,暂时不涉及存储问题,这一步日后进行到了再记录。

Spark安装配置

先到官网上下载对应的Spark版本,注意要和Hadoop的版本匹配,例如笔者下载协同Hadoop2.7以上的最新2.3.2版.

成功下载后,使用tar命令(笔者习惯安装到/opt目录下,当然可以安装到/usr/local等目录):

1
2
tar zxf spark-2.3.2-bin-hadoop2.7.tgz -C /opt # 笔者在root权限下执行
cd /opt/spark-2.3.2-bin-hadoop2.7/bin

直接执行:

1
./spark-shell

进入交互模式,证明安装成功。

机器学习练习笔记(九)

C-SVM:Cost-sensitive SVM,代价敏感SVM。

题目9.1 - C-SVM优化问题求解

线性神经元中存在一个未用在分类中的自由度。通过设置如下约束消除:

证明在此约束下,样本到决策边界上最近的一点被下式限制:

第二问,是写下C-SVM的拉格朗日的优化问题并解出C-SVM的对偶优化问题:

Missing or unrecognized delimiter for \left \underset{\lambda}{\max}\left{-\frac{1}{2}\sum_{\alpha=1}^{p}\sum_{\beta=1}{p}\lambda_\alpha \lambda_\beta y_T^{(\alpha)} y_T^{(\beta)} \left(x^{(\alpha)})\right)^T x^{(\beta)} + \sum_{\alpha=1}^{p}\lambda_\alpha \right}

其中:

关于SVM优化的证明过程及解释网上都有不少优秀的讲解,笔者在此就不展开了。

题目9.2 - 标准参数下的C-SVM

本题目是练习解决经典的“XOR”分类问题。首先通过前面章节题目7.1产生80个样本的训练集,然后通过同样的分布产生80个样本的测试集。这里不实现SVM算法,对于matlab,可以使用libsvm包;对于python则可以使用libsvmscikit.learn;笔者使用的R中的e1071

通过软件自身默认的C-SVM训练参数建立模型,并用将模型应用在测试集上。把决策边界显示出来,同时表示出支持向量。

图中蓝点即为支持向量

题目9.3 - C-SVM参数优化

使用交叉验证以及网格搜索发找出C与核参数。使用指数增长搜索,如,画出交叉验证中训练集分类率,以及使用等高线画出参数空间下的关于这两个参数的值。

第二问使用上述所得的最佳,重做练习9.2。

机器学习练习笔记(八)

本章节是一些统计学习理论。

题目8.1 - Vapnik-Chervonenkis dimension,VC维

使用的定义以及二项式的递归属性:

对于,证明一个线性分类器,,其VC维

记住,$$\tilde{C}{(N+1,N)} = 2^{N+1}\tilde{C}{(N+2,N)}<2^{N+2}$$。

显然笔者暂时不会证,或者网上已经有大堆博客,这题先放着。

题目8.2 - 分类可变性

假设样本分别属于两个聚类,分别通过正态分布,其中是单位阵。使用N个样本,测试一个线性神经元学习出来的模型的性能如何。按照如下步骤:

  1. 对于两个聚类,分别产生个数据点,当类属为时,;当,当类属为时,
  2. 根据均方误差最小化,得出
  3. 产生根据同样的分布,每个类属产生500个测试样本。
  4. 分别计算经验(训练)误差以及测试误差。

对于,分别重复50次,记下训练后的参数以及训练集的精度和测试集的精度。

第一问使用误差棒图描绘出每个N下的训练精度以及测试集精度均值和标准差:

可以看到训练样本越少,模型越容易过拟合,泛化性能越差,模型也不稳定(方差大)。

第二问分别绘出关于N的误差棒图:

基本情况跟第一问一样,样本越少,重复中出来的参数误差越大。

题目8.3 - 二项分布

本题目涉及三个概率密度函数:

第一个问题是通过不同绘出函数图形。

第二个问题是什么条件下,可以合理使用正态分布近似二项分布。在时,正态分布可以近似表达。可以绘制一个样本图像来说明。

第三个问题是什么条件下,可以使用泊松分布来近似二项分布。当二项分布的很大而p很小时,泊松分布可作为二项分布的近似,其中。通常当时,就可以用泊松公式近似得计算。同样也可以绘制一个示例来说明。

至此第八章的解题结束。

机器学习练习笔记(七)

题目7.1 - 训练数据的准备

目的是产生一个典型的XOR问题的数据分布,通过如下的公式产生:

其中

根据规则产生y=0以及y=1各60组的数据分布:

题目7.2 - k近邻

kNN算法概念,令k=1,3,5,描绘出决策边界,没有什么技巧,就是暴力计算,用密集的点表示出决策边界:

k=1时的决策边界

k=3时的决策边界

k=1时的决策边界

题目7.3 - “Parzen window”分类器

基于欧氏范数的高斯窗口函数:

即根据作为训练集的点与将被预测的点的距离通过此函数计算出影响权重,最后得出哪个类别的权重最大。

利用同样作图方法,画出时的决策边界。

$\sigma_{\mathcal{k}}^2=0.5$时的决策边界

$\sigma_{\mathcal{k}}^2=0.1$时的决策边界

$\sigma_{\mathcal{k}}^2=0.01$时的决策边界

可以看到值越小,边界越靠近支持向量机的结果。

第二问是添加第三个类别,根据,然后利用kNN和Parzen窗口同样的参数再跑一遍算法,观察结果。

kNN,k=1

kNN,k=3

kNN,k=5

Parzen窗口,$\sigma_{\mathcal{k}}^2=0.5$

Parzen窗口,$\sigma_{\mathcal{k}}^2=0.1$

Parzen窗口,$\sigma_{\mathcal{k}}^2=0.01$

题目7.4 - RBF网络

上一题里面,利用全体训练集对进来的点进行预测,显然是一个自然而然的选择,但是当训练集的样本数很大时,假设进来t个点,那么判定的时间复杂度就攀升到,显然对计算能力提出了要求。那么一个想法就是,能不能通过采集一些训练集中具有代表性的点,用来进行预测?

通过这样的思路,选区代表性的点可以通过K-means方法,然后对于每个将要进行预测的点,计算该点与这些代表点的距离(高斯窗口函数),将所得的“距离”作为线性分类器的输,即利用下述的表达式:

其中:

为代表点,信号函数:

根据最小二乘法,可知训练后的权重:

第一问就令,选取合理的,笔者选择0.5与0.01,画出决策边界:

$K=2,\sigma^2_k=0.01$

$K=2,\sigma^2_k=0.5$

$K=3,\sigma^2_k=0.01$

$K=3,\sigma^2_k=0.5$

$K=4,\sigma^2_k=0.01$

$K=4,\sigma^2_k=0.5$

回想一下一个XOR点的分布图,为4的倍数时应该是最佳的效果。

第二问通过修改固定的两个代表点来检验效果,其中,笔者就不画出决策边界了,但是经过线性处理之后的图像,笔者认为可以看一看:

其中横坐标轴为,纵座标轴为,显然通过核函数转换之后,问题变成了线性可分。

至此第七章的练习结束。

数据预处理-白化

白化,Whitening,有些文献也将该过程称作Sphering

白化的目的是:

  • 特征之间相关性较低
  • 所有特征具有相同的方差

白化处理分PCA白化和ZCA白化,PCA白化保证数据各维度的方差为1,而ZCA白化保证数据各维度的方差相同。

PCA白化可以用于降维也可以去相关性,而ZCA白化主要用于去相关性,且尽量使白化后的数据接近原始输入数据。

该部分仅仅介绍ZCA白化。

首先展示原始的输入

第一步作中心化,使得每个维度的均值为,即

接下来求数据的协方差矩阵,根据协方差公式,有:

对求得的协方差矩阵特征分解,对于2维的输入,将所得的特征向量与中心化后的数据一同显示:

去相关过程,记住“实对称矩阵的特征向量矩阵是正交矩阵”,设特征向量组成的矩阵为,接下来就是将数据投影到特征向量,

最后作缩放,设协方差矩阵作特征分解后的特征值矩阵为:

缩放

数据的分布就变圆了一些,这也是为什么白化过程也成为Sphering的原因。

矩阵运算与坐标变换

相信本科时候没有好好学线性代数的同学会对:

$$
\left[

\right]
\left[

\right]

\left[

\right]
$$

这样的一个矩阵乘法之后,原坐标下的向量坐标就会变成了新坐标下的向量坐标,多少会感觉到一些突然。

笔者在此复习一边这样的矩阵乘法与坐标变换的关系。

好了,从熟悉坐标系开始,假设我们在这个坐标下有一个向量

事实上图中的坐标系是由一组标准正交基构成的。计算一个向量在一组基下的坐标是分别用该向量与每个基作点乘(投影),得到向量在每个基下的投影长度。

例如计算就是分别计算的值。

那么将向量的形式换成用线性代数一般的表示形式:

那么坐标系变换的过程可以表示为如下的矩阵运算:

$$
\left[

\right]
\left[

\right]

\left[

\right]
\left[

\right]

\left[

\right]
$$

矩阵运算与坐标变换就这样联系起来了,当然这里全都设置为的值,当然看不出变换在哪里了,这里开始从原来的组成的坐标系开始作变换:

假设有一组新的标准正交基,容易验证:

新标准正交基加入后,作图如下:

计算原向量在新坐标系(基底)下的坐标(各基底下的投影长度)如下:

写成矩阵表示:

$$
\left[

\right]
\vec{a}^T

\left[

\right]
\left[

\right]

\left[

\right]
$$

抹去原来的坐标线,只看新基底与被投影的向量:

把头倾斜一下,就看到形成的新坐标系:

注意新基底在变成了新坐标,因为他们自己投影自己后的长度都为,并且正交,在对方的投影值都为。读者可以试试用投影定义式计算图中向量在新坐标系下的坐标值。

对于个标准正交基组成的向量空间,其坐标变换可以表示为矩阵运算:

$$
\left[

\right]
\vec{x}^T

\left[

\right]
\left[

\right]
$$

其中为原N维空间下的坐标向量,长度为n

当需要表示更加复杂的变换,例如2维空间下,需要平移操作,这个时候增加一维信息,具体有兴趣的读者可以到网上了解。

至此,又复习了一课线性代数。

机器学习练习笔记(六)

这章是为了让人体验深度神经网络而设置,根据题目要求组合出来的神经网络,进行一下训练,熟悉一下一般的机器学习科研(调参)流程。

因而笔者建议在这部分更加侧重于学习每种神经网络层的作用以及区别,例如Loss函数、激活函数、不同的梯度下降法对训练网络的影响。

常用的神经网络层有全连接层、循环层、卷积层以及经常配套出现的池化层等。

题目6.1 - 卷积神经网络

该章所用的数据集就是常用的MNIST手写数字数据集:

  • 数据集每个样本都是28*28的矩阵存储,展开为一维向量时则有784个属性
  • 样本的分类使用布尔值向量表示,如结果为3

第一问是使用经典的线性层来训练,其中参数:

  • 学习率
  • 使用Cross Entropy作为损失函数
  • 随机梯度下降作为参数优化方法
  • 数据批处理大小,训练

由于10000个Epochs对于笔者的个人电脑来说压力太大了,训练起来太久了,于是偷个懒设置成1000了,虽然可以使用GPU加速,但是这样会与笔者的GeForce驱动冲突,于是也懒得用cuDNN了。

训练过程中的精度和Loss变化:

第二问是使用三层线性成组成多层网络,参数:

  • 初始化
  • 每个隐藏层使用ReLU作为激活函数
  • 最后输出使用Softmax作为激活函数
  • 学习率
  • 参数优化使用Adam算法
  • Cannot read properties of null (reading '4')Math input error,为优化器参数
  • 数据批处理大小,训练

同样设置20个Epochs就好了,笔者电脑吃不消。

第三问在相邻的隐藏层间插入Dropout层,参数:

  • 随机断开连接的几率设置为0.5

其余参数与上一问一样,重复实验。

第四问轮到大名鼎鼎的卷积层CNN出场,这部分的参数较为复杂,所幸的是这里学习的问题在TensorFlow官网上的配置基本是一致的。

参数方面,卷积层:

  • 卷积核的大小为5*5,因为每张图像原始大小为28*28,经过卷积后变成了24*24
  • 填充策略padding='same'
  • 卷积层1feature maps32,即参数filter=32卷积层2则为64
  • 默认使用bias=TRUE
  • 使用ReLU作为激活函数

池化层采用最大池化层:

  • 池化大小pool_size=2,事实上应该是pool_size=c(2,2),代表每2*2局部图像抽取其中最大值成一个像素
  • 跨幅strides=2,即每次池化后选取下一个池化区域的步长,例如池化大小为2时,第一次池化图像的坐标(0,0),(0,1),(1,0),(1,1),那下一个为(0,2),(0,3),(1,2),(1,3)

损失函数使用交叉熵Cross-EntropyAdam作为优化器。

最后一问就是比较前几问的模型,使用100个Epochs对比它们的效果,包括过拟合现象等比较,笔者在这里就不多介绍了,机器快烧了。

题目6.2 - LSTM网络

第一问是准备数据,数据样本有如下特征:

  • 10000组数据,每组数据为长度30的序列
  • 为整数
  • 当序列和不小于100时,对应的标签,否则为0
  • 其中8000组作为训练集,2000组作为验证集

产生了数据集之后,第二问自然就是构建一个LSTM网络并且用上述的数据集训练了。

LSTM网络参数:

  • 输入为长度30的1维序列
  • 有200个输出单元
  • 使用logistic sigmoidal作为激活函数
  • cross entropy作为损失函数
  • 添加一层线性层,将上一层的LSTM的200个输出拟合为一个0-1的输出

于是笔者实验出了一个神奇的ACC-LOSS图像:

笔者不能理解这个突跃是什么情况,日后有机会问到大佬给出解释之后再说吧。

剩下的问题就是修改一下参数跑实验,对比一下不同点,笔者就不再赘述了。

至此第六章的习题结束。