├── Chapter1 └── README.md ├── Chapter2 ├── 2d.png ├── README.md ├── perceptron.py └── perceptron_duality.py ├── Chapter3 ├── 3.1.py ├── KNN_appointment.py ├── KNN_movie.py ├── README.md ├── datingTestSet.txt ├── iris.py └── iris_kdtree.py ├── Chapter4 ├── Naive_Bayes.py ├── README.md └── 例4.1.py ├── Chapter5 ├── C4.5.py ├── README.md ├── decision_tree.py └── info_gain.py ├── Chapter6 └── README.md ├── Chapter7 ├── README.md ├── SVM.py ├── surrogate_loss_function.py ├── test.png └── 习题7.2.py ├── Chapter8 ├── AdaBoost习题8.1.py ├── AdaBoost例8.1.py └── README.md ├── README.md └── markdown语法.md /Chapter1/README.md: -------------------------------------------------------------------------------- 1 | 2 | # 笔记摘要 3 | 4 | * 统计学习或机器学习一般包括监督学习、无监督学习、强化学习,有时还包括半监督学习、主动学习 5 | ## 监督学习 6 | * 监督学习指从标注数据中学习预测模型的机器学习问题,其本质是学习输入到输出的映射的统计规律。 7 | * 输入变量$X$和输出变量$Y$有不同的类型,可以是连续或是离散的。根据输入输出变量的不同类型,对预测任务给予不同的名称:输入与输出均为连续变量的预测问题称为**回归问题**;输出变量为有限个离散变量的预测问题称为**分类问题**;输入与输出变量均为变量序列的预测问题称为**标注问题**。 8 | ## 无监督学习 9 | * 无监督学习指从无标注数据中学习预测模型的机器学习问题,其本质是学习数据中的统计规律或内在结构。 10 | * 无监督学习旨在从假设空间中选出在给定评价标准下的最优模型,模型可以实现对数据的聚类、降维或是概率估计。 11 | ## 强化学习 12 | * 强化学习指智能系统在与环境的连续互动中学习最优行为策略的机器学习问题,其本质是学习最优的序贯决策。 13 | * 智能系统的目标不是短期奖励的最大化,而是长期累积奖励的最大化。强化学习过程中,系统不断地试错,以达到学习最优策略地目的。 14 | 15 | ## 半监督学习与主动学习 16 | * 半监督学习指利用标注数据和未标注数据学习预测模型地机器学习问题。其旨在利用未标注数据中的信息,辅助标注数据,进行监督学习,以较低的成本达到较好的学习效果。 17 | * 主动学习是指机器不断主动给出实例让教师进行标注,然后利用标注数据学习预测模型的机器学习问题。主动学习的目标是找出对学习最有帮助的实例让教师标注,以较小的标注代价达到较好的学习效果。 18 | * 这两种学习更接近监督学习。 19 | 20 | ## 实现统计学习方法的步骤 21 | 22 | 23 | 1. 得到一个有限的训练数据集合 24 | 2. 确定包含所有可能的模型的**假设空间**,即学习**模型的集合** 25 | 3. 确定模型选择的准则,即学习的**策略** 26 | 1. 实现求解最优模型的算法,即学习的**算法** 27 | 4. 通过学习方法选择最优的模型 28 | 5. 利用学习的最优模型对新数据进行预测或分析 29 | 30 | * 在上述步骤中涵盖了统计学习方法三要素:模型,策略,算法 31 | 32 | 33 | * 在监督学习过程中,模型就是所要学习的**条件概率分布**或者**决策函数**。 34 | 注意书中的这部分描述,整理了一下到表格里: 35 | 36 | | | 假设空间$\mathcal F$ | 输入空间$\mathcal X$ | 输出空间$\mathcal Y$ | 参数空间 | 37 | | ------------ | ------------------------------------------------------------ | ---------------- | ---------------- | ------------- | 38 | | 决策函数 | $\mathcal F =\{f$\|$Y=f_{\theta}(x), \theta \in \bf R \it ^n\}$ | 变量 | 变量 | $\bf R\it ^n$ | 39 | | 条件概率分布 | $\mathcal F =\{P$\|$P_\theta(Y$\|$X), \theta \in \bf R \it ^n\}$ | 随机变量 | 随机变量 | $\bf R\it ^n$ | 40 | 41 | ## 损失函数与风险函数 42 | 43 | * **损失函数**度量模型**一次预测**的好坏,**风险函数**度量**平均意义**下模型预测的好坏。 44 | 45 | * 损失函数(loss function)或代价函数(cost function)定义为给定输入$X$的**预测值$f(X)$**和**真实值$Y$**之间的**非负实值**函数,记作$L(Y,f(X))$。 46 | 47 | * 风险函数(risk function)或期望损失(expected loss)和模型的泛化误差的形式是一样的 48 | $R_{exp}(f)=E_p[L(Y, f(X))]=\int_{\mathcal X\times\mathcal Y}L(y,f(x))P(x,y)\, {\rm d}x{\rm d}y$ 49 | 上式是模型$f(X)$关于联合分布$P(X,Y)$的**平均意义下的**损失(期望损失),但是因为$P(X,Y)$是未知的,所以前面的用词是**期望**,以及**平均意义下的**。这个表示其实就是损失的均值,反映了对整个数据的预测效果的好坏。 50 | 51 | * **经验风险**(empirical risk)或**经验损失**(empirical loss) 52 | $R_{emp}(f)=\frac{1}{N}\sum^{N}_{i=1}L(y_i,f(x_i))$ 53 | 上式是模型$f$关于**训练样本集**的平均损失。根据大数定律,当样本容量N趋于无穷大时,经验风险趋于期望风险。 54 | 55 | * **结构风险**(structural risk) 56 | $R_{srm}(f)=\frac{1}{N}\sum_{i=1}^{N}L(y_i,f(x_i))+\lambda J(f)$ 57 | 其中$J(f)$为模型复杂度, $\lambda \geqslant 0$是系数,用以权衡经验风险和模型复杂度。 58 | 59 | ## 常用损失函数 60 | 61 | 损失函数数值越小,模型就越好 62 | 63 | * 0-1损失 64 | $L(Y,f(X))=\begin{cases}1, Y \neq f(X) \\0, Y=f(X) \end{cases}$ 65 | * 平方损失 66 | $L(Y,f(X))=(Y-f(X))^2$ 67 | * 绝对损失 68 | $L(Y,f(X))=|Y-f(X)|$ 69 | 70 | * 对数损失 71 | $L(Y,P(Y|X))=−logP(Y|X)$ 72 | 73 | 74 | 75 | ## ERM与SRM 76 | 77 | 经验风险最小化(ERM)与结构风险最小化(SRM) 78 | 79 | * **极大似然估计**是经验风险最小化的一个例子。当模型是条件概率分布,损失函数是对数损失函数时,经验风险最小化等价于极大似然估计,下面习题1.2中给出了证明。 80 | * 结构风险最小化等价于**正则化** 81 | * **贝叶斯估计**中的**最大后验概率估计**是结构风险最小化的一个例子。当模型是条件概率分布,损失函数是对数损失函数,**模型复杂度由模型的先验概率表示**时,结构风险最小化等价于最大后验概率估计。 82 | 83 | ## 算法 84 | * 算法是指学习模型的具体计算方法。统计学习基于训练数据集,根据学习策略,从假设空间中选择最优模型,最后需要考虑用什么杨的计算方法来求解最优模型。 85 | 86 | ## 模型评估与选择 87 | * 训练误差和测试误差是模型关于数据集的平均损失。 88 | 89 | * 注意:统计学习方法具体采用的损失函数未必是评估时使用的损失函数。 90 | * 过拟合是指学习时选择的模型所包含的参数过多,以至出现这一模型对已知数据预测得很好,但对未知数据预测得很差的现象。可以说模型选择旨在避免过拟合并提高模型的预测能力。 91 | 92 | ## 正则化与交叉验证 93 | * 模型选择的典型方法是**正则化**.。正则化项一般是模型复杂度的单调递增函数,模型越复杂,正则化就越大。比如,正则化项可以是模型参数向量的范数。 94 | * $L(w)=\frac{1}{N}\sum_{i=1}^{N}(f(x_i;w)-y_i)^2+\frac{\lambda}{2}\|w\|^2$ 95 | * $\|w\|$表示向量$w$的$L_2$范数 96 | * 正则化符合奥卡姆剃刀原理:如无必要,勿增实体。在应用于模型选择中时,可以理解为:在所有可能选择的模型中,能够很好地解释已知数据并且十分简单的才是最好的模型,也是应该选择的模型。 97 | * 交叉验证的基本想法时重复地利用数据;把给定地数据进行切分,将切分的数据集组合为训练集和测试集,在此基础上反复地进行训练、测试以及模型选择。 98 | * 主要有简单交叉验证,S折交叉验证,留一交叉验证三种。 99 | * 在算法学习的过程中,测试集可能是固定的,但是验证集和训练集可能是变化的。比如S折交叉验证的情况下,分成S折之后,其中的S-1折作为训练集,1折作为验证集,计算这S个模型每个模型的平均测试误差,最后选择平均测试误差最小的模型。这个过程中用来验证模型效果的那一折数据就是验证集。 100 | 101 | ## 生成模型与判别模型 102 | 103 | **监督学习方法**可分为**生成方法**(generative approach)与**判别方法**(discriminative approach) 104 | 105 | * **生成方法(generative approach)** 106 | 107 | - 可以还原出**联合概率分布**$P(X,Y)$ 108 | - 收敛速度快, 当样本容量增加时, 学到的模型可以更快收敛到真实模型 109 | - 当存在隐变量时仍可以用 110 | 111 | * **判别方法(discriminative approach)** 112 | 113 | - 直接学习**条件概率**$P(Y|X)$或者**决策函数**$f(X)$ 114 | - 直接面对预测, 往往学习准确率更高 115 | - 可以对数据进行各种程度的抽象, 定义特征并使用特征, 可以简化学习问题 116 | 117 | # 习题解答 118 | 119 | * **1.1** 说明伯努利模型的极大似然估计以及贝叶斯估计中的统计学方法三要素 120 | 121 | * 伯努利模型是定义在取值为0与1的随机变量上的概率分布。统计学分为两派:经典统计学派和贝叶斯统计学派。两者的不同主要是,经典统计学派认为模型已定,参数未知,参数是固定的,只是还不知道;贝叶斯统计学派是通过观察到的现象对概率分布中的主观认定不断进行修正。 122 | 123 | * **极大似然估计**用的是经典统计学派的策略,**贝叶斯估计**用的是贝叶斯统计学派的策略;为了得到使经验风险最小的参数值,使用的算法都是对经验风险求导,使导数为0。 124 | 125 | * 定义随机变量$A$为一次伯努利试验的结果,$A$的取值为$\{0,1\}$,概率分布为$P(A)$: 126 | $$P(A=1)=θ,P(A=0)=1-θ$$ 127 | * 极大似然估计 128 | $$L(θ)=\prod_{i=1}^nP(A_i)=θ^k(1-θ)^{n-k}$$ 129 | $$θ=\arg\max_{θ}L(θ)=\frac{k}{n}$$ 130 | 上述估计通过取对数求导得到,$A_i$为第$i$次随机试验 131 | 132 | 133 | * 贝叶斯估计 134 | $$P(θ|A_1,A_2,…,A_n)=\frac{P(A_1,A_2,…,A_n|θ)P(θ)}{P(A_1,A_2,…,A_n)}$$ 135 | 136 | 根据观察到的结果修正$θ$,也就是假设$θ$是随机变量,$θ$服从β分布,有很多个可能的取值,我们要取的值是在已知观察结果的条件下使$θ$出现概率最大的值。上式分母是不变的,求分子最大就可以。 137 | 138 | $$ 139 | \begin{aligned} 140 | \theta 141 | &=arg\max \limits_\theta {P(A_1,A_2,...,A_n|\theta)P(\theta)} \\ 142 | &= arg\max \limits_\theta {\prod_{i=1}^{n}P(A_i|\theta)P(\theta)} \\ 143 | &=arg \max \limits_\theta {\theta^k(1-\theta)^{n-k}\theta^{a-1}(1-\theta)^{b-1}} \\ 144 | &=\frac{k+(a-1)}{n+(a-1)+(b-1)} 145 | \end{aligned}$$ 146 | 147 | β分布是一个作为伯努利分布和二项式分布的共轭先验分布的密度函数,是指一组定义在$(0,1)$区间的连续概率分布,有两个参数α,β>0。选定参数后就可以确定$\theta$。 148 | 149 | * 统计学习方法的三要素为模型,策略,算法。 150 | 151 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190524102938764.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x5YzQ0ODEzNDE4,size_16,color_FFFFFF,t_70) 152 | 153 | * **1.2** 通过经验风险最小化推导极大似然估计。证明模型是条件概率分布,当损失函数是对数损失函数时,经验风险最小化等价于极大似然估计。 154 | * 模型是条件概率分布:$P_θ(Y|X)$, 155 | 损失函数是对数损失函数:$L(Y,P_θ(Y|X))=−logP_θ(Y|X)$ 156 | 经验风险为:$$ \begin{aligned} 157 | R_{emp}(f)&=\frac{1}{N}\sum_{i=1}^{N}L(y_i,f(x_i)) \\ 158 | &=\frac{1}{N}\sum_{i=1}^{N}-logP(y_i|x_i) \\ 159 | &=-\frac{1}{N}\sum_{i=1}^{N}logP(y_i|x_i) 160 | \end{aligned}$$ 161 | 162 | 163 | * 极大似然估计的似然函数为: 164 | $$L(\theta)=\prod_DP_{\theta}(Y|X)$$ 165 | * 取对数 166 | $$log(L(\theta))=\sum_DlogP_{\theta}(Y|X)$$ 167 | $$arg\max_\theta\sum_DlogP_{\theta}(Y|X)=arg\min_{\theta}\sum_D-logP_{\theta}(Y|X)$$ 168 | 169 | * 因此,当损失函数是对数损失函数时,经验风险最小化等价于极大似然估计。 170 | -------------------------------------------------------------------------------- /Chapter2/2d.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/librauee/Statistical-Learning/c988aea60ba0ed5a01b10d31f4a823eb3c75f3b7/Chapter2/2d.png -------------------------------------------------------------------------------- /Chapter2/README.md: -------------------------------------------------------------------------------- 1 | # 感知机 2 | ## 学习笔记 3 | * 感知机是二类分类的线性模型,属于**判别模型** 4 | * 感知机学习旨在求出将训练数据进行线性划分的分离超平面.是神经网络和支持向量机的基础 5 | * 损失函数选择 6 | * 损失函数的一个自然选择是误分类点的总数,但是,这样的损失函数不是参数$w,b$的连续可导函数,不易优化 7 | * 损失函数的另一个选择是误分类点到超平面$S$的总距离,这正是感知机所采用的 8 | 9 | * 感知机学习的经验风险函数(损失函数) 10 | $$ 11 | L(w,b)=-\sum_{x_i\in M}y_i(w\cdot x_i+b) 12 | $$ 13 | 其中$M$是误分类点的集合,给定训练数据集$T$,损失函数$L(w,b)$是$w$和$b$的连续可导函数 14 | 15 | #### 原始形式算法 16 | 17 | > 输入:训练数据集$T=\{(x_1,y_1),(x_2,y_2),\dots,(x_N,y_N)\},x_i\in R^n,y_i\in {\{+1,-1\}},i=1,2,3,\dots,N;学习率0<\eta\leqslant 1$ 18 | > 19 | > 输出:$w,b;感知机模型f(x)=sign(w\cdot x+b)$ 20 | > 21 | > 1. 选取初值$w_0,b_0$ 22 | > 23 | > 1. 训练集中选取数据$(x_i,y_i)$ 24 | > 25 | > 1. 如果$y_i(w\cdot x_i+b)\leqslant 0$ 26 | > $$ 27 | > w\leftarrow w+\eta y_ix_i \\ 28 | > b\leftarrow b+\eta y_i 29 | > $$ 30 | > 4. 转至(2),直至训练集中没有误分类点 31 | 32 | * 这个是原始形式中的迭代公式,可以对$x​$补1,将$w​$和$b​$合并在一起,合在一起的这个叫做扩充权重向量 33 | 34 | #### 对偶形式算法 35 | 36 | * 对偶形式的基本思想是将$w$和$b$表示为实例$x_i$和标记$y_i$的线性组合的形式,通过求解其系数而求得$w$和$b$。 37 | 38 | 39 | 40 | > 输入:$T=\{(x_1,y_1),(x_2,y_2),\dots,(x_N,y_N)\},x_i\in R^n,y_i\in {\{+1,-1\}},i=1,2,3,\dots,N;学习率0<\eta\leqslant 1$ 41 | > 42 | > 输出: 43 | $\alpha ,b; 感知机模型f(x)=sign\left(\sum_{j=1}^N\alpha_jy_jx_j\cdot x+b\right), 44 | \alpha=(\alpha_1,\alpha_2,\cdots,\alpha_N)^T$ 45 | > 46 | > 1. $\alpha \leftarrow 0,b\leftarrow 0​$ 47 | > 48 | > 1. 训练集中选取数据$(x_i,y_i)$ 49 | > 50 | > 1. 如果$y_i\left(\sum_{j=1}^N\alpha_jy_jx_j\cdot x+b\right) \leqslant 0​$ 51 | > $$ 52 | > \alpha_i\leftarrow \alpha_i+\eta \\ 53 | > b\leftarrow b+\eta y_i 54 | > $$ 55 | > 56 | > 4. 转至(2),直至训练集中没有误分类点 57 | 58 | * **Gram matrix** 59 | 60 | 对偶形式中,训练实例仅以内积的形式出现。 61 | 62 | 为了方便可预先将训练集中的实例间的内积计算出来并以矩阵的形式存储,这个矩阵就是所谓的Gram矩阵 63 | $$ 64 | G=[x_i\cdot x_j]_{N\times N} 65 | $$ 66 | 67 | 68 | 69 | 70 | ## 习题解答 71 | * 2.1 Minsky 与 Papert 指出:感知机因为是线性模型,所以不能表示复杂的函数,如异或 (XOR)。验证感知机为什么不能表示异或。 72 | * 我们显然无法使用一条直线将两类样本划分,异或问题是线性不可分的。 73 | * 可以借助下面动图理解 74 | 75 | 76 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190527153433865.gif#pic_center) 77 | 78 | * 2.2 模仿例题 2.1,构建从训练数据求解感知机模型的例子。 79 | * 感知机的训练过程如上所述,取与原例题相同的数据,计算出不同的结果 80 | * x = [3 3; 4 3; 1 1]; 81 | y = [1; 1; -1]; 82 | * 根据程序运行可得: 83 | * eg1: 84 | 误分类点为: [3 3] 此时的w和b为: [[0.][0.]] 0 85 | 误分类点为: [1 1] 此时的w和b为: [[3.][3.]] 1 86 | 误分类点为: [1 1] 此时的w和b为: [[2.][2.]] 0 87 | 误分类点为: [1 1] 此时的w和b为: [[1.][1.]] -1 88 | 误分类点为: [3 3] 此时的w和b为: [[0.][0.]] -2 89 | 误分类点为: [1 1] 此时的w和b为: [[3.][3.]] -1 90 | 误分类点为: [1 1] 此时的w和b为: [[2. [2.]] -2 91 | 最终训练得到的w和b为: [[1.] [1.]] -3 92 | 即$f(x)=sign(x^{(1)}+x^{(2)}-3)$ 93 | * eg2: 94 | 误分类点为: [1 1] 此时的w和b为: [[0.] [0.]] 0 95 | 误分类点为: [4 3] 此时的w和b为: [[-1.] [-1.]] -1 96 | 误分类点为: [1 1] 此时的w和b为: [[3.] [2.]] 0 97 | 误分类点为: [1 1] 此时的w和b为: [[2.] [1.]] -1 98 | 最终训练得到的w和b为: [[1.] [0.]] -2 99 | 即$f(x)=sign(x^{(1)}-2)$ 100 | -------------------------------------------------------------------------------- /Chapter2/perceptron.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon May 27 16:22:53 2019 4 | 5 | @author: Administrator 6 | """ 7 | 8 | 9 | import numpy as np 10 | import matplotlib.pyplot as plt 11 | 12 | #1、创建数据集 13 | def createdata(): 14 | samples=np.array([[3,3],[4,3],[1,1]]) 15 | labels=np.array([1,1,-1]) 16 | return samples,labels 17 | 18 | #训练感知机模型 19 | class Perceptron: 20 | def __init__(self,x,y,a=1): 21 | self.x=x 22 | self.y=y 23 | self.w=np.zeros((x.shape[1],1))#初始化权重,w1,w2均为0 24 | self.b=0 25 | self.a=1#学习率 26 | self.numsamples=self.x.shape[0] 27 | self.numfeatures=self.x.shape[1] 28 | 29 | def sign(self,w,b,x): 30 | y=np.dot(x,w)+b 31 | return int(y) 32 | 33 | def update(self,label_i,data_i): 34 | tmp=label_i*self.a*data_i 35 | tmp=tmp.reshape(self.w.shape) 36 | #更新w和b 37 | self.w+=tmp 38 | self.b+=label_i*self.a 39 | 40 | def train(self): 41 | isFind=False 42 | while not isFind: 43 | count=0 44 | for i in range(self.numsamples): 45 | tmpY=self.sign(self.w,self.b,self.x[i,:]) 46 | if tmpY*self.y[i]<=0: 47 | #如果是一个误分类实例点 48 | print('误分类点为:',self.x[i,:],'此时的w和b为:',self.w,self.b) 49 | count+=1 50 | self.update(self.y[i],self.x[i,:]) 51 | if count==0: 52 | print('最终训练得到的w和b为:',self.w,self.b) 53 | isFind=True 54 | return self.w,self.b 55 | 56 | #画图描绘 57 | class Picture: 58 | def __init__(self,data,w,b): 59 | self.b=b 60 | self.w=w 61 | plt.figure(1) 62 | plt.title('Perceptron Learning Algorithm',size=14) 63 | plt.xlabel('x0-axis',size=14) 64 | plt.ylabel('x1-axis',size=14) 65 | 66 | xData=np.linspace(0,5,100) 67 | yData=self.expression(xData) 68 | plt.plot(xData,yData,color='r',label='sample data') 69 | 70 | plt.scatter(data[0][0],data[0][1],s=50) 71 | plt.scatter(data[1][0],data[1][1],s=50) 72 | plt.scatter(data[2][0],data[2][1],s=50,marker='x') 73 | plt.savefig('2d.png',dpi=75) 74 | 75 | def expression(self,x): 76 | y=(-self.b-self.w[0]*x)/self.w[1]#注意在此,把x0,x1当做两个坐标轴,把x1当做自变量,x2为因变量 77 | return y 78 | 79 | def Show(self): 80 | plt.show() 81 | 82 | 83 | if __name__ == '__main__': 84 | samples,labels=createdata() 85 | myperceptron=Perceptron(x=samples,y=labels) 86 | weights,bias=myperceptron.train() 87 | Picture=Picture(samples,weights,bias) 88 | Picture.Show() 89 | 90 | 91 | -------------------------------------------------------------------------------- /Chapter2/perceptron_duality.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Tue May 28 09:28:22 2019 4 | 5 | @author: Administrator 6 | """ 7 | import numpy as np 8 | 9 | x=np.array([[3,3],[4,3],[1,1]]) 10 | y=np.array([1,1,-1]) 11 | a = np.zeros(len(x), np.float) 12 | b = 0.0 13 | Gram = None 14 | 15 | #calculate the Gram matrix 16 | def cal_gram(): 17 | 18 | g = np.empty((len(x), len(x)), np.int) 19 | for i in range(len(x)): 20 | for j in range(len(x)): 21 | g[i][j] = np.dot(x[i],x[j]) 22 | return g 23 | 24 | #update parameters using stochastic gradient descent 25 | def update(i): 26 | 27 | global a, b 28 | a[i] += 1 29 | b = b + y[i] 30 | print(a) 31 | print(b) 32 | 33 | 34 | # calculate the judge condition 35 | def cal(i): 36 | global a, b, x, y 37 | res = np.dot(a * y, Gram[i]) 38 | res = (res + b) * y[i] 39 | return res 40 | 41 | # check if the hyperplane can classify the examples correctly 42 | def check(): 43 | global a, b, x, y 44 | flag = False 45 | for i in range(len(x)): 46 | if cal(i) <= 0: 47 | flag = True 48 | update(i) 49 | if not flag: 50 | w = np.dot(a * y, x) 51 | print ("RESULT: w: " + str(w) + " b: " + str(b)) 52 | return False 53 | return True 54 | 55 | 56 | if __name__ == "__main__": 57 | Gram = cal_gram() # initialize the Gram matrix 58 | for i in range(1000): 59 | if not check(): 60 | break -------------------------------------------------------------------------------- /Chapter3/3.1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sun Jun 2 13:24:51 2019 4 | 5 | @author: Administrator 6 | """ 7 | import math 8 | 9 | x=[[1,1],[5,1],[4,4]] 10 | 11 | def distance(x,y,p=2): 12 | if len(x)!=len(y): 13 | return 0 14 | elif len(x)>1: 15 | sum1=0 16 | for i in range(len(x)): 17 | sum1+=math.pow(abs(x[i]-y[i]),p) 18 | return math.pow(sum1,1/p) 19 | 20 | nearest=min(distance(x[0],x[1]),distance(x[0],x[2])) 21 | 22 | print(nearest) 23 | -------------------------------------------------------------------------------- /Chapter3/KNN_appointment.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sat Mar 30 20:29:36 2019 4 | 5 | @author: Administrator 6 | """ 7 | 8 | from matplotlib.font_manager import FontProperties 9 | import matplotlib.lines as mlines 10 | import matplotlib.pyplot as plt 11 | import numpy as np 12 | import operator 13 | 14 | 15 | #KNN算法 16 | def classify0(inX, dataSet, labels, k): 17 | 18 | dataSetSize = dataSet.shape[0] 19 | diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet 20 | sqDiffMat = diffMat**2 21 | sqDistances = sqDiffMat.sum(axis=1) 22 | distances = sqDistances**0.5 23 | sortedDistIndices = distances.argsort() 24 | classCount = {} 25 | for i in range(k): 26 | voteIlabel = labels[sortedDistIndices[i]] 27 | classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 28 | sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) 29 | print(sortedClassCount) 30 | #返回次数最多的类别,即所要分类的类别 31 | return sortedClassCount[0][0] 32 | 33 | 34 | #打开并解析文件,对数据进行分类:1代表不喜欢,2代表魅力一般,3代表极具魅力 35 | 36 | def file2matrix(filename): 37 | 38 | fr = open(filename,'r',encoding = 'utf-8') 39 | arrayOLines = fr.readlines() 40 | #针对有BOM的UTF-8文本,应该去掉BOM,否则后面会引发错误。 41 | arrayOLines[0]=arrayOLines[0].lstrip('\ufeff') 42 | numberOfLines = len(arrayOLines) 43 | #返回的NumPy矩阵,解析完成的数据:numberOfLines行,3列 44 | returnMat = np.zeros((numberOfLines,3)) 45 | #返回的分类标签向量 46 | classLabelVector = [] 47 | index = 0 #行索引 48 | 49 | for line in arrayOLines: 50 | 51 | line = line.strip() 52 | #使用s.split(str="",num=string,cout(str))将字符串根据'\t'分隔符进行切片。 53 | listFromLine = line.split('\t') 54 | #将数据前三列提取出来,存放到returnMat的NumPy矩阵中,也就是特征矩阵 55 | returnMat[index,:] = listFromLine[0:3] 56 | #根据文本中标记的喜欢的程度进行分类,1代表不喜欢,2代表魅力一般,3代表极具魅力 57 | # 对于datingTestSet2.txt 最后的标签是已经经过处理的 标签已经改为了1, 2, 3 58 | if listFromLine[-1] == 'didntLike': 59 | classLabelVector.append(1) 60 | elif listFromLine[-1] == 'smallDoses': 61 | classLabelVector.append(2) 62 | elif listFromLine[-1] == 'largeDoses': 63 | classLabelVector.append(3) 64 | index += 1 65 | return returnMat, classLabelVector 66 | 67 | 68 | def showdatas(datingDataMat, datingLabels): 69 | #设置汉字格式 70 | font = FontProperties(fname=r"c:\windows\fonts\simsunb.ttf", size=14) 71 | fig, axs = plt.subplots(nrows=2, ncols=2,sharex=False, sharey=False, figsize=(13,8)) 72 | 73 | numberOfLabels = len(datingLabels) 74 | LabelsColors = [] 75 | for i in datingLabels: 76 | if i == 1: 77 | LabelsColors.append('black') 78 | if i == 2: 79 | LabelsColors.append('orange') 80 | if i == 3: 81 | LabelsColors.append('red') 82 | #画出散点图,以datingDataMat矩阵的第一(飞行常客例程)、第二列(玩游戏)数据画散点数据,散点大小为15,透明度为0.5 83 | axs[0][0].scatter(x=datingDataMat[:,0], y=datingDataMat[:,1], color=LabelsColors,s=15, alpha=.5) 84 | #设置标题,x轴label,y轴label 85 | axs0_title_text = axs[0][0].set_title(u'每年获得的飞行常客里程数与玩视频游戏所消耗时间占比',FontProperties=font) 86 | axs0_xlabel_text = axs[0][0].set_xlabel(u'每年获得的飞行常客里程数',FontProperties=font) 87 | axs0_ylabel_text = axs[0][0].set_ylabel(u'玩视频游戏所消耗时间占比',FontProperties=font) 88 | plt.setp(axs0_title_text, size=9, weight='bold', color='red') 89 | plt.setp(axs0_xlabel_text, size=7, weight='bold', color='black') 90 | plt.setp(axs0_ylabel_text, size=7, weight='bold', color='black') 91 | 92 | #画出散点图,以datingDataMat矩阵的第一(飞行常客例程)、第三列(冰激凌)数据画散点数据,散点大小为15,透明度为0.5 93 | axs[0][1].scatter(x=datingDataMat[:,0], y=datingDataMat[:,2], color=LabelsColors,s=15, alpha=.5) 94 | #设置标题,x轴label,y轴label 95 | axs1_title_text = axs[0][1].set_title(u'每年获得的飞行常客里程数与每周消费的冰激淋公升数',FontProperties=font) 96 | axs1_xlabel_text = axs[0][1].set_xlabel(u'每年获得的飞行常客里程数',FontProperties=font) 97 | axs1_ylabel_text = axs[0][1].set_ylabel(u'每周消费的冰激淋公升数',FontProperties=font) 98 | plt.setp(axs1_title_text, size=9, weight='bold', color='red') 99 | plt.setp(axs1_xlabel_text, size=7, weight='bold', color='black') 100 | plt.setp(axs1_ylabel_text, size=7, weight='bold', color='black') 101 | 102 | #画出散点图,以datingDataMat矩阵的第二(玩游戏)、第三列(冰激凌)数据画散点数据,散点大小为15,透明度为0.5 103 | axs[1][0].scatter(x=datingDataMat[:,1], y=datingDataMat[:,2], color=LabelsColors,s=15, alpha=.5) 104 | #设置标题,x轴label,y轴label 105 | axs2_title_text = axs[1][0].set_title(u'玩视频游戏所消耗时间占比与每周消费的冰激淋公升数',FontProperties=font) 106 | axs2_xlabel_text = axs[1][0].set_xlabel(u'玩视频游戏所消耗时间占比',FontProperties=font) 107 | axs2_ylabel_text = axs[1][0].set_ylabel(u'每周消费的冰激淋公升数',FontProperties=font) 108 | plt.setp(axs2_title_text, size=9, weight='bold', color='red') 109 | plt.setp(axs2_xlabel_text, size=7, weight='bold', color='black') 110 | plt.setp(axs2_ylabel_text, size=7, weight='bold', color='black') 111 | #设置图例 112 | didntLike = mlines.Line2D([], [], color='black', marker='.', 113 | markersize=6, label='didntLike') 114 | smallDoses = mlines.Line2D([], [], color='orange', marker='.', 115 | markersize=6, label='smallDoses') 116 | largeDoses = mlines.Line2D([], [], color='red', marker='.', 117 | markersize=6, label='largeDoses') 118 | #添加图例 119 | axs[0][0].legend(handles=[didntLike,smallDoses,largeDoses]) 120 | axs[0][1].legend(handles=[didntLike,smallDoses,largeDoses]) 121 | axs[1][0].legend(handles=[didntLike,smallDoses,largeDoses]) 122 | #显示图片 123 | plt.show() 124 | 125 | 126 | 127 | #对数据进行归一化 128 | def autoNorm(dataSet): 129 | #获得数据的最小值 130 | minVals = dataSet.min(0) 131 | maxVals = dataSet.max(0) 132 | #最大值和最小值的范围 133 | ranges = maxVals - minVals 134 | #shape(dataSet)返回dataSet的矩阵行列数 135 | normDataSet = np.zeros(np.shape(dataSet)) 136 | #返回dataSet的行数 137 | m = dataSet.shape[0] 138 | #原始值减去最小值 139 | normDataSet = dataSet - np.tile(minVals, (m, 1)) 140 | #除以最大和最小值的差,得到归一化数据 141 | normDataSet = normDataSet / np.tile(ranges, (m, 1)) 142 | #返回归一化数据结果,数据范围,最小值 143 | return normDataSet, ranges, minVals 144 | 145 | 146 | 147 | #取百分之十的数据作为测试数据,检测分类器的正确性 148 | 149 | def datingClassTest(): 150 | #打开的文件名 151 | filename = "datingTestSet.txt" 152 | #将返回的特征矩阵和分类向量分别存储到datingDataMat和datingLabels中 153 | datingDataMat, datingLabels = file2matrix(filename) 154 | #取所有数据的百分之十 155 | hoRatio = 0.10 156 | #数据归一化,返回归一化后的矩阵,数据范围,数据最小值 157 | normMat, ranges, minVals = autoNorm(datingDataMat) 158 | #获得normMat的行数 159 | m = normMat.shape[0] 160 | #百分之十的测试数据的个数 161 | numTestVecs = int(m * hoRatio) 162 | #分类错误计数 163 | errorCount = 0.0 164 | 165 | for i in range(numTestVecs): 166 | #前numTestVecs个数据作为测试集,后m-numTestVecs个数据作为训练集 167 | classifierResult = classify0(normMat[i,:], normMat[numTestVecs:m,:], 168 | datingLabels[numTestVecs:m], 4) 169 | print("分类结果:%s\t真实类别:%d" % (classifierResult, datingLabels[i])) 170 | if classifierResult != datingLabels[i]: 171 | errorCount += 1.0 172 | print("错误率:%f%%" %(errorCount/float(numTestVecs)*100)) 173 | 174 | 175 | #通过输入一个人的三维特征,进行分类输出 176 | 177 | def classifyPerson(): 178 | 179 | resultList = ['讨厌','有些喜欢','非常喜欢'] 180 | precentTats = float(input("玩视频游戏所耗时间百分比:")) 181 | ffMiles = float(input("每年获得的飞行常客里程数:")) 182 | iceCream = float(input("每周消费的冰激淋公升数:")) 183 | filename = "datingTestSet.txt" 184 | #打开并处理数据 185 | datingDataMat, datingLabels = file2matrix(filename) 186 | #训练集归一化 187 | normMat, ranges, minVals = autoNorm(datingDataMat) 188 | #生成NumPy数组,测试集 189 | inArr = np.array([ffMiles, precentTats, iceCream]) 190 | #测试集归一化 191 | norminArr = (inArr - minVals) / ranges 192 | #返回分类结果 193 | classifierResult = classify0(norminArr, normMat, datingLabels, 3) 194 | #打印结果 195 | print("你可能%s这个人" % (resultList[classifierResult-1])) 196 | 197 | if __name__ == '__main__': 198 | datingClassTest() 199 | -------------------------------------------------------------------------------- /Chapter3/KNN_movie.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sat Mar 30 19:58:34 2019 4 | 5 | @author: Administrator 6 | """ 7 | 8 | import numpy as np 9 | import operator 10 | 11 | def createDataSet(): 12 | #四组二维特征 13 | group = np.array([[1,101],[5,89],[108,5],[115,8]]) 14 | #四组特征的标签 15 | labels = ['爱情片','爱情片','动作片','动作片'] 16 | return group, labels 17 | 18 | def classify(inX, dataSet, labels, k): 19 | #numpy函数shape[0]返回dataSet的行数 20 | dataSetSize = dataSet.shape[0] 21 | #沿横轴重复inX共1次,沿竖轴方向重复inX共dataSetSize次 22 | diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet 23 | #二维特征相减后平方 24 | sqDiffMat = diffMat**2 25 | sqDistances = sqDiffMat.sum(axis=1) #沿横轴相加 26 | distances = sqDistances**0.5 27 | #返回distances中元素从小到大排序后的索引值 28 | sortedDistIndices = distances.argsort() 29 | #定一个记录类别次数的字典 30 | classCount = {} 31 | for i in range(k): 32 | #取出前k个元素的类别 33 | voteIlabel = labels[sortedDistIndices[i]] 34 | #dict.get(key,default=None),字典的get()方法,返回指定键的值,如果值不在字典中返回默认值。 35 | #计算类别次数 36 | classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 37 | #python3中用items()替换python2中的iteritems() 38 | #key=operator.itemgetter(1)根据字典的值进行排序 39 | #key=operator.itemgetter(0)根据字典的键进行排序 40 | #reverse降序排序字典 41 | sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) 42 | #返回次数最多的类别,即所要分类的类别 43 | return sortedClassCount[0][0] 44 | 45 | def main(): 46 | group, labels = createDataSet() 47 | test = [19,200] 48 | test_class = classify(test, group, labels, 3) 49 | print(test_class) 50 | 51 | if __name__ == '__main__': 52 | main() 53 | 54 | -------------------------------------------------------------------------------- /Chapter3/README.md: -------------------------------------------------------------------------------- 1 | # k近邻法 2 | 3 | ## 学习笔记 4 | * k值的选择、距离度量及分类决策规则是k近邻法的三要素 5 | * 三要素在算法之中完整体现出来: 6 | ### 算法 7 | 8 | >输入: $T=\{(x_1,y_1),(x_2,y_2),\dots,(x_N,y_N)\}, x_i\in X \sube{\bf{R}^n}, y_i\in Y=\{c_1,c_2,\dots, c_k\}$; 实例特征向量$x$ 9 | 输出: 实例所属的$y$ 10 | 步骤: 11 | >1. 根据指定的**距离度量**,在$T$中查找$x$的**最近邻的$k$个点**,覆盖这$k$个点的$x$的邻域定义为$N_k(x)$ 12 | >1. 在$N_k(x)$中应用**分类决策规则**决定$x$的类别$y$ 13 | $$ 14 | y=\arg\max_{c_j}\sum_{x_i\in N_k(x)}I(y_i=c_j), i=1,2,\dots,N, j=1,2,\dots,K 15 | $$ 16 | ### 距离度量 17 | * **特征空间**中的两个实例点的距离是两个实例点相似程度的反映。 18 | 1. $p=1$ 对应 曼哈顿距离 19 | 1. $p=2$ 对应 欧氏距离 20 | 1. 任意$p$ 对应 闵可夫斯基距离 21 | 22 | 23 | $$L_p(x_i, x_j)=\left(\sum_{l=1}^{n}{\left|x_{i}^{(l)}-x_{j}^{(l)}\right|^p}\right)^{\frac{1}{p}}$$ 24 | 25 | * 范数是对向量或者矩阵的度量,是一个标量,这个里面两个点之间的$L_p$距离可以认为是两个点坐标差值的$p$范数 26 | 27 | ### k值选择 28 | * k值选择会对算法结果产生重大影响。若选较小,只有与输入实例相似的训练实例才会对预测结果起作用,“学习”的近似误差会减小,但“学习”的估计误差会增大,会对近邻的实例点非常敏感,k值减少意味着整体模型变得复杂,容易发生过拟合;若选较大,与输入实例不相似的训练实例也对预测起作用,从而发生错误 29 | * 通过**交叉验证**选取最优$k$,算是超参数,一般k值会取一个较小的数值 30 | * 在二分类问题中,$k$选择奇数有助于避免平票 31 | 32 | ### 分类决策规则 33 | * 决策规则往往是多数表决(Majority Voting Rule) 34 | * 误分类率 35 | 36 | $$\frac{1}{k}\sum_{x_i\in N_k(x)}{I(y_i\ne c_i)}=1-\frac{1}{k}\sum_{x_i\in N_k(x)}{I(y_i= c_i)}$$ 37 | 38 | * 如果分类损失函数是0-1损失,误分类率最低即经验风险最小。 39 | 40 | 41 | ### kd树 42 | 43 | * k近邻最简单的实现方法是线性扫描,这时候要计算输入实例与每一个训练实例的距离 44 | * 为了提高k近邻的搜索效率,考虑使用树结构存储训练数据,以减少计算距离的次数 45 | * kd树是二叉树,表示对**k维空间的一个划分**,注意这里的k和k近邻的k意义并不相同,**只是习惯上的一致** 46 | * kdTree搜索时效率未必是最优的,这个和样本分布有关系。随机分布样本**kdTree搜索**(这里应该是**最**近邻搜索)的平均计算复杂度是$O(\log N)$,空间维数$K$接近训练样本数$N$时,搜索效率急速下降,几乎$O(N)$ 47 | * kd树的构造:构造根结点,使根结点对应于k维空间中包含所有实例点的超矩形区域;通过递归的方法,不断对k维空间进行切分,生成子节点;直到子区域内没有实例时终止。 48 | ~~~python 49 | k = len(data[0]) # 数据维度 50 | 51 | def CreateNode(split, data_set): # 按第split维划分数据集exset创建KdNode 52 | if not data_set: # 数据集为空 53 | return None 54 | 55 | data_set.sort(key=lambda x: x[split]) 56 | split_pos = len(data_set) // 2 # //为Python中的整数除法 57 | median = data_set[split_pos] # 中位数分割点 58 | split_next = (split + 1) % k # cycle coordinates 59 | 60 | # 递归的创建kd树 61 | return KdNode(median, split, 62 | CreateNode(split_next, data_set[:split_pos]), # 创建左子树 63 | CreateNode(split_next, data_set[split_pos + 1:])) # 创建右子树 64 | self.root = CreateNode(0, data) # 从第0维分量开始构建kd树,返回根节点 65 | 66 | ~~~ 67 | 68 | ### kd树最近邻搜索 69 | * 算法 70 | >输入:已构造的$kd$树,目标点$x$ 71 | >输出:$x$的最近邻 72 | >1. 在$kd$树中找出包含目标点$x$的叶结点:从根结点出发,递归地向下访问$kd$树。若目标点$x$当前维的坐标小于切分点的坐标,则移动到左子结点,否则移动到右子结点。直到子结点为叶结点为止。 73 | >1. 以此叶结点为“当前最近点”。 74 | >1. 递归地向上回退,在每个结点进行以下操作: 75 | > * 如果该点保存地实例点比当前最近点距离目标点更近,则以该实例点为“当前最近点”。 76 | > * 当前最近点一定存在于该结点一个子结点对应地区域。检查该子结点的父结点的另一子结点对应的区域是否有更近的点。具体地,检查另一子结点对应的区域是否与以目标点为球心、以目标点与“当前最近点”间的距离为半径的超球体相交。 77 | > **如果相交**,可能在另一子结点对应的区域内存在距离目标点更近的点,移动到另一个子结点。接着递归地进行最近邻搜索; 78 | > **如果不相交**,向上回退。 79 | >4. 当回退到根结点时,搜索结束。最后的“当前最近点”即为$x$的最近邻点。 80 | 81 | ## 习题解答 82 | 83 | * 3.1 参照图 3.1,在 二维空间中给出实例点,画出 k 为 1 和 2 时的 K 近邻法构成的空间划分,并对其进行比较,体会 K 值选择与模型复杂度及预测准确率的关系。 84 | * k为1时 85 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190603093035295.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x5YzQ0ODEzNDE4,size_16,color_FFFFFF,t_70#pic_center) 86 | * k为2时 87 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190603093201425.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x5YzQ0ODEzNDE4,size_16,color_FFFFFF,t_70#pic_center) 88 | 89 | * 3.2 利用例题 3.2 构造的kd树求点 x=(3,4.5) 的最近邻点。 90 | 91 | * 首先找到包含(3,4.5)的叶节点(4,7),将叶节点作为“当前最近点”; 92 | * 回退到(4,7)的父节点(5,4),将(5,4)作为“当前最近点”。以(3,4.5)为圆心,到“当前最近点”(5,4)距离为半径的圆显然和(5,4)的另一个子节点(2,3)区域相交,因此移动到(2,3); 93 | * 移动到(2,3)后发现,距离(3,4.5)更近,因此将(2,3)作为“当前最近点”,由于(2,3)是叶节点,因此直接回退; 94 | * 回到(5,4)的根节点(7,2),到(7,2)距离大于到“当前最近点”距离,同时(3,4.5)和“当前最近点”距离构成的圆和根节点的另一个子节点的区域不相交,所以搜索结束,得到最近点(2,3)。 95 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190603094841314.png) 96 | * 3.3 参照算法 3.3,写出输出为 x 的 K 近邻的算法。 97 | 98 | 在寻找最近邻节点的时候需要维护一个”当前最近点“,而寻找 K 近邻的时候,就需要维护一个”当前 K 近邻点集“。首先定义一个”当前 K 近邻点集“插入新点操作:如果”当前 K 近邻点集“元素数量小于K,那么直接将新点插入集合;如果”当前 K 近邻点集“元素数量等于K,那么将新节点替换原来集合中最远的节点。 99 | 100 | (1)在 kd 树中找出包含目标点 x 的叶结点:从根结点出发,递归地向下访问树。若目标点 x 当前维的坐标小于切分点的坐标,则移动到左子结点,否则移动到右子结点,直到子结点为叶结点为止; 101 | 102 | (2)如果”当前 K 近邻点集“元素数量小于K或者叶节点距离小于”当前 K 近邻点集“中最远点距离,那么将叶节点插入”当前 K 近邻点集“; 103 | 104 | (3)递归地向上回退,在每个结点进行以下操作: 105 | 106 | * 如果”当前 K 近邻点集“元素数量小于K或者当前节点距离小于”当前 K 近邻点集“中最远点距离,那么将该节点插入”当前 K 近邻点集“, 107 | 108 | * 检查另一子结点对应的区域是否与以目标点为球心、以目标点与于”当前 K 近邻点集“中最远点间的距离为半径的超球体相交。如果相交,可能在另一个子结点对应的区域内存在距目标点更近的点,移动到另一个子结点 . 接着,递归地进行最近邻搜索;如果不相交,向上回退; 109 | 110 | (4)当回退到根结点时,搜索结束,最后的”当前 K 近邻点集“即为 x 的 K 近邻点集。 111 | -------------------------------------------------------------------------------- /Chapter3/datingTestSet.txt: -------------------------------------------------------------------------------- 1 | 40920 8.326976 0.953952 largeDoses 2 | 14488 7.153469 1.673904 smallDoses 3 | 26052 1.441871 0.805124 didntLike 4 | 75136 13.147394 0.428964 didntLike 5 | 38344 1.669788 0.134296 didntLike 6 | 72993 10.141740 1.032955 didntLike 7 | 35948 6.830792 1.213192 largeDoses 8 | 42666 13.276369 0.543880 largeDoses 9 | 67497 8.631577 0.749278 didntLike 10 | 35483 12.273169 1.508053 largeDoses 11 | 50242 3.723498 0.831917 didntLike 12 | 63275 8.385879 1.669485 didntLike 13 | 5569 4.875435 0.728658 smallDoses 14 | 51052 4.680098 0.625224 didntLike 15 | 77372 15.299570 0.331351 didntLike 16 | 43673 1.889461 0.191283 didntLike 17 | 61364 7.516754 1.269164 didntLike 18 | 69673 14.239195 0.261333 didntLike 19 | 15669 0.000000 1.250185 smallDoses 20 | 28488 10.528555 1.304844 largeDoses 21 | 6487 3.540265 0.822483 smallDoses 22 | 37708 2.991551 0.833920 didntLike 23 | 22620 5.297865 0.638306 smallDoses 24 | 28782 6.593803 0.187108 largeDoses 25 | 19739 2.816760 1.686209 smallDoses 26 | 36788 12.458258 0.649617 largeDoses 27 | 5741 0.000000 1.656418 smallDoses 28 | 28567 9.968648 0.731232 largeDoses 29 | 6808 1.364838 0.640103 smallDoses 30 | 41611 0.230453 1.151996 didntLike 31 | 36661 11.865402 0.882810 largeDoses 32 | 43605 0.120460 1.352013 didntLike 33 | 15360 8.545204 1.340429 largeDoses 34 | 63796 5.856649 0.160006 didntLike 35 | 10743 9.665618 0.778626 smallDoses 36 | 70808 9.778763 1.084103 didntLike 37 | 72011 4.932976 0.632026 didntLike 38 | 5914 2.216246 0.587095 smallDoses 39 | 14851 14.305636 0.632317 largeDoses 40 | 33553 12.591889 0.686581 largeDoses 41 | 44952 3.424649 1.004504 didntLike 42 | 17934 0.000000 0.147573 smallDoses 43 | 27738 8.533823 0.205324 largeDoses 44 | 29290 9.829528 0.238620 largeDoses 45 | 42330 11.492186 0.263499 largeDoses 46 | 36429 3.570968 0.832254 didntLike 47 | 39623 1.771228 0.207612 didntLike 48 | 32404 3.513921 0.991854 didntLike 49 | 27268 4.398172 0.975024 didntLike 50 | 5477 4.276823 1.174874 smallDoses 51 | 14254 5.946014 1.614244 smallDoses 52 | 68613 13.798970 0.724375 didntLike 53 | 41539 10.393591 1.663724 largeDoses 54 | 7917 3.007577 0.297302 smallDoses 55 | 21331 1.031938 0.486174 smallDoses 56 | 8338 4.751212 0.064693 smallDoses 57 | 5176 3.692269 1.655113 smallDoses 58 | 18983 10.448091 0.267652 largeDoses 59 | 68837 10.585786 0.329557 didntLike 60 | 13438 1.604501 0.069064 smallDoses 61 | 48849 3.679497 0.961466 didntLike 62 | 12285 3.795146 0.696694 smallDoses 63 | 7826 2.531885 1.659173 smallDoses 64 | 5565 9.733340 0.977746 smallDoses 65 | 10346 6.093067 1.413798 smallDoses 66 | 1823 7.712960 1.054927 smallDoses 67 | 9744 11.470364 0.760461 largeDoses 68 | 16857 2.886529 0.934416 smallDoses 69 | 39336 10.054373 1.138351 largeDoses 70 | 65230 9.972470 0.881876 didntLike 71 | 2463 2.335785 1.366145 smallDoses 72 | 27353 11.375155 1.528626 largeDoses 73 | 16191 0.000000 0.605619 smallDoses 74 | 12258 4.126787 0.357501 smallDoses 75 | 42377 6.319522 1.058602 didntLike 76 | 25607 8.680527 0.086955 largeDoses 77 | 77450 14.856391 1.129823 didntLike 78 | 58732 2.454285 0.222380 didntLike 79 | 46426 7.292202 0.548607 largeDoses 80 | 32688 8.745137 0.857348 largeDoses 81 | 64890 8.579001 0.683048 didntLike 82 | 8554 2.507302 0.869177 smallDoses 83 | 28861 11.415476 1.505466 largeDoses 84 | 42050 4.838540 1.680892 didntLike 85 | 32193 10.339507 0.583646 largeDoses 86 | 64895 6.573742 1.151433 didntLike 87 | 2355 6.539397 0.462065 smallDoses 88 | 0 2.209159 0.723567 smallDoses 89 | 70406 11.196378 0.836326 didntLike 90 | 57399 4.229595 0.128253 didntLike 91 | 41732 9.505944 0.005273 largeDoses 92 | 11429 8.652725 1.348934 largeDoses 93 | 75270 17.101108 0.490712 didntLike 94 | 5459 7.871839 0.717662 smallDoses 95 | 73520 8.262131 1.361646 didntLike 96 | 40279 9.015635 1.658555 largeDoses 97 | 21540 9.215351 0.806762 largeDoses 98 | 17694 6.375007 0.033678 smallDoses 99 | 22329 2.262014 1.022169 didntLike 100 | 46570 5.677110 0.709469 didntLike 101 | 42403 11.293017 0.207976 largeDoses 102 | 33654 6.590043 1.353117 didntLike 103 | 9171 4.711960 0.194167 smallDoses 104 | 28122 8.768099 1.108041 largeDoses 105 | 34095 11.502519 0.545097 largeDoses 106 | 1774 4.682812 0.578112 smallDoses 107 | 40131 12.446578 0.300754 largeDoses 108 | 13994 12.908384 1.657722 largeDoses 109 | 77064 12.601108 0.974527 didntLike 110 | 11210 3.929456 0.025466 smallDoses 111 | 6122 9.751503 1.182050 largeDoses 112 | 15341 3.043767 0.888168 smallDoses 113 | 44373 4.391522 0.807100 didntLike 114 | 28454 11.695276 0.679015 largeDoses 115 | 63771 7.879742 0.154263 didntLike 116 | 9217 5.613163 0.933632 smallDoses 117 | 69076 9.140172 0.851300 didntLike 118 | 24489 4.258644 0.206892 didntLike 119 | 16871 6.799831 1.221171 smallDoses 120 | 39776 8.752758 0.484418 largeDoses 121 | 5901 1.123033 1.180352 smallDoses 122 | 40987 10.833248 1.585426 largeDoses 123 | 7479 3.051618 0.026781 smallDoses 124 | 38768 5.308409 0.030683 largeDoses 125 | 4933 1.841792 0.028099 smallDoses 126 | 32311 2.261978 1.605603 didntLike 127 | 26501 11.573696 1.061347 largeDoses 128 | 37433 8.038764 1.083910 largeDoses 129 | 23503 10.734007 0.103715 largeDoses 130 | 68607 9.661909 0.350772 didntLike 131 | 27742 9.005850 0.548737 largeDoses 132 | 11303 0.000000 0.539131 smallDoses 133 | 0 5.757140 1.062373 smallDoses 134 | 32729 9.164656 1.624565 largeDoses 135 | 24619 1.318340 1.436243 didntLike 136 | 42414 14.075597 0.695934 largeDoses 137 | 20210 10.107550 1.308398 largeDoses 138 | 33225 7.960293 1.219760 largeDoses 139 | 54483 6.317292 0.018209 didntLike 140 | 18475 12.664194 0.595653 largeDoses 141 | 33926 2.906644 0.581657 didntLike 142 | 43865 2.388241 0.913938 didntLike 143 | 26547 6.024471 0.486215 largeDoses 144 | 44404 7.226764 1.255329 largeDoses 145 | 16674 4.183997 1.275290 smallDoses 146 | 8123 11.850211 1.096981 largeDoses 147 | 42747 11.661797 1.167935 largeDoses 148 | 56054 3.574967 0.494666 didntLike 149 | 10933 0.000000 0.107475 smallDoses 150 | 18121 7.937657 0.904799 largeDoses 151 | 11272 3.365027 1.014085 smallDoses 152 | 16297 0.000000 0.367491 smallDoses 153 | 28168 13.860672 1.293270 largeDoses 154 | 40963 10.306714 1.211594 largeDoses 155 | 31685 7.228002 0.670670 largeDoses 156 | 55164 4.508740 1.036192 didntLike 157 | 17595 0.366328 0.163652 smallDoses 158 | 1862 3.299444 0.575152 smallDoses 159 | 57087 0.573287 0.607915 didntLike 160 | 63082 9.183738 0.012280 didntLike 161 | 51213 7.842646 1.060636 largeDoses 162 | 6487 4.750964 0.558240 smallDoses 163 | 4805 11.438702 1.556334 largeDoses 164 | 30302 8.243063 1.122768 largeDoses 165 | 68680 7.949017 0.271865 didntLike 166 | 17591 7.875477 0.227085 smallDoses 167 | 74391 9.569087 0.364856 didntLike 168 | 37217 7.750103 0.869094 largeDoses 169 | 42814 0.000000 1.515293 didntLike 170 | 14738 3.396030 0.633977 smallDoses 171 | 19896 11.916091 0.025294 largeDoses 172 | 14673 0.460758 0.689586 smallDoses 173 | 32011 13.087566 0.476002 largeDoses 174 | 58736 4.589016 1.672600 didntLike 175 | 54744 8.397217 1.534103 didntLike 176 | 29482 5.562772 1.689388 didntLike 177 | 27698 10.905159 0.619091 largeDoses 178 | 11443 1.311441 1.169887 smallDoses 179 | 56117 10.647170 0.980141 largeDoses 180 | 39514 0.000000 0.481918 didntLike 181 | 26627 8.503025 0.830861 largeDoses 182 | 16525 0.436880 1.395314 smallDoses 183 | 24368 6.127867 1.102179 didntLike 184 | 22160 12.112492 0.359680 largeDoses 185 | 6030 1.264968 1.141582 smallDoses 186 | 6468 6.067568 1.327047 smallDoses 187 | 22945 8.010964 1.681648 largeDoses 188 | 18520 3.791084 0.304072 smallDoses 189 | 34914 11.773195 1.262621 largeDoses 190 | 6121 8.339588 1.443357 smallDoses 191 | 38063 2.563092 1.464013 didntLike 192 | 23410 5.954216 0.953782 didntLike 193 | 35073 9.288374 0.767318 largeDoses 194 | 52914 3.976796 1.043109 didntLike 195 | 16801 8.585227 1.455708 largeDoses 196 | 9533 1.271946 0.796506 smallDoses 197 | 16721 0.000000 0.242778 smallDoses 198 | 5832 0.000000 0.089749 smallDoses 199 | 44591 11.521298 0.300860 largeDoses 200 | 10143 1.139447 0.415373 smallDoses 201 | 21609 5.699090 1.391892 smallDoses 202 | 23817 2.449378 1.322560 didntLike 203 | 15640 0.000000 1.228380 smallDoses 204 | 8847 3.168365 0.053993 smallDoses 205 | 50939 10.428610 1.126257 largeDoses 206 | 28521 2.943070 1.446816 didntLike 207 | 32901 10.441348 0.975283 largeDoses 208 | 42850 12.478764 1.628726 largeDoses 209 | 13499 5.856902 0.363883 smallDoses 210 | 40345 2.476420 0.096075 didntLike 211 | 43547 1.826637 0.811457 didntLike 212 | 70758 4.324451 0.328235 didntLike 213 | 19780 1.376085 1.178359 smallDoses 214 | 44484 5.342462 0.394527 didntLike 215 | 54462 11.835521 0.693301 largeDoses 216 | 20085 12.423687 1.424264 largeDoses 217 | 42291 12.161273 0.071131 largeDoses 218 | 47550 8.148360 1.649194 largeDoses 219 | 11938 1.531067 1.549756 smallDoses 220 | 40699 3.200912 0.309679 didntLike 221 | 70908 8.862691 0.530506 didntLike 222 | 73989 6.370551 0.369350 didntLike 223 | 11872 2.468841 0.145060 smallDoses 224 | 48463 11.054212 0.141508 largeDoses 225 | 15987 2.037080 0.715243 smallDoses 226 | 70036 13.364030 0.549972 didntLike 227 | 32967 10.249135 0.192735 largeDoses 228 | 63249 10.464252 1.669767 didntLike 229 | 42795 9.424574 0.013725 largeDoses 230 | 14459 4.458902 0.268444 smallDoses 231 | 19973 0.000000 0.575976 smallDoses 232 | 5494 9.686082 1.029808 largeDoses 233 | 67902 13.649402 1.052618 didntLike 234 | 25621 13.181148 0.273014 largeDoses 235 | 27545 3.877472 0.401600 didntLike 236 | 58656 1.413952 0.451380 didntLike 237 | 7327 4.248986 1.430249 smallDoses 238 | 64555 8.779183 0.845947 didntLike 239 | 8998 4.156252 0.097109 smallDoses 240 | 11752 5.580018 0.158401 smallDoses 241 | 76319 15.040440 1.366898 didntLike 242 | 27665 12.793870 1.307323 largeDoses 243 | 67417 3.254877 0.669546 didntLike 244 | 21808 10.725607 0.588588 largeDoses 245 | 15326 8.256473 0.765891 smallDoses 246 | 20057 8.033892 1.618562 largeDoses 247 | 79341 10.702532 0.204792 didntLike 248 | 15636 5.062996 1.132555 smallDoses 249 | 35602 10.772286 0.668721 largeDoses 250 | 28544 1.892354 0.837028 didntLike 251 | 57663 1.019966 0.372320 didntLike 252 | 78727 15.546043 0.729742 didntLike 253 | 68255 11.638205 0.409125 didntLike 254 | 14964 3.427886 0.975616 smallDoses 255 | 21835 11.246174 1.475586 largeDoses 256 | 7487 0.000000 0.645045 smallDoses 257 | 8700 0.000000 1.424017 smallDoses 258 | 26226 8.242553 0.279069 largeDoses 259 | 65899 8.700060 0.101807 didntLike 260 | 6543 0.812344 0.260334 smallDoses 261 | 46556 2.448235 1.176829 didntLike 262 | 71038 13.230078 0.616147 didntLike 263 | 47657 0.236133 0.340840 didntLike 264 | 19600 11.155826 0.335131 largeDoses 265 | 37422 11.029636 0.505769 largeDoses 266 | 1363 2.901181 1.646633 smallDoses 267 | 26535 3.924594 1.143120 didntLike 268 | 47707 2.524806 1.292848 didntLike 269 | 38055 3.527474 1.449158 didntLike 270 | 6286 3.384281 0.889268 smallDoses 271 | 10747 0.000000 1.107592 smallDoses 272 | 44883 11.898890 0.406441 largeDoses 273 | 56823 3.529892 1.375844 didntLike 274 | 68086 11.442677 0.696919 didntLike 275 | 70242 10.308145 0.422722 didntLike 276 | 11409 8.540529 0.727373 smallDoses 277 | 67671 7.156949 1.691682 didntLike 278 | 61238 0.720675 0.847574 didntLike 279 | 17774 0.229405 1.038603 smallDoses 280 | 53376 3.399331 0.077501 didntLike 281 | 30930 6.157239 0.580133 didntLike 282 | 28987 1.239698 0.719989 didntLike 283 | 13655 6.036854 0.016548 smallDoses 284 | 7227 5.258665 0.933722 smallDoses 285 | 40409 12.393001 1.571281 largeDoses 286 | 13605 9.627613 0.935842 smallDoses 287 | 26400 11.130453 0.597610 largeDoses 288 | 13491 8.842595 0.349768 largeDoses 289 | 30232 10.690010 1.456595 largeDoses 290 | 43253 5.714718 1.674780 largeDoses 291 | 55536 3.052505 1.335804 didntLike 292 | 8807 0.000000 0.059025 smallDoses 293 | 25783 9.945307 1.287952 largeDoses 294 | 22812 2.719723 1.142148 didntLike 295 | 77826 11.154055 1.608486 didntLike 296 | 38172 2.687918 0.660836 didntLike 297 | 31676 10.037847 0.962245 largeDoses 298 | 74038 12.404762 1.112080 didntLike 299 | 44738 10.237305 0.633422 largeDoses 300 | 17410 4.745392 0.662520 smallDoses 301 | 5688 4.639461 1.569431 smallDoses 302 | 36642 3.149310 0.639669 didntLike 303 | 29956 13.406875 1.639194 largeDoses 304 | 60350 6.068668 0.881241 didntLike 305 | 23758 9.477022 0.899002 largeDoses 306 | 25780 3.897620 0.560201 smallDoses 307 | 11342 5.463615 1.203677 smallDoses 308 | 36109 3.369267 1.575043 didntLike 309 | 14292 5.234562 0.825954 smallDoses 310 | 11160 0.000000 0.722170 smallDoses 311 | 23762 12.979069 0.504068 largeDoses 312 | 39567 5.376564 0.557476 didntLike 313 | 25647 13.527910 1.586732 largeDoses 314 | 14814 2.196889 0.784587 smallDoses 315 | 73590 10.691748 0.007509 didntLike 316 | 35187 1.659242 0.447066 didntLike 317 | 49459 8.369667 0.656697 largeDoses 318 | 31657 13.157197 0.143248 largeDoses 319 | 6259 8.199667 0.908508 smallDoses 320 | 33101 4.441669 0.439381 largeDoses 321 | 27107 9.846492 0.644523 largeDoses 322 | 17824 0.019540 0.977949 smallDoses 323 | 43536 8.253774 0.748700 largeDoses 324 | 67705 6.038620 1.509646 didntLike 325 | 35283 6.091587 1.694641 largeDoses 326 | 71308 8.986820 1.225165 didntLike 327 | 31054 11.508473 1.624296 largeDoses 328 | 52387 8.807734 0.713922 largeDoses 329 | 40328 0.000000 0.816676 didntLike 330 | 34844 8.889202 1.665414 largeDoses 331 | 11607 3.178117 0.542752 smallDoses 332 | 64306 7.013795 0.139909 didntLike 333 | 32721 9.605014 0.065254 largeDoses 334 | 33170 1.230540 1.331674 didntLike 335 | 37192 10.412811 0.890803 largeDoses 336 | 13089 0.000000 0.567161 smallDoses 337 | 66491 9.699991 0.122011 didntLike 338 | 15941 0.000000 0.061191 smallDoses 339 | 4272 4.455293 0.272135 smallDoses 340 | 48812 3.020977 1.502803 didntLike 341 | 28818 8.099278 0.216317 largeDoses 342 | 35394 1.157764 1.603217 didntLike 343 | 71791 10.105396 0.121067 didntLike 344 | 40668 11.230148 0.408603 largeDoses 345 | 39580 9.070058 0.011379 largeDoses 346 | 11786 0.566460 0.478837 smallDoses 347 | 19251 0.000000 0.487300 smallDoses 348 | 56594 8.956369 1.193484 largeDoses 349 | 54495 1.523057 0.620528 didntLike 350 | 11844 2.749006 0.169855 smallDoses 351 | 45465 9.235393 0.188350 largeDoses 352 | 31033 10.555573 0.403927 largeDoses 353 | 16633 6.956372 1.519308 smallDoses 354 | 13887 0.636281 1.273984 smallDoses 355 | 52603 3.574737 0.075163 didntLike 356 | 72000 9.032486 1.461809 didntLike 357 | 68497 5.958993 0.023012 didntLike 358 | 35135 2.435300 1.211744 didntLike 359 | 26397 10.539731 1.638248 largeDoses 360 | 7313 7.646702 0.056513 smallDoses 361 | 91273 20.919349 0.644571 didntLike 362 | 24743 1.424726 0.838447 didntLike 363 | 31690 6.748663 0.890223 largeDoses 364 | 15432 2.289167 0.114881 smallDoses 365 | 58394 5.548377 0.402238 didntLike 366 | 33962 6.057227 0.432666 didntLike 367 | 31442 10.828595 0.559955 largeDoses 368 | 31044 11.318160 0.271094 largeDoses 369 | 29938 13.265311 0.633903 largeDoses 370 | 9875 0.000000 1.496715 smallDoses 371 | 51542 6.517133 0.402519 largeDoses 372 | 11878 4.934374 1.520028 smallDoses 373 | 69241 10.151738 0.896433 didntLike 374 | 37776 2.425781 1.559467 didntLike 375 | 68997 9.778962 1.195498 didntLike 376 | 67416 12.219950 0.657677 didntLike 377 | 59225 7.394151 0.954434 didntLike 378 | 29138 8.518535 0.742546 largeDoses 379 | 5962 2.798700 0.662632 smallDoses 380 | 10847 0.637930 0.617373 smallDoses 381 | 70527 10.750490 0.097415 didntLike 382 | 9610 0.625382 0.140969 smallDoses 383 | 64734 10.027968 0.282787 didntLike 384 | 25941 9.817347 0.364197 largeDoses 385 | 2763 0.646828 1.266069 smallDoses 386 | 55601 3.347111 0.914294 didntLike 387 | 31128 11.816892 0.193798 largeDoses 388 | 5181 0.000000 1.480198 smallDoses 389 | 69982 10.945666 0.993219 didntLike 390 | 52440 10.244706 0.280539 largeDoses 391 | 57350 2.579801 1.149172 didntLike 392 | 57869 2.630410 0.098869 didntLike 393 | 56557 11.746200 1.695517 largeDoses 394 | 42342 8.104232 1.326277 largeDoses 395 | 15560 12.409743 0.790295 largeDoses 396 | 34826 12.167844 1.328086 largeDoses 397 | 8569 3.198408 0.299287 smallDoses 398 | 77623 16.055513 0.541052 didntLike 399 | 78184 7.138659 0.158481 didntLike 400 | 7036 4.831041 0.761419 smallDoses 401 | 69616 10.082890 1.373611 didntLike 402 | 21546 10.066867 0.788470 largeDoses 403 | 36715 8.129538 0.329913 largeDoses 404 | 20522 3.012463 1.138108 smallDoses 405 | 42349 3.720391 0.845974 didntLike 406 | 9037 0.773493 1.148256 smallDoses 407 | 26728 10.962941 1.037324 largeDoses 408 | 587 0.177621 0.162614 smallDoses 409 | 48915 3.085853 0.967899 didntLike 410 | 9824 8.426781 0.202558 smallDoses 411 | 4135 1.825927 1.128347 smallDoses 412 | 9666 2.185155 1.010173 smallDoses 413 | 59333 7.184595 1.261338 didntLike 414 | 36198 0.000000 0.116525 didntLike 415 | 34909 8.901752 1.033527 largeDoses 416 | 47516 2.451497 1.358795 didntLike 417 | 55807 3.213631 0.432044 didntLike 418 | 14036 3.974739 0.723929 smallDoses 419 | 42856 9.601306 0.619232 largeDoses 420 | 64007 8.363897 0.445341 didntLike 421 | 59428 6.381484 1.365019 didntLike 422 | 13730 0.000000 1.403914 smallDoses 423 | 41740 9.609836 1.438105 largeDoses 424 | 63546 9.904741 0.985862 didntLike 425 | 30417 7.185807 1.489102 largeDoses 426 | 69636 5.466703 1.216571 didntLike 427 | 64660 0.000000 0.915898 didntLike 428 | 14883 4.575443 0.535671 smallDoses 429 | 7965 3.277076 1.010868 smallDoses 430 | 68620 10.246623 1.239634 didntLike 431 | 8738 2.341735 1.060235 smallDoses 432 | 7544 3.201046 0.498843 smallDoses 433 | 6377 6.066013 0.120927 smallDoses 434 | 36842 8.829379 0.895657 largeDoses 435 | 81046 15.833048 1.568245 didntLike 436 | 67736 13.516711 1.220153 didntLike 437 | 32492 0.664284 1.116755 didntLike 438 | 39299 6.325139 0.605109 largeDoses 439 | 77289 8.677499 0.344373 didntLike 440 | 33835 8.188005 0.964896 largeDoses 441 | 71890 9.414263 0.384030 didntLike 442 | 32054 9.196547 1.138253 largeDoses 443 | 38579 10.202968 0.452363 largeDoses 444 | 55984 2.119439 1.481661 didntLike 445 | 72694 13.635078 0.858314 didntLike 446 | 42299 0.083443 0.701669 didntLike 447 | 26635 9.149096 1.051446 largeDoses 448 | 8579 1.933803 1.374388 smallDoses 449 | 37302 14.115544 0.676198 largeDoses 450 | 22878 8.933736 0.943352 largeDoses 451 | 4364 2.661254 0.946117 smallDoses 452 | 4985 0.988432 1.305027 smallDoses 453 | 37068 2.063741 1.125946 didntLike 454 | 41137 2.220590 0.690754 didntLike 455 | 67759 6.424849 0.806641 didntLike 456 | 11831 1.156153 1.613674 smallDoses 457 | 34502 3.032720 0.601847 didntLike 458 | 4088 3.076828 0.952089 smallDoses 459 | 15199 0.000000 0.318105 smallDoses 460 | 17309 7.750480 0.554015 largeDoses 461 | 42816 10.958135 1.482500 largeDoses 462 | 43751 10.222018 0.488678 largeDoses 463 | 58335 2.367988 0.435741 didntLike 464 | 75039 7.686054 1.381455 didntLike 465 | 42878 11.464879 1.481589 largeDoses 466 | 42770 11.075735 0.089726 largeDoses 467 | 8848 3.543989 0.345853 smallDoses 468 | 31340 8.123889 1.282880 largeDoses 469 | 41413 4.331769 0.754467 largeDoses 470 | 12731 0.120865 1.211961 smallDoses 471 | 22447 6.116109 0.701523 largeDoses 472 | 33564 7.474534 0.505790 largeDoses 473 | 48907 8.819454 0.649292 largeDoses 474 | 8762 6.802144 0.615284 smallDoses 475 | 46696 12.666325 0.931960 largeDoses 476 | 36851 8.636180 0.399333 largeDoses 477 | 67639 11.730991 1.289833 didntLike 478 | 171 8.132449 0.039062 smallDoses 479 | 26674 10.296589 1.496144 largeDoses 480 | 8739 7.583906 1.005764 smallDoses 481 | 66668 9.777806 0.496377 didntLike 482 | 68732 8.833546 0.513876 didntLike 483 | 69995 4.907899 1.518036 didntLike 484 | 82008 8.362736 1.285939 didntLike 485 | 25054 9.084726 1.606312 largeDoses 486 | 33085 14.164141 0.560970 largeDoses 487 | 41379 9.080683 0.989920 largeDoses 488 | 39417 6.522767 0.038548 largeDoses 489 | 12556 3.690342 0.462281 smallDoses 490 | 39432 3.563706 0.242019 didntLike 491 | 38010 1.065870 1.141569 didntLike 492 | 69306 6.683796 1.456317 didntLike 493 | 38000 1.712874 0.243945 didntLike 494 | 46321 13.109929 1.280111 largeDoses 495 | 66293 11.327910 0.780977 didntLike 496 | 22730 4.545711 1.233254 didntLike 497 | 5952 3.367889 0.468104 smallDoses 498 | 72308 8.326224 0.567347 didntLike 499 | 60338 8.978339 1.442034 didntLike 500 | 13301 5.655826 1.582159 smallDoses 501 | 27884 8.855312 0.570684 largeDoses 502 | 11188 6.649568 0.544233 smallDoses 503 | 56796 3.966325 0.850410 didntLike 504 | 8571 1.924045 1.664782 smallDoses 505 | 4914 6.004812 0.280369 smallDoses 506 | 10784 0.000000 0.375849 smallDoses 507 | 39296 9.923018 0.092192 largeDoses 508 | 13113 2.389084 0.119284 smallDoses 509 | 70204 13.663189 0.133251 didntLike 510 | 46813 11.434976 0.321216 largeDoses 511 | 11697 0.358270 1.292858 smallDoses 512 | 44183 9.598873 0.223524 largeDoses 513 | 2225 6.375275 0.608040 smallDoses 514 | 29066 11.580532 0.458401 largeDoses 515 | 4245 5.319324 1.598070 smallDoses 516 | 34379 4.324031 1.603481 didntLike 517 | 44441 2.358370 1.273204 didntLike 518 | 2022 0.000000 1.182708 smallDoses 519 | 26866 12.824376 0.890411 largeDoses 520 | 57070 1.587247 1.456982 didntLike 521 | 32932 8.510324 1.520683 largeDoses 522 | 51967 10.428884 1.187734 largeDoses 523 | 44432 8.346618 0.042318 largeDoses 524 | 67066 7.541444 0.809226 didntLike 525 | 17262 2.540946 1.583286 smallDoses 526 | 79728 9.473047 0.692513 didntLike 527 | 14259 0.352284 0.474080 smallDoses 528 | 6122 0.000000 0.589826 smallDoses 529 | 76879 12.405171 0.567201 didntLike 530 | 11426 4.126775 0.871452 smallDoses 531 | 2493 0.034087 0.335848 smallDoses 532 | 19910 1.177634 0.075106 smallDoses 533 | 10939 0.000000 0.479996 smallDoses 534 | 17716 0.994909 0.611135 smallDoses 535 | 31390 11.053664 1.180117 largeDoses 536 | 20375 0.000000 1.679729 smallDoses 537 | 26309 2.495011 1.459589 didntLike 538 | 33484 11.516831 0.001156 largeDoses 539 | 45944 9.213215 0.797743 largeDoses 540 | 4249 5.332865 0.109288 smallDoses 541 | 6089 0.000000 1.689771 smallDoses 542 | 7513 0.000000 1.126053 smallDoses 543 | 27862 12.640062 1.690903 largeDoses 544 | 39038 2.693142 1.317518 didntLike 545 | 19218 3.328969 0.268271 smallDoses 546 | 62911 7.193166 1.117456 didntLike 547 | 77758 6.615512 1.521012 didntLike 548 | 27940 8.000567 0.835341 largeDoses 549 | 2194 4.017541 0.512104 smallDoses 550 | 37072 13.245859 0.927465 largeDoses 551 | 15585 5.970616 0.813624 smallDoses 552 | 25577 11.668719 0.886902 largeDoses 553 | 8777 4.283237 1.272728 smallDoses 554 | 29016 10.742963 0.971401 largeDoses 555 | 21910 12.326672 1.592608 largeDoses 556 | 12916 0.000000 0.344622 smallDoses 557 | 10976 0.000000 0.922846 smallDoses 558 | 79065 10.602095 0.573686 didntLike 559 | 36759 10.861859 1.155054 largeDoses 560 | 50011 1.229094 1.638690 didntLike 561 | 1155 0.410392 1.313401 smallDoses 562 | 71600 14.552711 0.616162 didntLike 563 | 30817 14.178043 0.616313 largeDoses 564 | 54559 14.136260 0.362388 didntLike 565 | 29764 0.093534 1.207194 didntLike 566 | 69100 10.929021 0.403110 didntLike 567 | 47324 11.432919 0.825959 largeDoses 568 | 73199 9.134527 0.586846 didntLike 569 | 44461 5.071432 1.421420 didntLike 570 | 45617 11.460254 1.541749 largeDoses 571 | 28221 11.620039 1.103553 largeDoses 572 | 7091 4.022079 0.207307 smallDoses 573 | 6110 3.057842 1.631262 smallDoses 574 | 79016 7.782169 0.404385 didntLike 575 | 18289 7.981741 0.929789 largeDoses 576 | 43679 4.601363 0.268326 didntLike 577 | 22075 2.595564 1.115375 didntLike 578 | 23535 10.049077 0.391045 largeDoses 579 | 25301 3.265444 1.572970 smallDoses 580 | 32256 11.780282 1.511014 largeDoses 581 | 36951 3.075975 0.286284 didntLike 582 | 31290 1.795307 0.194343 didntLike 583 | 38953 11.106979 0.202415 largeDoses 584 | 35257 5.994413 0.800021 didntLike 585 | 25847 9.706062 1.012182 largeDoses 586 | 32680 10.582992 0.836025 largeDoses 587 | 62018 7.038266 1.458979 didntLike 588 | 9074 0.023771 0.015314 smallDoses 589 | 33004 12.823982 0.676371 largeDoses 590 | 44588 3.617770 0.493483 didntLike 591 | 32565 8.346684 0.253317 largeDoses 592 | 38563 6.104317 0.099207 didntLike 593 | 75668 16.207776 0.584973 didntLike 594 | 9069 6.401969 1.691873 smallDoses 595 | 53395 2.298696 0.559757 didntLike 596 | 28631 7.661515 0.055981 largeDoses 597 | 71036 6.353608 1.645301 didntLike 598 | 71142 10.442780 0.335870 didntLike 599 | 37653 3.834509 1.346121 didntLike 600 | 76839 10.998587 0.584555 didntLike 601 | 9916 2.695935 1.512111 smallDoses 602 | 38889 3.356646 0.324230 didntLike 603 | 39075 14.677836 0.793183 largeDoses 604 | 48071 1.551934 0.130902 didntLike 605 | 7275 2.464739 0.223502 smallDoses 606 | 41804 1.533216 1.007481 didntLike 607 | 35665 12.473921 0.162910 largeDoses 608 | 67956 6.491596 0.032576 didntLike 609 | 41892 10.506276 1.510747 largeDoses 610 | 38844 4.380388 0.748506 didntLike 611 | 74197 13.670988 1.687944 didntLike 612 | 14201 8.317599 0.390409 smallDoses 613 | 3908 0.000000 0.556245 smallDoses 614 | 2459 0.000000 0.290218 smallDoses 615 | 32027 10.095799 1.188148 largeDoses 616 | 12870 0.860695 1.482632 smallDoses 617 | 9880 1.557564 0.711278 smallDoses 618 | 72784 10.072779 0.756030 didntLike 619 | 17521 0.000000 0.431468 smallDoses 620 | 50283 7.140817 0.883813 largeDoses 621 | 33536 11.384548 1.438307 largeDoses 622 | 9452 3.214568 1.083536 smallDoses 623 | 37457 11.720655 0.301636 largeDoses 624 | 17724 6.374475 1.475925 largeDoses 625 | 43869 5.749684 0.198875 largeDoses 626 | 264 3.871808 0.552602 smallDoses 627 | 25736 8.336309 0.636238 largeDoses 628 | 39584 9.710442 1.503735 largeDoses 629 | 31246 1.532611 1.433898 didntLike 630 | 49567 9.785785 0.984614 largeDoses 631 | 7052 2.633627 1.097866 smallDoses 632 | 35493 9.238935 0.494701 largeDoses 633 | 10986 1.205656 1.398803 smallDoses 634 | 49508 3.124909 1.670121 didntLike 635 | 5734 7.935489 1.585044 smallDoses 636 | 65479 12.746636 1.560352 didntLike 637 | 77268 10.732563 0.545321 didntLike 638 | 28490 3.977403 0.766103 didntLike 639 | 13546 4.194426 0.450663 smallDoses 640 | 37166 9.610286 0.142912 largeDoses 641 | 16381 4.797555 1.260455 smallDoses 642 | 10848 1.615279 0.093002 smallDoses 643 | 35405 4.614771 1.027105 didntLike 644 | 15917 0.000000 1.369726 smallDoses 645 | 6131 0.608457 0.512220 smallDoses 646 | 67432 6.558239 0.667579 didntLike 647 | 30354 12.315116 0.197068 largeDoses 648 | 69696 7.014973 1.494616 didntLike 649 | 33481 8.822304 1.194177 largeDoses 650 | 43075 10.086796 0.570455 largeDoses 651 | 38343 7.241614 1.661627 largeDoses 652 | 14318 4.602395 1.511768 smallDoses 653 | 5367 7.434921 0.079792 smallDoses 654 | 37894 10.467570 1.595418 largeDoses 655 | 36172 9.948127 0.003663 largeDoses 656 | 40123 2.478529 1.568987 didntLike 657 | 10976 5.938545 0.878540 smallDoses 658 | 12705 0.000000 0.948004 smallDoses 659 | 12495 5.559181 1.357926 smallDoses 660 | 35681 9.776654 0.535966 largeDoses 661 | 46202 3.092056 0.490906 didntLike 662 | 11505 0.000000 1.623311 smallDoses 663 | 22834 4.459495 0.538867 didntLike 664 | 49901 8.334306 1.646600 largeDoses 665 | 71932 11.226654 0.384686 didntLike 666 | 13279 3.904737 1.597294 smallDoses 667 | 49112 7.038205 1.211329 largeDoses 668 | 77129 9.836120 1.054340 didntLike 669 | 37447 1.990976 0.378081 didntLike 670 | 62397 9.005302 0.485385 didntLike 671 | 0 1.772510 1.039873 smallDoses 672 | 15476 0.458674 0.819560 smallDoses 673 | 40625 10.003919 0.231658 largeDoses 674 | 36706 0.520807 1.476008 didntLike 675 | 28580 10.678214 1.431837 largeDoses 676 | 25862 4.425992 1.363842 didntLike 677 | 63488 12.035355 0.831222 didntLike 678 | 33944 10.606732 1.253858 largeDoses 679 | 30099 1.568653 0.684264 didntLike 680 | 13725 2.545434 0.024271 smallDoses 681 | 36768 10.264062 0.982593 largeDoses 682 | 64656 9.866276 0.685218 didntLike 683 | 14927 0.142704 0.057455 smallDoses 684 | 43231 9.853270 1.521432 largeDoses 685 | 66087 6.596604 1.653574 didntLike 686 | 19806 2.602287 1.321481 smallDoses 687 | 41081 10.411776 0.664168 largeDoses 688 | 10277 7.083449 0.622589 smallDoses 689 | 7014 2.080068 1.254441 smallDoses 690 | 17275 0.522844 1.622458 smallDoses 691 | 31600 10.362000 1.544827 largeDoses 692 | 59956 3.412967 1.035410 didntLike 693 | 42181 6.796548 1.112153 largeDoses 694 | 51743 4.092035 0.075804 didntLike 695 | 5194 2.763811 1.564325 smallDoses 696 | 30832 12.547439 1.402443 largeDoses 697 | 7976 5.708052 1.596152 smallDoses 698 | 14602 4.558025 0.375806 smallDoses 699 | 41571 11.642307 0.438553 largeDoses 700 | 55028 3.222443 0.121399 didntLike 701 | 5837 4.736156 0.029871 smallDoses 702 | 39808 10.839526 0.836323 largeDoses 703 | 20944 4.194791 0.235483 smallDoses 704 | 22146 14.936259 0.888582 largeDoses 705 | 42169 3.310699 1.521855 didntLike 706 | 7010 2.971931 0.034321 smallDoses 707 | 3807 9.261667 0.537807 smallDoses 708 | 29241 7.791833 1.111416 largeDoses 709 | 52696 1.480470 1.028750 didntLike 710 | 42545 3.677287 0.244167 didntLike 711 | 24437 2.202967 1.370399 didntLike 712 | 16037 5.796735 0.935893 smallDoses 713 | 8493 3.063333 0.144089 smallDoses 714 | 68080 11.233094 0.492487 didntLike 715 | 59016 1.965570 0.005697 didntLike 716 | 11810 8.616719 0.137419 smallDoses 717 | 68630 6.609989 1.083505 didntLike 718 | 7629 1.712639 1.086297 smallDoses 719 | 71992 10.117445 1.299319 didntLike 720 | 13398 0.000000 1.104178 smallDoses 721 | 26241 9.824777 1.346821 largeDoses 722 | 11160 1.653089 0.980949 smallDoses 723 | 76701 18.178822 1.473671 didntLike 724 | 32174 6.781126 0.885340 largeDoses 725 | 45043 8.206750 1.549223 largeDoses 726 | 42173 10.081853 1.376745 largeDoses 727 | 69801 6.288742 0.112799 didntLike 728 | 41737 3.695937 1.543589 didntLike 729 | 46979 6.726151 1.069380 largeDoses 730 | 79267 12.969999 1.568223 didntLike 731 | 4615 2.661390 1.531933 smallDoses 732 | 32907 7.072764 1.117386 largeDoses 733 | 37444 9.123366 1.318988 largeDoses 734 | 569 3.743946 1.039546 smallDoses 735 | 8723 2.341300 0.219361 smallDoses 736 | 6024 0.541913 0.592348 smallDoses 737 | 52252 2.310828 1.436753 didntLike 738 | 8358 6.226597 1.427316 smallDoses 739 | 26166 7.277876 0.489252 largeDoses 740 | 18471 0.000000 0.389459 smallDoses 741 | 3386 7.218221 1.098828 smallDoses 742 | 41544 8.777129 1.111464 largeDoses 743 | 10480 2.813428 0.819419 smallDoses 744 | 5894 2.268766 1.412130 smallDoses 745 | 7273 6.283627 0.571292 smallDoses 746 | 22272 7.520081 1.626868 largeDoses 747 | 31369 11.739225 0.027138 largeDoses 748 | 10708 3.746883 0.877350 smallDoses 749 | 69364 12.089835 0.521631 didntLike 750 | 37760 12.310404 0.259339 largeDoses 751 | 13004 0.000000 0.671355 smallDoses 752 | 37885 2.728800 0.331502 didntLike 753 | 52555 10.814342 0.607652 largeDoses 754 | 38997 12.170268 0.844205 largeDoses 755 | 69698 6.698371 0.240084 didntLike 756 | 11783 3.632672 1.643479 smallDoses 757 | 47636 10.059991 0.892361 largeDoses 758 | 15744 1.887674 0.756162 smallDoses 759 | 69058 8.229125 0.195886 didntLike 760 | 33057 7.817082 0.476102 largeDoses 761 | 28681 12.277230 0.076805 largeDoses 762 | 34042 10.055337 1.115778 largeDoses 763 | 29928 3.596002 1.485952 didntLike 764 | 9734 2.755530 1.420655 smallDoses 765 | 7344 7.780991 0.513048 smallDoses 766 | 7387 0.093705 0.391834 smallDoses 767 | 33957 8.481567 0.520078 largeDoses 768 | 9936 3.865584 0.110062 smallDoses 769 | 36094 9.683709 0.779984 largeDoses 770 | 39835 10.617255 1.359970 largeDoses 771 | 64486 7.203216 1.624762 didntLike 772 | 0 7.601414 1.215605 smallDoses 773 | 39539 1.386107 1.417070 didntLike 774 | 66972 9.129253 0.594089 didntLike 775 | 15029 1.363447 0.620841 smallDoses 776 | 44909 3.181399 0.359329 didntLike 777 | 38183 13.365414 0.217011 largeDoses 778 | 37372 4.207717 1.289767 didntLike 779 | 0 4.088395 0.870075 smallDoses 780 | 17786 3.327371 1.142505 smallDoses 781 | 39055 1.303323 1.235650 didntLike 782 | 37045 7.999279 1.581763 largeDoses 783 | 6435 2.217488 0.864536 smallDoses 784 | 72265 7.751808 0.192451 didntLike 785 | 28152 14.149305 1.591532 largeDoses 786 | 25931 8.765721 0.152808 largeDoses 787 | 7538 3.408996 0.184896 smallDoses 788 | 1315 1.251021 0.112340 smallDoses 789 | 12292 6.160619 1.537165 smallDoses 790 | 49248 1.034538 1.585162 didntLike 791 | 9025 0.000000 1.034635 smallDoses 792 | 13438 2.355051 0.542603 smallDoses 793 | 69683 6.614543 0.153771 didntLike 794 | 25374 10.245062 1.450903 largeDoses 795 | 55264 3.467074 1.231019 didntLike 796 | 38324 7.487678 1.572293 largeDoses 797 | 69643 4.624115 1.185192 didntLike 798 | 44058 8.995957 1.436479 largeDoses 799 | 41316 11.564476 0.007195 largeDoses 800 | 29119 3.440948 0.078331 didntLike 801 | 51656 1.673603 0.732746 didntLike 802 | 3030 4.719341 0.699755 smallDoses 803 | 35695 10.304798 1.576488 largeDoses 804 | 1537 2.086915 1.199312 smallDoses 805 | 9083 6.338220 1.131305 smallDoses 806 | 47744 8.254926 0.710694 largeDoses 807 | 71372 16.067108 0.974142 didntLike 808 | 37980 1.723201 0.310488 didntLike 809 | 42385 3.785045 0.876904 didntLike 810 | 22687 2.557561 0.123738 didntLike 811 | 39512 9.852220 1.095171 largeDoses 812 | 11885 3.679147 1.557205 smallDoses 813 | 4944 9.789681 0.852971 smallDoses 814 | 73230 14.958998 0.526707 didntLike 815 | 17585 11.182148 1.288459 largeDoses 816 | 68737 7.528533 1.657487 didntLike 817 | 13818 5.253802 1.378603 smallDoses 818 | 31662 13.946752 1.426657 largeDoses 819 | 86686 15.557263 1.430029 didntLike 820 | 43214 12.483550 0.688513 largeDoses 821 | 24091 2.317302 1.411137 didntLike 822 | 52544 10.069724 0.766119 largeDoses 823 | 61861 5.792231 1.615483 didntLike 824 | 47903 4.138435 0.475994 didntLike 825 | 37190 12.929517 0.304378 largeDoses 826 | 6013 9.378238 0.307392 smallDoses 827 | 27223 8.361362 1.643204 largeDoses 828 | 69027 7.939406 1.325042 didntLike 829 | 78642 10.735384 0.705788 didntLike 830 | 30254 11.592723 0.286188 largeDoses 831 | 21704 10.098356 0.704748 largeDoses 832 | 34985 9.299025 0.545337 largeDoses 833 | 31316 11.158297 0.218067 largeDoses 834 | 76368 16.143900 0.558388 didntLike 835 | 27953 10.971700 1.221787 largeDoses 836 | 152 0.000000 0.681478 smallDoses 837 | 9146 3.178961 1.292692 smallDoses 838 | 75346 17.625350 0.339926 didntLike 839 | 26376 1.995833 0.267826 didntLike 840 | 35255 10.640467 0.416181 largeDoses 841 | 19198 9.628339 0.985462 largeDoses 842 | 12518 4.662664 0.495403 smallDoses 843 | 25453 5.754047 1.382742 smallDoses 844 | 12530 0.000000 0.037146 smallDoses 845 | 62230 9.334332 0.198118 didntLike 846 | 9517 3.846162 0.619968 smallDoses 847 | 71161 10.685084 0.678179 didntLike 848 | 1593 4.752134 0.359205 smallDoses 849 | 33794 0.697630 0.966786 didntLike 850 | 39710 10.365836 0.505898 largeDoses 851 | 16941 0.461478 0.352865 smallDoses 852 | 69209 11.339537 1.068740 didntLike 853 | 4446 5.420280 0.127310 smallDoses 854 | 9347 3.469955 1.619947 smallDoses 855 | 55635 8.517067 0.994858 largeDoses 856 | 65889 8.306512 0.413690 didntLike 857 | 10753 2.628690 0.444320 smallDoses 858 | 7055 0.000000 0.802985 smallDoses 859 | 7905 0.000000 1.170397 smallDoses 860 | 53447 7.298767 1.582346 largeDoses 861 | 9194 7.331319 1.277988 smallDoses 862 | 61914 9.392269 0.151617 didntLike 863 | 15630 5.541201 1.180596 smallDoses 864 | 79194 15.149460 0.537540 didntLike 865 | 12268 5.515189 0.250562 smallDoses 866 | 33682 7.728898 0.920494 largeDoses 867 | 26080 11.318785 1.510979 largeDoses 868 | 19119 3.574709 1.531514 smallDoses 869 | 30902 7.350965 0.026332 largeDoses 870 | 63039 7.122363 1.630177 didntLike 871 | 51136 1.828412 1.013702 didntLike 872 | 35262 10.117989 1.156862 largeDoses 873 | 42776 11.309897 0.086291 largeDoses 874 | 64191 8.342034 1.388569 didntLike 875 | 15436 0.241714 0.715577 smallDoses 876 | 14402 10.482619 1.694972 smallDoses 877 | 6341 9.289510 1.428879 smallDoses 878 | 14113 4.269419 0.134181 smallDoses 879 | 6390 0.000000 0.189456 smallDoses 880 | 8794 0.817119 0.143668 smallDoses 881 | 43432 1.508394 0.652651 didntLike 882 | 38334 9.359918 0.052262 largeDoses 883 | 34068 10.052333 0.550423 largeDoses 884 | 30819 11.111660 0.989159 largeDoses 885 | 22239 11.265971 0.724054 largeDoses 886 | 28725 10.383830 0.254836 largeDoses 887 | 57071 3.878569 1.377983 didntLike 888 | 72420 13.679237 0.025346 didntLike 889 | 28294 10.526846 0.781569 largeDoses 890 | 9896 0.000000 0.924198 smallDoses 891 | 65821 4.106727 1.085669 didntLike 892 | 7645 8.118856 1.470686 smallDoses 893 | 71289 7.796874 0.052336 didntLike 894 | 5128 2.789669 1.093070 smallDoses 895 | 13711 6.226962 0.287251 smallDoses 896 | 22240 10.169548 1.660104 largeDoses 897 | 15092 0.000000 1.370549 smallDoses 898 | 5017 7.513353 0.137348 smallDoses 899 | 10141 8.240793 0.099735 smallDoses 900 | 35570 14.612797 1.247390 largeDoses 901 | 46893 3.562976 0.445386 didntLike 902 | 8178 3.230482 1.331698 smallDoses 903 | 55783 3.612548 1.551911 didntLike 904 | 1148 0.000000 0.332365 smallDoses 905 | 10062 3.931299 0.487577 smallDoses 906 | 74124 14.752342 1.155160 didntLike 907 | 66603 10.261887 1.628085 didntLike 908 | 11893 2.787266 1.570402 smallDoses 909 | 50908 15.112319 1.324132 largeDoses 910 | 39891 5.184553 0.223382 largeDoses 911 | 65915 3.868359 0.128078 didntLike 912 | 65678 3.507965 0.028904 didntLike 913 | 62996 11.019254 0.427554 didntLike 914 | 36851 3.812387 0.655245 didntLike 915 | 36669 11.056784 0.378725 largeDoses 916 | 38876 8.826880 1.002328 largeDoses 917 | 26878 11.173861 1.478244 largeDoses 918 | 46246 11.506465 0.421993 largeDoses 919 | 12761 7.798138 0.147917 largeDoses 920 | 35282 10.155081 1.370039 largeDoses 921 | 68306 10.645275 0.693453 didntLike 922 | 31262 9.663200 1.521541 largeDoses 923 | 34754 10.790404 1.312679 largeDoses 924 | 13408 2.810534 0.219962 smallDoses 925 | 30365 9.825999 1.388500 largeDoses 926 | 10709 1.421316 0.677603 smallDoses 927 | 24332 11.123219 0.809107 largeDoses 928 | 45517 13.402206 0.661524 largeDoses 929 | 6178 1.212255 0.836807 smallDoses 930 | 10639 1.568446 1.297469 smallDoses 931 | 29613 3.343473 1.312266 didntLike 932 | 22392 5.400155 0.193494 didntLike 933 | 51126 3.818754 0.590905 didntLike 934 | 53644 7.973845 0.307364 largeDoses 935 | 51417 9.078824 0.734876 largeDoses 936 | 24859 0.153467 0.766619 didntLike 937 | 61732 8.325167 0.028479 didntLike 938 | 71128 7.092089 1.216733 didntLike 939 | 27276 5.192485 1.094409 largeDoses 940 | 30453 10.340791 1.087721 largeDoses 941 | 18670 2.077169 1.019775 smallDoses 942 | 70600 10.151966 0.993105 didntLike 943 | 12683 0.046826 0.809614 smallDoses 944 | 81597 11.221874 1.395015 didntLike 945 | 69959 14.497963 1.019254 didntLike 946 | 8124 3.554508 0.533462 smallDoses 947 | 18867 3.522673 0.086725 smallDoses 948 | 80886 14.531655 0.380172 didntLike 949 | 55895 3.027528 0.885457 didntLike 950 | 31587 1.845967 0.488985 didntLike 951 | 10591 10.226164 0.804403 largeDoses 952 | 70096 10.965926 1.212328 didntLike 953 | 53151 2.129921 1.477378 didntLike 954 | 11992 0.000000 1.606849 smallDoses 955 | 33114 9.489005 0.827814 largeDoses 956 | 7413 0.000000 1.020797 smallDoses 957 | 10583 0.000000 1.270167 smallDoses 958 | 58668 6.556676 0.055183 didntLike 959 | 35018 9.959588 0.060020 largeDoses 960 | 70843 7.436056 1.479856 didntLike 961 | 14011 0.404888 0.459517 smallDoses 962 | 35015 9.952942 1.650279 largeDoses 963 | 70839 15.600252 0.021935 didntLike 964 | 3024 2.723846 0.387455 smallDoses 965 | 5526 0.513866 1.323448 smallDoses 966 | 5113 0.000000 0.861859 smallDoses 967 | 20851 7.280602 1.438470 smallDoses 968 | 40999 9.161978 1.110180 largeDoses 969 | 15823 0.991725 0.730979 smallDoses 970 | 35432 7.398380 0.684218 largeDoses 971 | 53711 12.149747 1.389088 largeDoses 972 | 64371 9.149678 0.874905 didntLike 973 | 9289 9.666576 1.370330 smallDoses 974 | 60613 3.620110 0.287767 didntLike 975 | 18338 5.238800 1.253646 smallDoses 976 | 22845 14.715782 1.503758 largeDoses 977 | 74676 14.445740 1.211160 didntLike 978 | 34143 13.609528 0.364240 largeDoses 979 | 14153 3.141585 0.424280 smallDoses 980 | 9327 0.000000 0.120947 smallDoses 981 | 18991 0.454750 1.033280 smallDoses 982 | 9193 0.510310 0.016395 smallDoses 983 | 2285 3.864171 0.616349 smallDoses 984 | 9493 6.724021 0.563044 smallDoses 985 | 2371 4.289375 0.012563 smallDoses 986 | 13963 0.000000 1.437030 smallDoses 987 | 2299 3.733617 0.698269 smallDoses 988 | 5262 2.002589 1.380184 smallDoses 989 | 4659 2.502627 0.184223 smallDoses 990 | 17582 6.382129 0.876581 smallDoses 991 | 27750 8.546741 0.128706 largeDoses 992 | 9868 2.694977 0.432818 smallDoses 993 | 18333 3.951256 0.333300 smallDoses 994 | 3780 9.856183 0.329181 smallDoses 995 | 18190 2.068962 0.429927 smallDoses 996 | 11145 3.410627 0.631838 smallDoses 997 | 68846 9.974715 0.669787 didntLike 998 | 26575 10.650102 0.866627 largeDoses 999 | 48111 9.134528 0.728045 largeDoses 1000 | 43757 7.882601 1.332446 largeDoses 1001 | -------------------------------------------------------------------------------- /Chapter3/iris.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sun Jun 2 13:38:39 2019 4 | 5 | @author: Administrator 6 | """ 7 | 8 | import numpy as np 9 | import pandas as pd 10 | import matplotlib.pyplot as plt 11 | from sklearn.datasets import load_iris 12 | from sklearn.model_selection import train_test_split 13 | 14 | from collections import Counter 15 | 16 | iris = load_iris() 17 | df = pd.DataFrame(iris.data, columns=iris.feature_names) 18 | df['label'] = iris.target 19 | df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label'] 20 | 21 | plt.scatter(df[:50]['sepal length'], df[:50]['sepal width'], label='0') 22 | plt.scatter(df[50:100]['sepal length'], df[50:100]['sepal width'], label='1') 23 | plt.xlabel('sepal length') 24 | plt.ylabel('sepal width') 25 | plt.legend() 26 | 27 | data = np.array(df.iloc[:100, [0, 1, -1]]) 28 | X, y = data[:,:-1], data[:,-1] 29 | X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) 30 | 31 | class KNN: 32 | def __init__(self, X_train, y_train, n_neighbors=3, p=2): 33 | self.n = n_neighbors 34 | self.p = p 35 | self.X_train = X_train 36 | self.y_train = y_train 37 | 38 | def predict(self, X): 39 | #取出n个点 40 | knn_list = [] 41 | for i in range(self.n): 42 | #范式 43 | dist = np.linalg.norm(X - self.X_train[i], ord=self.p) 44 | knn_list.append((dist, self.y_train[i])) 45 | #print(knn_list) 46 | 47 | for i in range(self.n, len(self.X_train)): 48 | #留在knn_list列表中的永远是最近的n个点,每次将最大的点取出 49 | max_index = knn_list.index(max(knn_list, key=lambda x: x[0])) 50 | dist = np.linalg.norm(X - self.X_train[i], ord=self.p) 51 | if knn_list[max_index][0] > dist: 52 | knn_list[max_index] = (dist, self.y_train[i]) 53 | 54 | knn = [k[-1] for k in knn_list] 55 | count_pairs = Counter(knn) 56 | #sorted默认升序,取记数最大值 57 | max_count = sorted(count_pairs, key=lambda x:x)[-1] 58 | return max_count 59 | 60 | def score(self, X_test, y_test): 61 | right_count = 0 62 | #n = 10 63 | for X, y in zip(X_test, y_test): 64 | label = self.predict(X) 65 | if label == y: 66 | right_count += 1 67 | return right_count / len(X_test) 68 | 69 | 70 | clf = KNN(X_train, y_train) 71 | 72 | print(clf.score(X_test, y_test)) 73 | 74 | -------------------------------------------------------------------------------- /Chapter3/iris_kdtree.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sun Jun 2 16:44:25 2019 4 | 5 | @author: Administrator 6 | """ 7 | import numpy as np 8 | import pandas as pd 9 | import matplotlib.pyplot as plt 10 | from sklearn.datasets import load_iris 11 | from sklearn.model_selection import train_test_split 12 | from collections import Counter 13 | 14 | iris = load_iris() 15 | df = pd.DataFrame(iris.data, columns=iris.feature_names) 16 | df['label'] = iris.target 17 | df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label'] 18 | 19 | plt.scatter(df[:50]['sepal length'], df[:50]['sepal width'], label='0') 20 | plt.scatter(df[50:100]['sepal length'], df[50:100]['sepal width'], label='1') 21 | plt.xlabel('sepal length') 22 | plt.ylabel('sepal width') 23 | plt.legend() 24 | 25 | data = np.array(df.iloc[:100, [0, 1, -1]]) 26 | X, y = data[:,:-1], data[:,-1] 27 | X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) 28 | 29 | 30 | # kd-tree每个结点中主要包含的数据结构如下 31 | class KdNode(object): 32 | def __init__(self, dom_elt, split, left, right): 33 | self.dom_elt = dom_elt # k维向量节点(k维空间中的一个样本点) 34 | self.split = split # 整数(进行分割维度的序号) 35 | self.left = left # 该结点分割超平面左子空间构成的kd-tree 36 | self.right = right # 该结点分割超平面右子空间构成的kd-tree 37 | 38 | 39 | class KdTree(object): 40 | def __init__(self, data): 41 | k = len(data[0]) # 数据维度 42 | 43 | def CreateNode(split, data_set): # 按第split维划分数据集exset创建KdNode 44 | if not data_set: # 数据集为空 45 | return None 46 | # key参数的值为一个函数,此函数只有一个参数且返回一个值用来进行比较 47 | # operator模块提供的itemgetter函数用于获取对象的哪些维的数据,参数为需要获取的数据在对象中的序号 48 | #data_set.sort(key=itemgetter(split)) # 按要进行分割的那一维数据排序 49 | data_set.sort(key=lambda x: x[split]) 50 | split_pos = len(data_set) // 2 # //为Python中的整数除法 51 | median = data_set[split_pos] # 中位数分割点 52 | split_next = (split + 1) % k # cycle coordinates 53 | 54 | # 递归的创建kd树 55 | return KdNode(median, split, 56 | CreateNode(split_next, data_set[:split_pos]), # 创建左子树 57 | CreateNode(split_next, data_set[split_pos + 1:])) # 创建右子树 58 | 59 | self.root = CreateNode(0, data) # 从第0维分量开始构建kd树,返回根节点 60 | 61 | 62 | # KDTree的前序遍历 63 | def preorder(root): 64 | print (root.dom_elt) 65 | if root.left: # 节点不为空 66 | preorder(root.left) 67 | if root.right: 68 | preorder(root.right) 69 | 70 | # 例3.2 71 | data = [[2,3],[5,4],[9,6],[4,7],[8,1],[7,2]] 72 | kd = KdTree(data) 73 | preorder(kd.root) 74 | 75 | # 对构建好的kd树进行搜索,寻找与目标点最近的样本点: 76 | from math import sqrt 77 | from collections import namedtuple 78 | 79 | # 定义一个namedtuple,分别存放最近坐标点、最近距离和访问过的节点数 80 | result = namedtuple("Result_tuple", "nearest_point nearest_dist nodes_visited") 81 | 82 | #最近邻搜索 83 | def find_nearest(tree, point): 84 | k = len(point) # 数据维度 85 | def travel(kd_node, target, max_dist): 86 | if kd_node is None: 87 | return result([0] * k, float("inf"), 0) # python中用float("inf")和float("-inf")表示正负无穷 88 | 89 | nodes_visited = 1 90 | 91 | s = kd_node.split # 进行分割的维度 92 | pivot = kd_node.dom_elt # 进行分割的“轴” 93 | 94 | if target[s] <= pivot[s]: # 如果目标点第s维小于分割轴的对应值(目标离左子树更近) 95 | nearer_node = kd_node.left # 下一个访问节点为左子树根节点 96 | further_node = kd_node.right # 同时记录下右子树 97 | else: # 目标离右子树更近 98 | nearer_node = kd_node.right # 下一个访问节点为右子树根节点 99 | further_node = kd_node.left 100 | 101 | temp1 = travel(nearer_node, target, max_dist) # 进行遍历找到包含目标点的区域 102 | 103 | nearest = temp1.nearest_point # 以此叶结点作为“当前最近点” 104 | dist = temp1.nearest_dist # 更新最近距离 105 | 106 | nodes_visited += temp1.nodes_visited 107 | 108 | if dist < max_dist: 109 | max_dist = dist # 最近点将在以目标点为球心,max_dist为半径的超球体内 110 | 111 | temp_dist = abs(pivot[s] - target[s]) # 第s维上目标点与分割超平面的距离 112 | if max_dist < temp_dist: # 判断超球体是否与超平面相交 113 | return result(nearest, dist, nodes_visited) # 不相交则可以直接返回,不用继续判断 114 | 115 | #---------------------------------------------------------------------- 116 | # 计算目标点与分割点的欧氏距离 117 | temp_dist = sqrt(sum((p1 - p2) ** 2 for p1, p2 in zip(pivot, target))) 118 | 119 | if temp_dist < dist: # 如果“更近” 120 | nearest = pivot # 更新最近点 121 | dist = temp_dist # 更新最近距离 122 | max_dist = dist # 更新超球体半径 123 | 124 | # 检查另一个子结点对应的区域是否有更近的点 125 | temp2 = travel(further_node, target, max_dist) 126 | 127 | nodes_visited += temp2.nodes_visited 128 | if temp2.nearest_dist < dist: # 如果另一个子结点内存在更近距离 129 | nearest = temp2.nearest_point # 更新最近点 130 | dist = temp2.nearest_dist # 更新最近距离 131 | 132 | return result(nearest, dist, nodes_visited) 133 | 134 | return travel(tree.root, point, float("inf")) # 从根节点开始递归 135 | 136 | 137 | 138 | 139 | import time 140 | from random import random 141 | 142 | # 产生一个k维随机向量,每维分量值在0~1之间 143 | def random_point(k): 144 | return [random() for _ in range(k)] 145 | 146 | # 产生n个k维随机向量 147 | def random_points(k, n): 148 | return [random_point(k) for _ in range(n)] 149 | 150 | ret = find_nearest(kd, [3,4.5]) 151 | print (ret) 152 | 153 | 154 | N = 400000 155 | t0 = time.time() 156 | kd2 = KdTree(random_points(3, N)) # 构建包含四十万个3维空间样本点的kd树 157 | ret2 = find_nearest(kd2, [0.1,0.5,0.8]) # 四十万个样本点中寻找离目标最近的点 158 | t1 = time.time() 159 | print ("time: ",t1-t0, "s") 160 | print (ret2) -------------------------------------------------------------------------------- /Chapter4/Naive_Bayes.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Tue Jun 4 13:11:22 2019 4 | 5 | @author: Administrator 6 | """ 7 | # 高斯模型 8 | import numpy as np 9 | import pandas as pd 10 | 11 | from sklearn.datasets import load_iris 12 | from sklearn.model_selection import train_test_split 13 | import math 14 | 15 | def create_data(): 16 | iris = load_iris() 17 | df = pd.DataFrame(iris.data, columns=iris.feature_names) 18 | df['label'] = iris.target 19 | df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label'] 20 | data = np.array(df.iloc[:100, :]) 21 | # print(data) 22 | return data[:,:-1], data[:,-1] 23 | 24 | X, y = create_data() 25 | X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3) 26 | 27 | class NaiveBayes: 28 | def __init__(self): 29 | self.model = None 30 | 31 | # 数学期望 32 | @staticmethod 33 | def mean(x): 34 | return sum(x)/float(len(x)) 35 | 36 | # 标准差 37 | def std(self,x): 38 | avg = self.mean(x) 39 | return math.sqrt(sum(math.pow(x_i-avg,2) for x_i in x)/float(len(x))) 40 | 41 | # 概率密度函数 42 | def gaussian_prob(self,x,mean,std): 43 | exp = math.pow(math.e, -1*(math.pow(x - mean,2))/(2*std)) 44 | return (1/(math.sqrt(2*math.pi*std)))*exp 45 | 46 | # 计算训练的均值和方差 47 | def mean_and_std(self,x): 48 | mean_and_std=[(self.mean(i),self.std(i)) for i in zip(*x)] 49 | return mean_and_std 50 | 51 | # 分类别求出数学期望和标准差 52 | def fit(self,x,y): 53 | labels = list(set(y)) 54 | data = {label:[] for label in labels} 55 | for f,label in zip(x,y): 56 | data[label].append(f) 57 | self.model = {label:self.mean_and_std(value) for label,value in data.items()} 58 | print("GaussianNB train Done!") 59 | 60 | 61 | # 计算概率 62 | def prob(self,data): 63 | probabillity = {} 64 | for label,value in self.model.items(): 65 | probabillity[label] = 1 66 | for i in range(len(value)): 67 | mean,std = value[i] 68 | probabillity[label] *= self.gaussian_prob(data[i],mean,std) 69 | return probabillity 70 | 71 | # 类别 72 | def predict(self,x_test): 73 | #print(self.prob(x_test)) 74 | label = sorted(self.prob(x_test).items(),key=lambda x:x[-1])[-1][0] 75 | return label 76 | 77 | def score(self,x_test,y_test): 78 | right = 0 79 | for x,y in zip(x_test,y_test): 80 | label = self.predict(x) 81 | if label == y: 82 | right+=1 83 | return right / float(len(x_test)) 84 | 85 | model = NaiveBayes() 86 | model.fit(X_train,y_train) 87 | #print(model.model) 88 | print(model.predict([4.4,3.2,1.3,0.2])) 89 | print("在测试集中的准确率:") 90 | print(str(100*(model.score(X_test, y_test)))+"%") 91 | 92 | # scikit-learn 实现 93 | 94 | from sklearn.naive_bayes import GaussianNB # 高斯模型 95 | from sklearn.naive_bayes import BernoulliNB # 伯努利模型 96 | from sklearn.naive_bayes import MultinomialNB # 多项式模型 97 | 98 | clf = GaussianNB() 99 | # clf = BernoulliNB() 100 | # clf = MultinomialNB() 101 | 102 | clf.fit(X_train,y_train) 103 | print(clf.predict([[4.4,3.2,1.3,0.2]])) 104 | -------------------------------------------------------------------------------- /Chapter4/README.md: -------------------------------------------------------------------------------- 1 | # 朴素贝叶斯法 2 | 3 | ## 笔记摘要 4 | * 条件概率分布$P(X=x|Y=c_k)$有指数级数量的参数,其实际估计是不可行的 5 | 6 | * 指数级数量的参数 $K\prod_{j=1}^nS_j$,实际估计不可行是实际上没有那么多样本 7 | * 朴素贝叶斯法是基于**贝叶斯定理**与**特征条件独立假设**的分类方法 8 | ### 贝叶斯定理 9 | $$P(B_i|A)=\frac{P(B_i)P(A|B_i)}{\sum _{j=1}^nP(B_j)P(A|B_j)}$$ 10 | 11 | ### 条件独立假设 12 | 13 | **independent and identically distributed** 14 | 15 | * 求$P(Y|X)$,其中$X\in\{X_1,X_2,\dots,X_n\}$,条件独立假设这里给定$Y$的情况下: 16 | 17 | 1. 每一个$X_i$和其他的每个$X_k$是条件独立的 18 | 1. 每一个$X_i$和其他的每个$X_k$的子集是条件独立的 19 | 20 | * 条件独立性假设是: 21 | $$ 22 | \begin{aligned} 23 | P(X=x|Y=c_k)&=P(X^{(1)},\dots,X^{(n)}|Y=c_k)\\ 24 | &=\prod^n_{j=1}P(X^{(j)}=x^{(j)}|Y=c_k) 25 | \end{aligned} 26 | $$ 27 | 28 | * 条件独立假设等于是说用于分类的**特征**在**类确定**的条件下都是**条件独立**的 29 | 30 | ### 参数估计 31 | 32 | #### 极大似然估计 33 | 34 | > 为了估计状态变量的条件分布,利用贝叶斯法则,有 35 | > $$ 36 | > \underbrace{P(X|Y)}_{posterior}=\frac{\overbrace{P(Y|X)}^{likelihood}\overbrace{P(X)}^{prior}}{\underbrace{P(Y)}_{evidence}}=\frac{\overbrace{P(Y|X)}^{likelihood}\overbrace{P(X)}^{prior}}{\underbrace{\sum\limits_x P(Y|X)P(X)}_{evidence}} 37 | > $$ 38 | > 其中$P(X|Y)$为给定$Y$下$X$的后验概率(Posterior), $P(Y|X)$称为似然(Likelyhood),$P(X)$称为先验(Prior)。 39 | > 40 | 41 | * 后验概率最大化的含义 42 | 43 | 朴素贝叶斯法将实例分到**后验概率最大的类**中, 这等价于**期望风险最小化**。 44 | 45 | * 后验是指观察到$Y$之后,对$X$的信念 46 | 47 | #### 贝叶斯估计 48 | 49 | * 对于$x$的某个特征的取值没有在先验中出现的情况 ,如果用极大似然估计就会出现所要估计的概率值为0的情况。这样会影响后验概率的计算结果,使分类产生偏差 50 | * 但是出现这种情况的原因通常是因为数据集不能全覆盖样本空间,出现未知的情况处理的策略就是做平滑 51 | $$ 52 | P_{\lambda}(X^{(j)}=a_{jl}|Y=c_k)=\frac{\sum\limits_{i=1}^NI(x_i^{j}=a_{jl},y_j=c_k)+\lambda}{\sum\limits_{i=1}^NI(y_j=c_k)+S_j\lambda} 53 | $$ 54 | 55 | * 当$\lambda = 0$的时候,就是极大似然估计 56 | 57 | * 当$\lambda=1$的时候,这个平滑方案叫做Laplace Smoothing。拉普拉斯平滑相当于给未知变量给定了先验概率 58 | 59 | 60 | ## 习题解答 61 | 62 | * 4.1 用极大似然估计法推出朴素贝叶斯法中的概率估计公式(4.8)及公式 (4.9) 63 | * 由于朴素贝叶斯法假设Y是定义在输出空间上的随机变量,因此可以定义$P(Y=c_k)=p$,令$m=\sum _{i=1}^NI(y_i=c_k)$ 64 | * 得出似然函数 $L(p)=p^m(1-p)^{N-m}$ 65 | * 求导求最值:$mp^{m-1}(1-p)^{N-m}-(N-m)p^m(1-p)^{N-m-1}=0$ 66 | * $p^{m-1}(1-p)^{N-m-1}(m-Np)=0$,易得$p=\frac mN$,即为公式(4.8) 67 | * 公式(4.9)的证明与公式(4.8)完全相同,定义$P(X^{(j)}=a_{jl}{\mid}Y=c_k)=p$,令$m=\sum_{i=1}^NI(y_i=c_k)$,$q=\sum_{i=1}^NI(x_i^{(j)}=a_{jl},y_i=c_k)$即可 68 | * 4.2 用贝叶斯估计法推出朴素贝叶斯法中的慨率估计公式(4.10)及公式(4.11) 69 | * 贝叶斯估计和传统的极大似然估计的区别就是,参数值是固定的还是也当做随机变量。传统的极大似然估计,把参数$\theta$当做固定的一个值,不变的,只是目前还不知道,通过最大化$L$求出$\theta$;贝叶斯估计认为参数$\theta$也是随机变量,它也服从一个分布(β分布) 70 | * 设$P(Y=c_k)=p$,$m=\sum _{i=1}^NI(y_i=c_k)$,加入先验概率,认为是均匀的$p=\frac{1}{K}$,对照上题极大似然概率下的条件概率约束 71 | * 得到$\lambda (pK-1)+pN-m=0$,从而解出$P(Y=c_k)=\frac{m+\lambda}{N+K\lambda}$,即为公式(4.11) 72 | 73 | -------------------------------------------------------------------------------- /Chapter4/例4.1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Tue Jun 4 14:05:30 2019 4 | 5 | @author: Administrator 6 | """ 7 | 8 | import numpy as np 9 | 10 | # SML分别对应为123 11 | 12 | X = np.array([[1, 1], [1, 2], [1, 2], [1, 1], [1, 1], [2, 1], [2, 2], [2, 2], [2, 3], [2, 3], [3, 3], [3,2], [3,2], [3, 3], [3, 3]]) 13 | Y = np.array([-1, -1, 1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, -1]) 14 | from sklearn.naive_bayes import GaussianNB 15 | clf = GaussianNB() 16 | #拟合数据 17 | clf.fit(X, Y) 18 | 19 | print(clf.predict([[2, 1]])) 20 | -------------------------------------------------------------------------------- /Chapter5/C4.5.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Sun Jun 9 14:30:23 2019 4 | 5 | @author: Administrator 6 | """ 7 | 8 | #C4.5 9 | import numpy as np 10 | import pandas as pd 11 | from math import log 12 | 13 | 14 | def create_data(): 15 | datasets = [['青年', '否', '否', '一般', '否'], 16 | ['青年', '否', '否', '好', '否'], 17 | ['青年', '是', '否', '好', '是'], 18 | ['青年', '是', '是', '一般', '是'], 19 | ['青年', '否', '否', '一般', '否'], 20 | ['中年', '否', '否', '一般', '否'], 21 | ['中年', '否', '否', '好', '否'], 22 | ['中年', '是', '是', '好', '是'], 23 | ['中年', '否', '是', '非常好', '是'], 24 | ['中年', '否', '是', '非常好', '是'], 25 | ['老年', '否', '是', '非常好', '是'], 26 | ['老年', '否', '是', '好', '是'], 27 | ['老年', '是', '否', '好', '是'], 28 | ['老年', '是', '否', '非常好', '是'], 29 | ['老年', '否', '否', '一般', '否'], 30 | ] 31 | labels = [u'年龄', u'有工作', u'有自己的房子', u'信贷情况', u'类别'] 32 | return datasets, labels 33 | 34 | datasets, labels = create_data() 35 | train_data = pd.DataFrame(datasets, columns=labels) 36 | 37 | 38 | class Node: 39 | def __init__(self,root=True,label=None,feature_name = None, feature = None): 40 | self.root = root 41 | self.label = label 42 | self.feature_name = feature_name 43 | self.feature = feature 44 | self.tree = {} 45 | self.result = {'label:':self.label,'feature':self.feature,'tree':self.tree} 46 | 47 | def __repr__(self): 48 | return '{}'.format(self.result) 49 | 50 | def add_node(self,val,node): 51 | self.tree[val] = node 52 | 53 | def predict(self,features): 54 | if self.root is True: 55 | return self.label 56 | return self.tree[features[self.feature]].predict(features) 57 | 58 | 59 | class DTree: 60 | def __init__(self,epsilon=0.1): 61 | self.epsilon = epsilon 62 | self._tree = {} 63 | 64 | # 经验熵 65 | @staticmethod #静态方法可以不实例化调用 66 | def entropy(datasets): 67 | data_length = len(datasets) 68 | label_count = {} 69 | for i in range(data_length): 70 | label = datasets[i][-1] 71 | if label not in label_count: 72 | label_count[label] = 0 73 | label_count[label] += 1 74 | ent = -sum([(p / data_length) * log(p / data_length, 2) 75 | for p in label_count.values()]) 76 | return ent 77 | 78 | # 经验条件熵 79 | def condition_entropy(self,datasets,axis = 0): 80 | data_length = len(datasets) 81 | feature_sets = {} 82 | for i in range(data_length): 83 | feature = datasets[i][axis] 84 | if feature not in feature_sets: 85 | feature_sets[feature] = [] 86 | feature_sets[feature].append(datasets[i]) 87 | condi_ent = sum([ (len(p) / data_length)*self.entropy(p) for p in feature_sets.values()]) 88 | 89 | HA=-sum([ (len(p) / data_length)*log(len(p) / data_length,2) for p in feature_sets.values()]) 90 | return condi_ent,HA 91 | 92 | # 信息增益比 93 | @staticmethod 94 | def info_gain_ratio(ent,condi_entropy,HA): 95 | return (ent - condi_entropy)/HA 96 | 97 | 98 | def info_gain_train(self, datasets): 99 | count = len(datasets[0]) - 1 100 | ent = self.entropy(datasets) 101 | best_feature = [] 102 | for c in range(count): 103 | condi_ent,HA=self.condition_entropy(datasets,axis=c) 104 | c_info_gain = self.info_gain_ratio(ent,condi_ent,HA) 105 | best_feature.append((c,c_info_gain)) 106 | print("特征({})的信息增益比为: {:.3f}".format(labels[c],c_info_gain)) 107 | best = max(best_feature, key=lambda x:x[-1]) 108 | return best 109 | 110 | def train(self,train_data): 111 | _,y_train,features = train_data.iloc[:,:-1],train_data.iloc[:,-1],train_data.columns[:-1] 112 | # 1,若D中实例属于同一类Ck,则T为单节点树,并将类Ck作为结点的类标记,返回T 113 | if len(y_train.value_counts()) == 1: 114 | return Node(root=True, label = y_train.iloc[0]) 115 | 116 | # 2, 若A为空,则T为单节点树,将D中实例树最大的类Ck作为该节点的类标记,返回T 117 | if len(features) == 0: 118 | return Node(root= True, label=y_train.value_counts().sort_values(ascending=False).index[0]) 119 | 120 | # 3,计算最大信息增益比 同5.1,Ag为信息增益比最大的特征 121 | max_feature, max_info_gain_ratio = self.info_gain_train(np.array(train_data)) 122 | max_feature_name = labels[max_feature] 123 | 124 | # 4,Ag的信息增益小于阈值epsilon,则置T为单节点树,并将D中是实例数最大的类Ck作为该节点的类标记,返回T 125 | if max_info_gain_ratio < self.epsilon: 126 | return Node(root=True,label= y_train.value_counts().sort_values(ascending=False).index[0]) 127 | 128 | # 5,构建Ag子集 129 | node_tree = Node(root = False,feature_name= max_feature_name, feature= max_feature) 130 | 131 | feature_list = train_data[max_feature_name].value_counts().index 132 | for f in feature_list: 133 | sub_train_df = train_data.loc[train_data[max_feature_name] == f].drop([max_feature_name],axis=1) 134 | # 6, 递归生成树 135 | sub_tree = self.train(sub_train_df) 136 | node_tree.add_node(f, sub_tree) 137 | return node_tree 138 | 139 | def fit(self,train_data): 140 | self._tree = self.train(train_data) 141 | return self._tree 142 | 143 | def predict(self,X_test): 144 | return self._tree.predict(X_test) 145 | 146 | datasets, labels = create_data() 147 | data_df = pd.DataFrame(datasets, columns=labels) 148 | dt = DTree() 149 | tree = dt.fit(data_df) 150 | print(tree) 151 | 152 | print(dt.predict(['老年', '否', '否', '一般'])) -------------------------------------------------------------------------------- /Chapter5/README.md: -------------------------------------------------------------------------------- 1 | # 决策树 2 | ## 笔记摘要 3 | * 决策树可以认为是if-then规则的集合,也可以认为是定义在特征空间上的条件概率分布 4 | * 根据损失函数最小化的原则建立决策树模型 5 | * 决策树的路径或其对应的if-then规则集合具有一个重要性质:互斥且完备 6 | * 决策树的学习算法包含特征选择、决策树的生成与决策树的剪枝 7 | * 决策树的生成对应于模型的局部选择,决策树的剪枝对应于模型的全局选择 8 | 9 | 10 | ### 熵 11 | 12 | $$ 13 | H(p)=H(X)=-\sum_{i=1}^{n}p_i\log p_i 14 | $$ 15 | 16 | * **熵只与$X$的分布有关,与$X$取值无关** 17 | 18 | * 定义$0\log0=0$,熵是非负的 19 | * 表示随机变量不确定性的度量 20 | 21 | ### 条件熵 22 | 23 | * 随机变量$(X,Y)$的联合概率分布为 24 | 25 | $$P(X=x_i,Y=y_j)=p_{ij}, i=1,2,\dots ,n;j=1,2,\dots ,m$$ 26 | 27 | * 条件熵$H(Y|X)$表示在已知随机变量$X$的条件下随机变量$Y$的不确定性 28 | $$ 29 | H(Y|X)=\sum_{i=1}^np_iH(Y|X=x_i) 30 | $$ 31 | 其中$p_i=P(X=x_i),i=1,2,\dots ,n$ 32 | 33 | ### 经验熵, 经验条件熵 34 | 35 | * 当熵和条件熵中的概率由数据估计(特别是极大似然估计)得到时,所对应的熵与条件熵分别称为经验熵和经验条件熵 36 | 37 | 38 | 39 | ### 信息增益 40 | 41 | * 特征$A$对训练数据集$D$的信息增益$g(D|A)$,定义为集合$D$的经验熵$H(D)$与特征$A$给定的条件下$D$的经验条件熵$H(D|A)$之差 42 | $$ 43 | g(D,A)=H(D)-H(D|A) 44 | $$ 45 | 46 | * 熵与条件熵的差称为互信息 47 | 48 | * 决策树中的信息增益等价于训练数据集中的类与特征的互信息 49 | 50 | * 考虑ID这种特征, 本身是唯一的。按照ID做划分, 得到的经验条件熵为0, 会得到最大的信息增益。所以, 按照信息增益的准则来选择特征, 可能会倾向于取值比较多的特征 51 | 52 | 53 | 54 | ### 信息增益比 55 | * 使用信息增益比可以对上面倾向取值较多的特征的问题进行校正 56 | $$ 57 | g_R(D,A)=\frac{g(D,A)}{H_A(D)}\\ 58 | H_A(D)=-\sum_{i=1}^n\frac{D_i}{D}log_2\frac{D_i}{D} 59 | $$ 60 | 61 | ### ID3算法 62 | 63 | > 输入:训练数据集$D$, 特征集$A$,阈值$\epsilon$ 64 | > 输出:决策树$T$ 65 | > 66 | > 1. 如果$D$中所有实例属于同一类$C_k$,则$T$为单节点树,并将类$C_k$作为该节点的类标记,返回$T$ 67 | > 1. 如果$A$是空集,则$T$为单节点树,并将实例数最多的类作为该节点类标记,返回$T$ 68 | > 1. 计算$g$, 选择信息增益最大的特征$A_g$ 69 | > 1. 如果$A_g$的信息增益小于$\epsilon$,则置$T$为单节点树,$D$中实例数最大的类$C_k$作为类标记,返回$T$ 70 | > 1. 否则,依$A_g=a_i$将D划分若干非空子集$D_i$,$D_i$中实例数最大的类$C_k$作为类标记,构建子结点,由结点及其子结点 构成树$T$,返回$T$ 71 | > 1. $D_i$训练集,$A-A_g$为特征集,递归调用前面步骤,得到$T_i$,返回$T_i$ 72 | 73 | 74 | 75 | 76 | 77 | ### C4.5的生成算法 78 | * 改用信息增益比来选择特征 79 | > 输入:训练数据集$D$, 特征集$A$,阈值$\epsilon$ 80 | > 输出:决策树$T$ 81 | > 82 | > 1. 如果$D$属于同一类$C_k$,$T$为单节点树,类$C_k$作为该节点的类标记,返回$T$ 83 | > 1. 如果$A$是空集, 置$T$为单节点树,实例数最多的作为该节点类标记,返回$T$ 84 | > 1. 计算$g$, 选择**信息增益比**最大的特征$A_g$ 85 | > 1. 如果$A_g$的**信息增益比**小于$\epsilon$,$T$为单节点树,$D$中实例数最大的类$C_k$作为类标记,返回$T$ 86 | > 1. 否则,依$A_g=a_i$将D划分若干非空子集$D_i$,$D_i$中实例数最大的类$C_k$作为类标记,构建子结点,由结点及其子结点 构成树$T$,返回$T$ 87 | > 1. $D_i$训练集,$A-A_g$为特征集,递归调用前面步骤,得到$T_i$,返回$T_i$ 88 | 89 | * ID3和C4.5在生成上,差异只在准则的差异 90 | 91 | 92 | 93 | ### 树的剪枝 94 | * 决策树的剪枝往往通过极小化决策树整体的损失函数或代价函数来实现的 95 | * 树$T$的叶结点个数为$|T|$,$t$是树$T$的叶结点,该结点有$N_t$个样本点,其中$k$类的样本点有$N_{tk}$个,$H_t(T)$为叶结点$t$上的经验熵, $\alpha\geqslant 0$为参数,决策树学习的损失函数可以定义为 96 | $$ 97 | C_\alpha(T)=\sum_{i=1}^{|T|}N_tH_t(T)+\alpha|T| 98 | $$ 99 | 其中 100 | $$ 101 | H_t(T)=-\sum_k\frac{N_{tk}}{N_t}\log \frac{N_{tk}}{N_t} 102 | $$ 103 | $$ 104 | C(T)=\sum_{t=1}^{|T|}N_tH_t(T)\color{black}=-\sum_{t=1}^{|T|}\sum_{k=1}^KN_{tk}\log\frac{N_{tk}}{N_t} 105 | $$ 106 | 这时有 107 | $$ 108 | C_\alpha(T)=C(T)+\alpha|T| 109 | $$ 110 | 其中$C(T)$表示模型对训练数据的误差,$|T|$表示模型复杂度,参数$\alpha \geqslant 0$控制两者之间的影响 111 | 112 | 113 | ### 剪枝算法 114 | 115 | > 输入:生成算法生成的整个树$T$,参数$\alpha$ 116 | > 117 | > 输出:修剪后的子树$T_\alpha$ 118 | > 119 | > 1. 计算每个结点的经验熵 120 | > 1. 递归地从树的叶结点向上回缩 121 | > 假设一组叶结点回缩到其父结点之前与之后的整体树分别是$T_B$和$T_A$,其对应的损失函数分别是$C_\alpha(T_A)$和$C_\alpha(T_B)$,如果$C_\alpha(T_A)\leqslant C_\alpha(T_B)$则进行剪枝,即将父结点变为新的叶结点 122 | > 1. 返回2,直至不能继续为止,得到损失函数最小的子树$T_\alpha$ 123 | * 决策树的剪枝算法可以由一种动态规划的算法实现 124 | 125 | ### CART 126 | 127 | * 决策树的生成就是递归地构建二叉决策树的过程。对回归树用平方误差最小化准则,对分类树用基尼系数最小化准则,并进行特征选择,生成二叉树 128 | #### 最小二乘回归树生成算法 129 | * 在训练数据集所在的输入空间中,递归地将每个区域划分为两个子区域并决定每个子区域上地输出值,构建二叉决策树 130 | 131 | >输入:训练数据集$D$ 132 | >输出:回归树$f(x)$ 133 | >步骤: 134 | >1. 遍历变量$j$,对固定的切分变量$j$扫描切分点$s$,得到满足下面式子的$(j,s)$ 135 | $$ 136 | \min\limits_{j,s}\left[\min\limits_{c_1}\sum\limits_{x_i\in R_1(j,s)}(y_i-c_1)^2+\min\limits_{c_2}\sum\limits_{x_i\in R_2(j,s)}(y_i-c_2)^2\right] 137 | $$ 138 | >1. 用选定的$(j,s)$, 划分区域并决定相应的输出值 139 | $$ 140 | R_1(j,s)=\{x|x^{(j)}\leq s\}, R_2(j,s)=\{x|x^{(j)}> s\} \\ 141 | \hat{c}_m= \frac{1}{N}\sum\limits_{x_i\in R_m(j,s)} y_j, x\in R_m, m=1,2 142 | $$ 143 | >1. 对两个子区域调用(1)(2)步骤, 直至满足停止条件 144 | >1. 将输入空间划分为$M$个区域$R_1, R_2,\dots,R_M$,生成决策树: 145 | $$ 146 | f(x)=\sum_{m=1}^M\hat{c}_mI(x\in R_m) 147 | $$ 148 | * 课后题有详细例子 149 | 150 | 151 | 152 | 153 | 154 | 155 | #### CART分类树的生成 156 | 157 | * 分类树用基尼指数选择最优特征,同时决定该特征的最优二值切分点 158 | 159 | * 概率分布的基尼指数定义 160 | 161 | $$ 162 | Gini(p) = \sum_{k=1}^Kp_k(1-p_k)=1-\sum_{k=1}^Kp_k^2 163 | $$ 164 | * 如果样本集合$D$根据特征$A$是否取某一可能值$a$被分割成$D_1$和$D_2$两部分,则在特征$A$的条件下,集合$D$的基尼指数定义为 165 | $$Gini(D,A)=\frac{|D_1|}{|D|}Gini(D_1)+\frac{|D_2|}{|D|}Gini(D_2)$$ 166 | >输入:训练数据集$D$,停止计算的条件 167 | >输出:CART决策树 168 | >根据训练数据集,从根节点开始,递归地对每个结点进行以下操作,构建二叉决策树: 169 | >1. 设结点地训练数据集为$D$,计算现有特征对该数据集的基尼指数。此时,对每一个特征$A$,对其可能取得每个值$a$,根据样本点对$A=a$的测试为“是”或“否”将$D$分成$D_1$和$D_2$两部分,计算$A=a$时的基尼指数 170 | >1. 在所有可能的特征$A$以及它们所有可能的切分点$a$中,选择基尼指数最小的特征及其对应的切分点作为最优特征与最优切分点。依照最优特征和最优切分点,从现结点生成两个子结点,将训练数据集依特征分配到两个子结点中去。 171 | >1. 对两个子结点递归地调用1、2,直至满足停止条件 172 | >1. 生成CART决策树 173 | * 算法停止计算的条件是结点中的样本个数小于预定阈值,或样本集的基尼指数小于指定阈值,或者没有更多特征 174 | 175 | 176 | ## 习题解答 177 | 178 | * 5.1 根据表 5.1 所给的训练数据集,利用信息增益比(C4.5 算法)生成决策树 179 | * 编写程序计算信息增益比,并利用C4.5算法生成决策树,得到结果如下 180 | 特征(年龄)的信息增益比为: 0.052 181 | 特征(有工作)的信息增益比为: 0.352 182 | 特征(有自己的房子)的信息增益比为: 0.433 183 | 特征(信贷情况)的信息增益比为: 0.232 184 | 特征(年龄)的信息增益比为: 0.164 185 | 特征(有工作)的信息增益比为: 1.000 186 | 特征(有自己的房子)的信息增益比为: 0.340 187 | * 决策树 188 | {'label:': None, 'feature': 2, 'tree': {'否': {'label:': None, 'feature': 1, 'tree': {'否': {'label:': '否', 'feature': None, 'tree': {}}, '是': {'label:': '是', 'feature': None, 'tree': {}}}}, '是': {'label:': '是', 'feature': None, 'tree': {}}}} 189 | * 结果与ID3算法完全相同 190 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/2019060915344250.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x5YzQ0ODEzNDE4,size_16,color_FFFFFF,t_70#pic_center) 191 | 192 | * 5.2 已知如表 5.2 所示的训练数据,试用平方误差损失准则生成一个二叉回归树 193 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/201906091538427.png#pic_center) 194 | 195 | * 5.3 证明 CART 剪枝算法中,当$α$确定时,存在唯一的最小子树 $T_α$使损失函数 $C_α(T)$最小 196 | * 利用反证法,假设存在两个最小子树使损失函数最小 197 | 设这两棵最小子树 为$T_1$​ 和 $T_2$​ ,其剪枝位置分别是 $t_1$​ 和 $t_2$​ ,两者都能使得损失函数最小,即两者拥有相等的 $C_\alpha(T)​$ 198 | 又有: 199 | $$C_\alpha(t_1) 输入:训练数据集$T={(x_1,y_1),(x_2,y_2),\dots, (x_N,y_N)}$,其中$x_i\in\mathcal X=\bf R^n, y_i\in\mathcal Y=\{-1,+1\}, i=1,2,\dots,N$,精度$\epsilon$ 316 | > 317 | > 输出:近似解$\hat\alpha$ 318 | > 319 | > 1. 取初值$\alpha_0=0$,令$k=0$ 320 | > 321 | > 1. **选取**优化变量$\alpha_1^{(k)},\alpha_2^{(k)}$,解析求解两个变量的最优化问题,求得最优解$\alpha_1^{(k+1)},\alpha_2^{(k+1)}$,更新$\alpha$为$\alpha^{k+1}$ 322 | > 323 | > 1. 若在精度$\epsilon$范围内满足停止条件 324 | > $$ 325 | > \sum_{i=1}^{N}\alpha_iy_i=0\\ 326 | > 0\leqslant\alpha_i\leqslant C,i=1,2,\dots,N\\ 327 | > y_i\cdot g(x_i)= 328 | > \begin{cases} 329 | > \geqslant1,\{x_i|\alpha_i=0\}\\ 330 | > =1,\{x_i|0<\alpha_i \leqslant1,\{x_i|\alpha_i=C\} 332 | > \end{cases}\\ 333 | > g(x_i)=\sum_{j=1}^{N}\alpha_jy_jK(x_j,x_i)+b 334 | > $$ 335 | > 则转4,否则,$k=k+1$转2 336 | > 337 | > 1. 取$\hat\alpha=\alpha^{(k+1)}$ 338 | 339 | # 习题解答 340 | 341 | * 1.**比较感知机的对偶形式与线性可分支持向量机的对偶形式** 342 | * 感知机的对偶形式 343 | $f(x)=sign\left(\sum_{j=1}^N\alpha_jy_jx_j\cdot x+b\right), 344 | \alpha=(\alpha_1,\alpha_2,\cdots,\alpha_N)^T$ 345 | * 线性可分支持向量机的对偶形式 346 | $f(x)=sign\left(\sum_{i=1}^N\alpha_i^*y_ix_i\cdot x+b^*\right), 347 | \alpha^*=(\alpha_1^*,\alpha_2^*,\cdots,\alpha_N^*)^T$ 348 | 感知机学习算法的原始形式和对偶形式与线性可分支持向量机学习算法的原始形式和对偶形式相对应。在线性可分支持向量机的对偶形式中,$w$也是被表示为实例 $x_i$和标记$y_i$的线性组合的形式 349 | $$w=\sum_{i=1}^{N}\alpha_iy_ix_i$$ 350 | 而它们的偏置$b$的形式不同,前者$b=\sum_{i=1}^{N}\alpha_iy_i$,而后者$b^*=y_j\color{black}-\sum_{i=1}^{N}\alpha_i^*y_i(x_i\cdot x_j)$ 351 | * 2.**已知正例点$x_1=(1,2)^T$,$x_2=(2,3)^T$,$x_3=(3,3)^T$,负例点$x_4=(2,1)^T$,$x_5=(3,2)^T$, 352 | 试求最大间隔分离超平面和分类决策函数,并在图上画出分离超平面、间隔边界及支持向量** 353 | * 根据书中算法,计算可得$w_1=-1$,$w_2=2$,$b=-2$,即最大间隔分离超平面为 354 | $$-x^{(1)}+2x^{(2)}-2=0$$ 355 | 分类决策函数为 356 | $$f(x)=sign(-x^{(1)}+2x^{(2)}-2)$$ 357 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190708102330284.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x5YzQ0ODEzNDE4,size_16,color_FFFFFF,t_70#pic_center) 358 | 359 | * 3.**线性支持向量机还可以定义为以下形式:** 360 | 361 | $$\min_{w,b,\xi}{\frac{1}{2}\|w\|^2}+C\sum^N_{i=1}\xi_i^2\\s.t.{\quad}y_i(w{\cdot}x_i+b)\ge1-\xi_i,\,i=1,2,\cdots,N\\\xi_i\ge0,\,i=1,2,\cdots,N$$ 362 | **试求其对偶形式** 363 | * 首先求得原始化最优问题的拉格朗日函数是: 364 | $L(w,b,\alpha,\xi,μ)=\frac{1}{2}\left\|w\right\|^2+C\sum_{i=1}^N\xi_i^2-\sum_{i=1}^N\alpha_i(y_i(w\cdot x_i+b-1)+\xi_i)-\sum_{i=1}^Nμ_i\xi_i$ 365 | * 对偶问题是拉格朗日的极大极小问题。首先求$L(w,b,\alpha,\xi,μ)$对$w,b,\xi$的极小,即对该三项求偏导,得 366 | $$ 367 | w=\sum_{i=1}^{N}\alpha_iy_ix_i\\ 368 | \sum_{i=1}^N\alpha_iy_i=0\\ 369 | 2C\xi_i-\alpha_i-μ_i=0 370 | $$ 371 | 将上述带入拉格朗日函数,得 372 | $$-\frac{1}{2}\sum_{i=1}^N\sum_{j=1}^N\alpha_i\alpha_jy_iy_j(x_i\cdot x_j)-C\sum_{i=1}^N\xi_i^2+\sum_{i=1}^N\alpha_i\\ 373 | -\frac{1}{2}\sum_{i=1}^N\sum_{j=1}^N\alpha_i\alpha_jy_iy_j(x_i\cdot x_j)-\frac{1}{4C}\sum_{i=1}^N(\alpha_i+μ_i)^2+\sum_{i=1}^N\alpha_i$$ 374 | * 4.**证明内积的正整数幂函数$K(x,z)=(x{\cdot}z)^p$是正定核函数,这里$p$是正整数,$x,z{\in}R^n$** 375 | * 要证明正整数幂函数是正定核函数,只需证明其对应得Gram矩阵$K=[K(x_i,x_j)]_{m\times m}$是半正定矩阵 376 | * 对任意$c_1,c_2…c_m\in R$,有 377 | 378 | $$ 379 | \begin{aligned} 380 | \sum_{i,j=1}^{m}c_ic_jK(x_i,x_j)\\ 381 | =&\sum_{i,j=1}^{m}c_ic_j(x_i\cdot x_j)^p\\ 382 | =&(\sum_{i=1}^{m}c_ix_i)(\sum_{j=1}^{m}c_jx_j)(x_ix_j)^{p-1}\\ 383 | =&||\sum_{i=1}^{m}c_ix_i||^2(x_ix_j)^{p-1} 384 | \end{aligned} 385 | $$ 386 | * 由于p大于等于1,该式子也大于等于0,即Gram矩阵半正定,所以正整数的幂函数是正定核函数 -------------------------------------------------------------------------------- /Chapter7/SVM.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Wed Jun 26 16:49:20 2019 4 | 5 | @author: Lee 6 | """ 7 | 8 | import numpy as np 9 | import pandas as pd 10 | import matplotlib.pyplot as plt 11 | from sklearn.datasets import load_iris 12 | from sklearn.model_selection import train_test_split 13 | 14 | iris = load_iris() 15 | df = pd.DataFrame(iris.data, columns=iris.feature_names) 16 | df['label'] = iris.target 17 | df.columns = ['sepal length', 'sepal width', 'petal length', 'petal width', 'label'] 18 | 19 | plt.scatter(df[:50]['sepal length'], df[:50]['sepal width'], label='0') 20 | plt.scatter(df[50:100]['sepal length'], df[50:100]['sepal width'], label='1') 21 | plt.xlabel('sepal length') 22 | plt.ylabel('sepal width') 23 | plt.legend() 24 | 25 | data = np.array(df.iloc[:100, [0, 1, -1]]) 26 | X, y = data[:,:-1], data[:,-1] 27 | X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2) 28 | 29 | 30 | # 根据SMO序列最小最优化算法更新参数值 31 | class SVM: 32 | def __init__(self, max_iter=100, kernel='linear'): 33 | self.max_iter = max_iter 34 | self._kernel = kernel 35 | 36 | def init_args(self, features, labels): 37 | self.m, self.n = features.shape 38 | self.X = features 39 | self.Y = labels 40 | self.b = 0.0 41 | 42 | # 将Ei保存在一个列表里 43 | self.alpha = np.ones(self.m) 44 | self.E = [self._E(i) for i in range(self.m)] 45 | # 惩罚参数C 46 | self.C = 1.0 47 | 48 | # 判断是否满足KKT条件 49 | def _KKT(self, i): 50 | y_g = self._g(i)*self.Y[i] 51 | if self.alpha[i] == 0: #7.111 52 | return y_g >= 1 53 | elif 0 < self.alpha[i] < self.C: #7.112 间隔边界 54 | return y_g == 1 55 | else: #7.113 56 | return y_g <= 1 57 | 58 | # g(x)预测值,输入xi(X[i]) 59 | def _g(self, i): #7.104 60 | r = self.b 61 | for j in range(self.m): 62 | r += self.alpha[j]*self.Y[j]*self.kernel(self.X[i], self.X[j]) 63 | return r 64 | 65 | # 核函数 66 | def kernel(self, x1, x2): 67 | if self._kernel == 'linear': 68 | return sum([x1[k]*x2[k] for k in range(self.n)]) 69 | elif self._kernel == 'poly': 70 | return (sum([x1[k]*x2[k] for k in range(self.n)]) + 1)**2 71 | else: 72 | return 0 73 | 74 | # E(x)为g(x)对输入x的预测值和y的差 75 | def _E(self, i): #7.105 76 | return self._g(i) - self.Y[i] 77 | 78 | def _init_alpha(self): 79 | # 外层循环首先遍历所有满足0= 0: 93 | j = min(range(self.m), key=lambda x: self.E[x]) 94 | else: 95 | j = max(range(self.m), key=lambda x: self.E[x]) 96 | return i, j 97 | 98 | # 剪辑使满足0<=alpha<=C的约束条件 99 | def _compare(self, _alpha, L, H): #7.108 100 | if _alpha > H: 101 | return H 102 | elif _alpha < L: 103 | return L 104 | else: 105 | return _alpha 106 | 107 | def fit(self, features, labels): 108 | self.init_args(features, labels) 109 | 110 | for t in range(self.max_iter): 111 | # train 112 | i1, i2 = self._init_alpha() 113 | 114 | # 边界 115 | if self.Y[i1] == self.Y[i2]: 116 | L = max(0, self.alpha[i1]+self.alpha[i2]-self.C) 117 | H = min(self.C, self.alpha[i1]+self.alpha[i2]) 118 | else: 119 | L = max(0, self.alpha[i2]-self.alpha[i1]) 120 | H = min(self.C, self.C+self.alpha[i2]-self.alpha[i1]) 121 | 122 | E1 = self.E[i1] 123 | E2 = self.E[i2] 124 | # eta=K11+K22-2K12 125 | eta = self.kernel(self.X[i1], self.X[i1]) + self.kernel(self.X[i2], self.X[i2]) - 2*self.kernel(self.X[i1], self.X[i2]) #7.107 126 | if eta <= 0: 127 | # print('eta <= 0') 128 | continue 129 | 130 | alpha2_new_unc = self.alpha[i2] + self.Y[i2] * (E1 - E2) / eta #7.106 131 | alpha2_new = self._compare(alpha2_new_unc, L, H) #7.109 132 | 133 | alpha1_new = self.alpha[i1] + self.Y[i1] * self.Y[i2] * (self.alpha[i2] - alpha2_new) 134 | 135 | b1_new = -E1 - self.Y[i1] * self.kernel(self.X[i1], self.X[i1]) * (alpha1_new-self.alpha[i1]) - self.Y[i2] * self.kernel(self.X[i2], self.X[i1]) * (alpha2_new-self.alpha[i2])+ self.b #7.115 136 | b2_new = -E2 - self.Y[i1] * self.kernel(self.X[i1], self.X[i2]) * (alpha1_new-self.alpha[i1]) - self.Y[i2] * self.kernel(self.X[i2], self.X[i2]) * (alpha2_new-self.alpha[i2])+ self.b #7.116 137 | 138 | if 0 < alpha1_new < self.C and 0 < alpha2_new < self.C: 139 | b_new = b1_new 140 | else: 141 | b_new = (b1_new + b2_new) / 2 142 | 143 | # 更新参数 144 | self.alpha[i1] = alpha1_new 145 | self.alpha[i2] = alpha2_new 146 | self.b = b_new 147 | 148 | self.E[i1] = self._E(i1) 149 | self.E[i2] = self._E(i2) 150 | print('train done!') 151 | 152 | 153 | def predict(self, data): 154 | r = self.b 155 | for i in range(self.m): 156 | r += self.alpha[i] * self.Y[i] * self.kernel(data, self.X[i]) 157 | 158 | return 1 if r > 0 else -1 159 | 160 | def score(self, X_test, y_test): 161 | right_count = 0 162 | for i in range(len(X_test)): 163 | result = self.predict(X_test[i]) 164 | if result == y_test[i]: 165 | right_count += 1 166 | return right_count / len(X_test) 167 | 168 | 169 | svm = SVM(max_iter=100) 170 | svm.fit(X_train, y_train) 171 | print(svm.score(X_test, y_test)) 172 | 173 | #sklearn 174 | 175 | from sklearn.svm import SVC 176 | clf = SVC() 177 | clf.fit(X_train, y_train) 178 | 179 | print(clf.score(X_test, y_test)) -------------------------------------------------------------------------------- /Chapter7/surrogate_loss_function.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Wed Jun 26 15:17:50 2019 4 | 5 | @author: Lee 6 | """ 7 | 8 | import numpy as np 9 | import matplotlib.pyplot as plt 10 | 11 | x = np.linspace(-2,2,200) 12 | # perceptron loss 13 | y1 = list(map(lambda x: max(0, -x), x)) 14 | # hinge loss 15 | y2 = list(map(lambda x: max(0,1-x), x)) 16 | # 0-1 loss 17 | y3 = list(map(lambda x:1 if x <= 0 else 0, x)) 18 | 19 | # lr loss 20 | y4 = list(map(lambda x:np.log2(1+np.exp(-x)), x)) 21 | # adaboost 22 | y5 = list(map(lambda x:np.exp(-x), x)) 23 | plt.plot(x,y1,'--', label='perceptron loss') 24 | plt.plot(x,y2, '-', label='hinge loss' ) 25 | plt.plot(x,y3, '-', label='0-1 loss') 26 | plt.plot(x,y4, '-', label='lr') 27 | plt.plot(x,y5, '-', label='adaboost') 28 | 29 | plt.legend() 30 | plt.xlim(-2,2) 31 | plt.ylim(0,2) 32 | plt.xlabel("functional margin") 33 | plt.ylabel("loss") 34 | plt.savefig("test.png") 35 | plt.show() 36 | 37 | -------------------------------------------------------------------------------- /Chapter7/test.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/librauee/Statistical-Learning/c988aea60ba0ed5a01b10d31f4a823eb3c75f3b7/Chapter7/test.png -------------------------------------------------------------------------------- /Chapter7/习题7.2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Jul 8 10:07:14 2019 4 | 5 | @author: Lee 6 | """ 7 | 8 | from sklearn import svm 9 | x=[[1, 2], [2, 3], [3, 3], [2, 1], [3, 2]] 10 | y=[1, 1, 1, -1, -1] 11 | # 给以极大的惩罚参数C,可以得到线性可分支持向量机 12 | clf = svm.SVC(kernel='linear',C=100000) 13 | clf.fit(x, y) 14 | print(clf.coef_) 15 | print(clf.intercept_) 16 | 17 | 18 | import matplotlib.pyplot as plt 19 | import numpy as np 20 | plt.scatter([i[0] for i in x], [i[1] for i in x], c=y) 21 | xaxis = np.linspace(0, 3.5) 22 | w = clf.coef_[0] 23 | a = -w[0] / w[1] 24 | y_sep = a * xaxis - (clf.intercept_[0]) / w[1] 25 | b1 = clf.support_vectors_[0] 26 | yy_down = a * xaxis + (b1[1] - a * b1[0]) 27 | b2 = clf.support_vectors_[-1] 28 | yy_up = a * xaxis + (b2[1] - a * b2[0]) 29 | plt.plot(xaxis, y_sep, 'k-') 30 | plt.plot(xaxis, yy_down, 'k--') 31 | plt.plot(xaxis, yy_up, 'k--') 32 | plt.scatter(clf.support_vectors_[:, 0], clf.support_vectors_[:, 1], s=150, facecolors='none', edgecolors='k') 33 | plt.show() 34 | -------------------------------------------------------------------------------- /Chapter8/AdaBoost习题8.1.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Mon Jul 22 12:22:56 2019 4 | 5 | @author: Lee 6 | """ 7 | import numpy as np 8 | 9 | class AdaBoost: 10 | def __init__(self,n_estimators=30,learning_rate=0.1): 11 | self.clf_num=n_estimators 12 | self.learning_rate=learning_rate 13 | 14 | def init_args(self,data,labels): 15 | self.X=data 16 | self.y=labels 17 | self.M,self.N=data.shape 18 | # 弱分类器数目和集合 19 | self.clf_sets=[] 20 | # 初始化weights,均分 21 | self.weights=[1.0/self.M]*self.M 22 | # 基本分类器的系数 alpha 23 | self.alpha=[] 24 | 25 | def _classify(self,features,labels,weights): 26 | m=len(features) 27 | error=1.0 # 初始化误差率 28 | best_v=0.0 # 初始化分类结点 29 | # 单维特征 30 | feature_min=min(features) 31 | feature_max=max(features) 32 | # 需要的步骤数目 33 | n_step=(feature_max-feature_min+self.learning_rate)/self.learning_rate 34 | direct,compare_array=None,None # 初始化方式和结果数组 35 | for i in range(1,int(n_step)): 36 | v=feature_min+self.learning_rate*i 37 | if v not in features: 38 | # 计算在训练集上的分类误差率 39 | # 不改变所给的训练数据,但是不断改变数据权值分布 40 | compare_array_positive=np.array([1 if features[k]>v else -1 for k in range(m)]) 41 | weight_error_positive=sum([weights[k] for k in range(m) if compare_array_positive[k]!=labels[k]]) 42 | compare_array_negative=np.array([-1 if features[k]>v else 1 for k in range(m)]) 43 | weight_error_negative=sum([weights[k] for k in range(m) if compare_array_negative[k]!=labels[k]]) 44 | 45 | if weight_error_positive<=weight_error_negative: 46 | weight_error=weight_error_positive 47 | _compare_array=compare_array_positive 48 | direct='positive' 49 | else: 50 | weight_error=weight_error_negative 51 | _compare_array=compare_array_negative 52 | direct='negative' 53 | 54 | if weight_errorv else -1 78 | else: 79 | return -1 if x>v else 1 80 | 81 | 82 | 83 | def fit(self,X,y): 84 | self.init_args(X,y) 85 | 86 | for epoch in range(self.clf_num): 87 | best_clf_error,best_v,clf_result=1.0,None,None 88 | # 根据特征维度, 选择误差最小的 89 | for j in range(self.N): 90 | features=self.X[:,j] 91 | # 分类阈值,分类误差,分类结果 92 | v,direct,error,compare_array=self._classify( 93 | features,self.y,self.weights) 94 | 95 | if errorv else -1 for k in range(m)]) 42 | weight_error_positive=sum([weights[k] for k in range(m) if compare_array_positive[k]!=labels[k]]) 43 | compare_array_negative=np.array([-1 if features[k]>v else 1 for k in range(m)]) 44 | weight_error_negative=sum([weights[k] for k in range(m) if compare_array_negative[k]!=labels[k]]) 45 | 46 | if weight_error_positive<=weight_error_negative: 47 | weight_error=weight_error_positive 48 | _compare_array=compare_array_positive 49 | direct='positive' 50 | else: 51 | weight_error=weight_error_negative 52 | _compare_array=compare_array_negative 53 | direct='negative' 54 | 55 | if weight_errorv else -1 79 | else: 80 | return -1 if x>v else 1 81 | 82 | 83 | 84 | def fit(self,X,y): 85 | self.init_args(X,y) 86 | 87 | for epoch in range(self.clf_num): 88 | best_v,final_direct,best_clf_error,clf_result=self._classify(self.X,self.y,self.weights) 89 | # 如果分类器已经完全分类,停止迭代 90 | if self.test()==1: 91 | break 92 | else: 93 | # 计算G(x)系数a 94 | a=self._alpha(best_clf_error) 95 | self.alpha.append(a) 96 | # 记录分类器 97 | self.clf_sets.append((best_v,final_direct)) 98 | Z=self._Z(self.weights,a,clf_result) 99 | self._w(a,clf_result,Z) 100 | print("已经训练完第{}个弱分类器,分类点为{},分类方式为{},分类误差为{:.4f},权重为{}" 101 | .format(epoch+1,best_v,final_direct,best_clf_error,self.weights)) 102 | 103 | 104 | print(self.clf_sets) 105 | 106 | def predict(self,feature): 107 | result=0.0 108 | for i in range(len(self.clf_sets)): 109 | clf_v,direct=self.clf_sets[i] 110 | result+=self.alpha[i]*self.G(feature,clf_v,direct) 111 | return np.sign(result) 112 | 113 | def test(self): 114 | right_count = 0 115 | for i in range(len(self.X)): 116 | feature=self.X[i] 117 | if self.predict(feature)==self.y[i]: 118 | right_count += 1 119 | return right_count/len(self.X) 120 | 121 | 122 | datasets=[0,1,2,3,4,5,6,7,8,9] 123 | labels=[1,1,1,-1,-1,-1,1,1,1,-1] 124 | 125 | clf=AdaBoost() 126 | clf.fit(datasets,labels) -------------------------------------------------------------------------------- /Chapter8/README.md: -------------------------------------------------------------------------------- 1 | # 提升方法 2 | ## 笔记摘要 3 | * 在PAC(概率近似正确(PAC, Probably approximately correct))学习框架下,一个概念是强可学习的**充分必要条件**是这个概念是弱可学习的。 4 | * 提升方法的两个问题 5 | 1. 在每一轮如何改变训练数据的权值或概率分布 6 | 2. 如何将**弱分类器**组合成一个**强分类器** 7 | 8 | * Adaboost的解决方案: 9 | 3. 提高那些被前一轮弱分类器错误分类样本的权值,降低那些被正确分类的样本的权值 10 | 4. 加权多数表决的方法,加大分类误差率小的弱分类器的权值,减小分类误差率大的弱分类器的权值 11 | 12 | 13 | ### AdaBoost算法 14 | * 输入:弱学习算法和训练数据集 15 | $T=\{(x_1,y_1), (x_2,y_2),...,(x_N,y_N)\}, x\in X \subseteq R^n$ 16 | * 输出:最终分类器$G(x)$ 17 | * 步骤 18 | 1. 初始化训练数据的权值分布 $D_1=(w_{11},\cdots,w_{1i},\cdots,w_{1N},w_{1i}=\frac{1}{N})​$ 19 | 2. m = 1,2, $\cdots$,M 20 | ( a ) 使用具有权值分布$D_m$的训练数据集学习,得到基本的分类器 21 | $$G_m(x):X→\{-1,+1\}$$ 22 | ( b ) 计算$G_m(x)$在训练集上的分类误差率 23 | $$e_m=\sum_{i=1}^{N}P(G_m(x_i)\not= y_i)=\sum_{i=1}^{N}w_{mi}I(G_m(x_i)\not=y_i)$$ 24 | ( c ) 计算$G_m(x)$的系数 25 | $$\alpha_m=\frac{1}{2}log\frac{1-e_m}{e_m}$$ 26 | ( d ) 更新训练数据集的权值分布 27 | $$w_{m+1,i}=\frac{w_{mi}}{Z_m}exp(-\alpha_my_iG_m(x_i))​$$ 28 | $$Z_m=\sum_{i=1}^Nw_{mi}exp(-\alpha_my_iG_m(x_i))$$ 29 | 3. $f(x)=\sum_{m=1}^M\alpha_mG_m(x)$ 30 | 4. 最终分类器$G(x)=sign(f(x))=sign(\sum_{m=1}^M\alpha_mG_m(x))$ 31 | 32 | * 误分类样本在下一轮学习中起更大的作用。不改变所给的训练数据,而不断改变训练数据权值的分布,使得训练数据在基本分类器的学习中起不同的作用, 这是AdaBoost的一个特点 33 | * 利用基本分类器的线性组合构建最终分类器使AdaBoost的另一特点 34 | 35 | 36 | 37 | ### AdaBoost算法的训练误差分析 38 | 39 | 40 | 41 | * AdaBoost算法最终分类器的训练误差界为 42 | $$ 43 | \frac{1}{N}\sum\limits_{i=1}\limits^N I(G(x_i)\neq y_i)\le\frac{1}{N}\sum\limits_i\exp(-y_i f(x_i))=\prod\limits_m Z_m 44 | $$ 45 | 这个的意思就是说指数损失是0-1损失的上界,这个上界使通过递推得到的,是归一化系数的连乘 46 | 47 | 48 | 49 | ### AdaBoost算法的解释 50 | * 模型为加法模型, 损失函数为指数函数, 学习算法为前向分步算法时的二分类学习方法。根据这些条件可以推导出AdaBoost 51 | 52 | #### 前向分步算法 53 | * 输入:训练数据集$T={(x_1,y_1),(x_2,y_2),...,(x_N, y_N)}, x_i \in X \sube \R^n, y_i\in \{-1, 1\}$, 损失函数$L(y, f(x))$; 基函数集合$\{b(x;\gamma)\}$ 54 | 55 | * 输出:加法模型$f(x)$ 56 | 57 | * 步骤: 58 | 59 | 1. 初始化$f_0(x)=0$ 60 | 61 | 1. 对$m=1,2,\cdots,M$, 极小化损失函数 62 | $$ 63 | (\beta_m,\gamma_m)=\arg\min \limits_ {\beta,\gamma}\sum_{i=1}^NL(y_i, f_{m-1}(x_i)+\beta b(x_i;\gamma)) 64 | $$ 65 | 66 | 1. 更新 67 | $$ 68 | f_m(x)=f_{m-1}(x)+\beta _mb(x;\gamma_m) 69 | $$ 70 | 71 | 1. 得到加法模型 72 | $$ 73 | f(x)=f_M(x)=\sum_{m=1}^M\beta_m b(x;\gamma_m) 74 | $$ 75 | 76 | 77 | ### 提升树 78 | * 提升树是以分类树或回归树为基本分类器的提升方法,被认为是统计学习中性能最好的方法之一 79 | * 提升方法实际采用加法模型(即基函数的线性组合)与前向分步算法 80 | 81 | #### 提升树模型 82 | 83 | * 以决策树为基函数的提升方法称为提升树 84 | * 提升树模型可以表示成决策树的加法模型 85 | $$ 86 | f_M(x)=\sum_{m=1}^MT(x;\Theta_m) 87 | $$ 88 | 89 | 90 | 91 | 92 | #### 提升树算法 93 | 94 | * 针对不同问题的提升树学习算法, 其主要区别在于使用的损失函数不同: 95 | 96 | 1. 平方误差损失函数用于回归问题 97 | 2. 指数损失函数用于分类问题 98 | 3. 一般损失函数的一般决策问题 99 | 100 | #### 回归问题的提升树算法 101 | 102 | * 输入:训练数据集$T={(x_1,y_1),(x_2,y_2),...,(x_N, y_N)}, x_i \in X \sube \R^n,y_i \in Y \sube R$ 103 | 104 | * 输出:提升树$f_M(x)$ 105 | 106 | * 步骤: 107 | 108 | 1. 初始化$f_0(x)=0$ 109 | 1. 对$m=1,2,\dots,M$ 110 | 1. 计算残差 111 | $$ 112 | r_{mi}=y_i-f_{m-1}(x_i), i=1,2,\dots,N 113 | $$ 114 | 1. **拟合残差**$r_{mi}$学习一个回归树,得到$T(x;\Theta_m)$ 115 | 1. 更新$f_m(x)=f_{m-1}(x)+T(x;\Theta_m)$ 116 | 1. 得到回归问题提升树 117 | $$ 118 | f(x)=f_M(x)=\sum_{m=1}^MT(x;\Theta_m) 119 | $$ 120 | 121 | ### 梯度提升(GBDT) 122 | 123 | 输入: 训练数据集$T={(x_1,y_1),(x_2,y_2),\dots,(x_N,y_N)}, x_i \in x \sube \R^n, y_i \in y \sube \R$;损失函数$L(y,f(x))$ 124 | 输出:回归树$\hat{f}(x)$ 125 | 步骤: 126 | 1. 初始化 127 | $$ 128 | f_0(x)=\arg\min\limits_c\sum_{i=1}^NL(y_i, c) 129 | $$ 130 | 131 | 2. 对$m=1,2,\cdots,M$ 132 | 133 | ( a )对$i=1,2,\cdots,N$,计算 134 | $$ 135 | r_{mi}=-\left[\frac{\partial L(y_i, f(x_i))}{\partial f(x_i)}\right]_{f(x)=f_{m-1}(x)} 136 | $$ 137 | ( b )对$r_{mi}$拟合一个回归树,得到第$m$棵树的叶节点区域$R_{mj}, j=1,2,\dots,J$ 138 | 139 | ( c ) 对$j=1,2,\dots,J$,计算 140 | $$ 141 | c_{mj}=\arg\min_c\sum_{xi\in R_{mj}}L(y_i,f_{m-1}(x_i)+c) 142 | $$ 143 | 144 | 4. 更新 145 | $$ 146 | f_m(x)=f_{m-1}(x)+\sum_{j=1}^Jc_{mj}I(x\in R_{mj}) 147 | $$ 148 | 149 | 5. 得到回归树 150 | $$ 151 | \hat{f}(x)=f_M(x)=\sum_{m=1}^M\sum_{j=1}^Jc_{mj}I(x\in R_{mj}) 152 | $$ 153 | 154 | 155 | 156 | ## 习题解答 157 | * 某公司招聘职员考查身体、业务能力、发展潜力这 3 项。身体分为合格1、不合格0两级,业务能力和发展潜力分为上1、中2、下3三级分类为合格1 、不合格-1两类。已知10个人的数据,如下表所示。假设弱分类器为决策树桩。.试用AdaBoost算法学习一个强分类器。 158 | ![在这里插入图片描述](https://img-blog.csdnimg.cn/20190719200718138.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2x5YzQ0ODEzNDE4,size_16,color_FFFFFF,t_70) 159 | [代码传送门](https://github.com/librauee/Statistical-Learning) 160 | * 比较支持向量机、 AdaBoost 、逻辑斯谛回归模型的学习策略与算法。 161 | 162 | * 支持向量机的学习策略是当训练数据近似线性可分时,通过软间隔最大化,学习一个线性分类器,其学习算法是SMO序列最小最优化算法 163 | * AdaBoost的学习策略是通过极小化加法模型的指数损失,得到一个强分类器,其学习算法是前向分步算法 164 | * 逻辑斯谛回归模型的学习策略是在给定的训练数据条件下对模型进行极大似然估计或正则化的极大似然估计,其学习算法可以是改进的迭代尺度算法(IIS),梯度下降法,牛顿法以及拟牛顿法 165 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Hits](https://www.smirkcao.info/hit_gits/Statistical-Learning/README.md) 2 | # 统计学习方法(第二版) 李航 3 | 4 | 每一单元的**知识要点整理**,**课后习题解答**,以及**算法的Python实现** 5 | 6 | ## 第一篇 监督学习 7 | * Chapter1 统计学习及监督学概论 8 | * Chapter2 感知机 9 | * Chapter3 k近邻法 10 | * Chapter4 朴素贝叶斯法 11 | * Chapter5 决策树 12 | * Chapter6 逻辑斯谛回归与最大熵模型 13 | * Chapter7 支持向量机 14 | * Chapter8 提升方法 15 | * Chapter9 EM算法及其推广 16 | * Chapter10 隐马尔可夫模型 17 | * Chapter11 条件随机场 18 | * Chapter12 监督学习方法总结 19 | ## 第二篇 无监督学习 20 | * Chapter13 无监督学习概论 21 | * Chapter14 聚类方法 22 | * Chapter15 奇异值分解 23 | * Chapter16 主成分分析 24 | * Chapter17 潜在语义分析 25 | * Chapter18 概率潜在语义分析 26 | * Chapter19 马尔可夫链蒙特卡罗法 27 | * Chapter20 潜在狄利克雷分配 28 | * Chapter21 PageRank算法 29 | * Chapter22 无监督学习方法总结 30 | 31 | 32 | 33 | ## 参考资料 34 | 35 | * 统计学习方法 by李航 36 | * 数学之美 by吴军 37 | * 机器学习 by周志华 38 | * [《统计学习方法》的代码实现](https://github.com/fengdu78/lihang-code) 39 | 40 | 41 | ![github](https://raw.githubusercontent.com/chenjiandongx/mzitu/master/images/forkstar.png "github") 42 | 43 | 44 | 45 | 46 | 欢迎关注我的微信公众号,记录学习,记录生活~ 47 | 48 | 49 | ![github](https://github.com/librauee/Reptile/blob/master/image/vx_code.jpg) 50 | 51 | 52 | [Click_into_My_CSDN](http://blog.csdn.net/lyc44813418) 53 | -------------------------------------------------------------------------------- /markdown语法.md: -------------------------------------------------------------------------------- 1 | @[TOC](这里写自定义目录标题) 2 | 3 | # 欢迎使用Markdown编辑器 4 | 5 | 你好! 这是你第一次使用 **Markdown编辑器** 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。 6 | 7 | ## 新的改变 8 | 9 | 我们对Markdown编辑器进行了一些功能拓展与语法支持,除了标准的Markdown编辑器功能,我们增加了如下几点新功能,帮助你用它写博客: 10 | 11 | 1. **全新的界面设计** ,将会带来全新的写作体验; 12 | 2. 在创作中心设置你喜爱的代码高亮样式,Markdown **将代码片显示选择的高亮样式** 进行展示; 13 | 3. 增加了 **图片拖拽** 功能,你可以将本地的图片直接拖拽到编辑区域直接展示; 14 | 4. 全新的 **KaTeX数学公式** 语法; 15 | 5. 增加了支持**甘特图的mermaid语法[^1]** 功能; 16 | 6. 增加了 **多屏幕编辑** Markdown文章功能; 17 | 7. 增加了 **焦点写作模式、预览模式、简洁写作模式、左右区域同步滚轮设置** 等功能,功能按钮位于编辑区域与预览区域中间; 18 | 8. 增加了 **检查列表** 功能。 19 | [^1]: [mermaid语法说明](https://mermaidjs.github.io/) 20 | 21 | ## 功能快捷键 22 | 23 | 撤销:Ctrl/Command + Z 24 | 重做:Ctrl/Command + Y 25 | 加粗:Ctrl/Command + B 26 | 斜体:Ctrl/Command + I 27 | 标题:Ctrl/Command + Shift + H 28 | 无序列表:Ctrl/Command + Shift + U 29 | 有序列表:Ctrl/Command + Shift + O 30 | 检查列表:Ctrl/Command + Shift + C 31 | 插入代码:Ctrl/Command + Shift + K 32 | 插入链接:Ctrl/Command + Shift + L 33 | 插入图片:Ctrl/Command + Shift + G 34 | 35 | 36 | ## 合理的创建标题,有助于目录的生成 37 | 38 | 直接输入1次#,并按下space后,将生成1级标题。 39 | 输入2次#,并按下space后,将生成2级标题。 40 | 以此类推,我们支持6级标题。有助于使用`TOC`语法后生成一个完美的目录。 41 | 42 | 43 | 44 | ## 如何改变文本的样式 45 | 46 | *强调文本* _强调文本_ 47 | 48 | **加粗文本** __加粗文本__ 49 | 50 | ==标记文本== 51 | 52 | ~~删除文本~~ 53 | 54 | > 引用文本 55 | 56 | H~2~O is是液体。 57 | 58 | 2^10^ 运算结果是 1024. 59 | 60 | 61 | 62 | ## 插入链接与图片 63 | 64 | 链接: [link](https://mp.csdn.net). 65 | 66 | 图片: ![Alt](https://avatar.csdn.net/7/7/B/1_ralf_hx163com.jpg) 67 | 68 | 带尺寸的图片: ![Alt](https://avatar.csdn.net/7/7/B/1_ralf_hx163com.jpg =30x30) 69 | 70 | 居中的图片: ![Alt](https://avatar.csdn.net/7/7/B/1_ralf_hx163com.jpg#pic_center) 71 | 72 | 居中并且带尺寸的图片: ![Alt](https://avatar.csdn.net/7/7/B/1_ralf_hx163com.jpg#pic_center =30x30) 73 | 74 | 当然,我们为了让用户更加便捷,我们增加了图片拖拽功能。 75 | 76 | 77 | ## 如何插入一段漂亮的代码片 78 | 79 | 去[博客设置](https://mp.csdn.net/configure)页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 `代码片`. 80 | ```javascript 81 | // An highlighted block 82 | var foo = 'bar'; 83 | ``` 84 | 85 | 86 | ## 生成一个适合你的列表 87 | 88 | - 项目 89 | - 项目 90 | - 项目 91 | 92 | 1. 项目1 93 | 2. 项目2 94 | 3. 项目3 95 | 96 | - [ ] 计划任务 97 | - [x] 完成任务 98 | 99 | 100 | ## 创建一个表格 101 | 一个简单的表格是这么创建的: 102 | 项目 | Value 103 | -------- | ----- 104 | 电脑 | $1600 105 | 手机 | $12 106 | 导管 | $1 107 | 108 | ### 设定内容居中、居左、居右 109 | 使用`:---------:`居中 110 | 使用`:----------`居左 111 | 使用`----------:`居右 112 | | 第一列 | 第二列 | 第三列 | 113 | |:-----------:| -------------:|:-------------| 114 | | 第一列文本居中 | 第二列文本居右 | 第三列文本居左 | 115 | 116 | 117 | ### SmartyPants 118 | SmartyPants将ASCII标点字符转换为“智能”印刷标点HTML实体。例如: 119 | | TYPE |ASCII |HTML 120 | |----------------|-------------------------------|-----------------------------| 121 | |Single backticks|`'Isn't this fun?'` |'Isn't this fun?' | 122 | |Quotes |`"Isn't this fun?"` |"Isn't this fun?" | 123 | |Dashes |`-- is en-dash, --- is em-dash`|-- is en-dash, --- is em-dash| 124 | 125 | 126 | ## 创建一个自定义列表 127 | Markdown 128 | : Text-to-HTML conversion tool 129 | 130 | Authors 131 | : John 132 | : Luke 133 | 134 | 135 | ## 如何创建一个注脚 136 | 137 | 一个具有注脚的文本。[^2] 138 | 139 | [^2]: 注脚的解释 140 | 141 | 142 | ## 注释也是必不可少的 143 | 144 | Markdown将文本转换为 HTML。 145 | 146 | *[HTML]: 超文本标记语言 147 | 148 | 149 | ## KaTeX数学公式 150 | 151 | 您可以使用渲染LaTeX数学表达式 [KaTeX](https://khan.github.io/KaTeX/): 152 | 153 | Gamma公式展示 $\Gamma(n) = (n-1)!\quad\forall 154 | n\in\mathbb N$ 是通过欧拉积分 155 | 156 | $$ 157 | \Gamma(z) = \int_0^\infty t^{z-1}e^{-t}dt\,. 158 | $$ 159 | 160 | > 你可以找到更多关于的信息 **LaTeX** 数学表达式[here][1]. 161 | 162 | 163 | ## 新的甘特图功能,丰富你的文章 164 | 165 | ```mermaid 166 | gantt 167 | dateFormat YYYY-MM-DD 168 | title Adding GANTT diagram functionality to mermaid 169 | section 现有任务 170 | 已完成 :done, des1, 2014-01-06,2014-01-08 171 | 进行中 :active, des2, 2014-01-09, 3d 172 | 计划一 : des3, after des2, 5d 173 | 计划二 : des4, after des3, 5d 174 | ``` 175 | - 关于 **甘特图** 语法,参考 [这儿][2], 176 | 177 | ## UML 图表 178 | 179 | 可以使用UML图表进行渲染。 [Mermaid](https://mermaidjs.github.io/). 例如下面产生的一个序列图:: 180 | 181 | ```mermaid 182 | sequenceDiagram 183 | 张三 ->> 李四: 你好!李四, 最近怎么样? 184 | 李四-->>王五: 你最近怎么样,王五? 185 | 李四--x 张三: 我很好,谢谢! 186 | 李四-x 王五: 我很好,谢谢! 187 | Note right of 王五: 李四想了很长时间, 文字太长了
不适合放在一行. 188 | 189 | 李四-->>张三: 打量着王五... 190 | 张三->>王五: 很好... 王五, 你怎么样? 191 | ``` 192 | 193 | 这将产生一个流程图。: 194 | 195 | ```mermaid 196 | graph LR 197 | A[长方形] -- 链接 --> B((圆)) 198 | A --> C(圆角长方形) 199 | B --> D{菱形} 200 | C --> D 201 | ``` 202 | 203 | - 关于 **Mermaid** 语法,参考 [这儿][3], 204 | 205 | ## FLowchart流程图 206 | 207 | 我们依旧会支持flowchart的流程图: 208 | ```mermaid 209 | flowchat 210 | st=>start: 开始 211 | e=>end: 结束 212 | op=>operation: 我的操作 213 | cond=>condition: 确认? 214 | 215 | st->op->cond 216 | cond(yes)->e 217 | cond(no)->op 218 | ``` 219 | 220 | - 关于 **Flowchart流程图** 语法,参考 [这儿][4]. 221 | 222 | 223 | ## 导出与导入 224 | 225 | ### 导出 226 | 如果你想尝试使用此编辑器, 你可以在此篇文章任意编辑。当你完成了一篇文章的写作, 在上方工具栏找到 **文章导出** ,生成一个.md文件或者.html文件进行本地保存。 227 | 228 | ### 导入 229 | 如果你想加载一篇你写过的.md文件或者.html文件,在上方工具栏可以选择导入功能进行对应扩展名的文件导入, 230 | 继续你的创作。 231 | 232 | [1]: http://meta.math.stackexchange.com/questions/5020/mathjax-basic-tutorial-and-quick-reference 233 | [2]: https://mermaidjs.github.io/ 234 | [3]: https://mermaidjs.github.io/ 235 | [4]: http://adrai.github.io/flowchart.js/ 236 | --------------------------------------------------------------------------------