Error message here!

Hide Error message here!

忘记密码?

Error message here!

请输入正确邮箱

Hide Error message here!

密码丢失?请输入您的电子邮件地址。您将收到一个重设密码链接。

Error message here!

返回登录

Close

Python机器学习笔记 Logistic回归

战争热诚 2019-01-19 14:24:00 阅读数:290 评论数:0 点赞数:0 收藏数:0

Logistic回归公式推导和代码实现

1,引言

logistic回归是机器学习中最常用最经典的分类方法之一,有人称之为逻辑回归或者逻辑斯蒂回归。虽然他称为回归模型,但是却处理的是分类问题,这主要是因为它的本质是一个线性模型加上一个映射函数Sigmoid,将线性模型得到的连续结果映射到离散型上。它常用于二分类问题,在多分类问题的推广叫softmax。

本文首先阐述Logistic回归的定义,然后介绍一些最优化算法,其中包括基本的梯度上升法和一个改进的随机梯度上升法,这些最优化算法将用于分类器的训练,最好本文将给出一个Logistic回归的实例,预测一匹病马是否能被治愈。

在我们的日常生活中遇到过很多最优化问题,比如如何在最短时间内从A点到达B点?如何投入最少工作量却获得最大的效益?如何设计发动机使得油耗最少而功率最大?可见,最优化的作用十分强大,所以此处我们介绍几个最优化算法,并利用它们训练出一个非线性函数用于分类。

现在假设有一些数据点,我们用一条直线对这些点进行拟合(该线称为最佳拟合直线),这个拟合过程就称作回归。利用logistic回归进行分类的主要思想是:根据现有数据对分类边界线建立回归公式,以此进行分类,这里的“回归”一词源于最佳拟合,表示要找到最佳拟合参数集。训练分类器时的做法就是寻找最佳拟合参数,使用的是最优化算法,下面我们首先介绍一下这个二值型输出分类器的数学原理。

2,Logistic回归的一般过程

(1)收集数据:采用任意方法收集数据

(2)准备数据:由于需要进行距离计算,因此要求数据类型为数值型。另外,结构化数据格式则最佳

(3)分析数据:采用任意方法对数据进行分析

(4)训练算法:大部分时间将用于训练,训练的目的是为了找到最佳的分类回归系数

(5)使用算法:首先,我们需要输入一些数据,并将其转换成对应的结构化数值;接着,基于训练好的回归系数就可以对这些数值进行简单的回归计算,判定他们属于哪个类别;在这之后,我们就可以在输出的类别上做一些其他分析工作。

3,Logistic回归的优缺点

优点:计算代码不高,易于理解和实现,计算代价不高,速度快,存储资源低

缺点:容易欠拟合,分类精度可能不高

适用数据类型:数值型和标称型数据

4,基于Logistic回归和Sigmoid函数的分类

  我们想要的函数应该是,能接受所有的输入,然后预测出类型。例如,在两个类的情况下,上述函数输出0或1。该函数称为海维赛德阶跃函数(Heaviside step function),或者直接称为单位阶跃函数。然而,海维赛德阶跃函数的问题在于:该函数在跳跃点上从0瞬间跳跃到1,这个瞬间跳跃过程有时很难处理。幸好,另一个函数也有类似的性质(可以输出0或者1),且数学上更易处理,这就是Sigmoid函数。Sigmoid函数具体的计算公式如下:

图5-1给出了Sigmoid函数在不同坐标尺度下的两条曲线图。当x为0时,Sigmoid函数值为0.5。随着x的增大,对应的Sigmoid值将逼近于1;而随着x的减少,Sigmoid值将逼近于0.如果横坐标刻度足够大,Sigmoid函数看起来很像一个阶跃函数。

因此,为了实现Logistic回归分类器,我们可以在每个特征上都乘以一个回归系数,然后把所有的结果值相加,将这个总和带入Sigmoid函数中,进而得到一个范围在0~1之间的数值。任何大于0.5的数据被分入1类,小于0.5即被归入0类,所以,Logistic回归也可以被看成是一种概率估计。

确定了分类器的函数形式之后,现在的问题变成了:最佳回归系数是多少?如何确定其大小。

5,基于最优化方法的最佳回归系数确定

Sigmoid函数的输入记为z,由下面公式得到:

如果采用向量的写法,上述公式可以写成  z = wTx  ,它表示将这两个数值向量对应元素相乘,然后全部加起来即得到z值。

 

其中的向量x是分类器的输入数据,向量w也就是我们要找到的最佳参数(系数),从而使得分类器尽可能的准确,为了寻找该最佳参数,需要用到最优化理论的一些知识。

然后再看看我们的Logistic回归模型的公式:

 

这里假设 W>0,Y与X各维度叠加的图形关系,如下图所示(x为了方便取1维):

 

 

下面首先学习梯度上升的最优化方法,我们将学习到如何使用该方法求得数据集的最佳参数,接下来,展示如何绘制梯度上升法产生的决策边界图,该图将梯度上升法的分类效果可视化的呈现出来,最后我们将学习随机梯度上升算法,以及如何对其进行修改以获得很好地结果。可能我们最常听到的是梯度下降算法,它与这里的梯度上升算法是一样的,只是公式中的 加法需要变成减法,梯度上升算法用来求函数的最大值,而梯度下降算法是用来求函数的最小值

6,梯度上升法 

梯度上升法基于的思想是:要找到某函数的最大值,最好的方法是沿着该函数的梯度方向探寻,如果梯度记为,则函数 f(x,y) 的梯度由下面式子表示:

这个梯度意味着要沿着x的方向移动,沿着y方向移动,其中函数f(x,y)必须要在待计算的点上有定义并且可微,一个具体的函数例子见图5-2:

  上图中的梯度上升算法沿梯度方向移动了一步,可以看出,梯度算子总是指向函数值增长最快的方向。这里所说的移动方向,而未提到移动量的大小。该量值称为步长,记为。用向量来表示的话,梯度算法的迭代公式如下:

该公式将一直被迭代执行,直至达到某个停止条件为止,比如迭代次数达到某个指定值或算法达到某个可以允许的误差范围。

基于上面的内容,我们来看一个Logistic回归分类器的应用例子,从图5-3可以看到我们采用的数据集。

梯度上升法的公式推导

由于Sigmoid函数的特性,我们可以做如下的假设:

上式即为在已知样本X和参数θ的情况下。样本X属性正类(y=1)和负类(y=0)的条件概率,将两个公式合并成一个,如下:

假定样本与样本之间相互独立,那么整个样本集生成的概率即为所有样本生成概率的乘积:

为了简化问题,我们对整个表达式求对数:

满足似然函数(θ)的最大的θ值即时我们需要求解的模型。

那么梯度上升法就像爬坡一样,一点一点逼近极值,而上升这个动作用数学公式表达即为:

其中,α 为步长。

回到Logistic回归问题,我们同样对函数求偏导。

对这个公式进行分解,先看:

我们可以看到,对函数求偏导,分解为三部分,然后我们对这三部分分布求导。

其中:

再由:

可得:

接下来:

最后:

综合三部分即得到:

因此梯度迭代公式为:

 

  

7,训练算法:使用梯度上升找到最佳参数

  上图有100个样本点,每个点包含两个数值型特征:X1和X2,在此数据集上,我们将通过使用梯度上升法找到最佳回归系数,也就是拟合出Logistic回归模型的最佳参数。

梯度上升法的伪代码如下:每个回归系数初始化为1 重复R次: 计算整个数据集的梯度 使用alpha /* gradient 更新回归系数的向量 返回回归系数

testSet.txt的文件内容如下:

-0.017612 14.053064 0 -1.395634 4.662541 1 -0.752157 6.538620 0 -1.322371 7.152853 0 0.423363 11.054677 0 0.406704 7.067335 1 0.667394 12.741452 0 -2.460150 6.866805 1 0.569411 9.548755 0 -0.026632 10.427743 0 0.850433 6.920334 1 1.347183 13.175500 0 1.176813 3.167020 1 -1.781871 9.097953 0 -0.566606 5.749003 1 0.931635 1.589505 1 -0.024205 6.151823 1 -0.036453 2.690988 1 -0.196949 0.444165 1 1.014459 5.754399 1 1.985298 3.230619 1 -1.693453 -0.557540 1 -0.576525 11.778922 0 -0.346811 -1.678730 1 -2.124484 2.672471 1 1.217916 9.597015 0 -0.733928 9.098687 0 -3.642001 -1.618087 1 0.315985 3.523953 1 1.416614 9.619232 0 -0.386323 3.989286 1 0.556921 8.294984 1 1.224863 11.587360 0 -1.347803 -2.406051 1 1.196604 4.951851 1 0.275221 9.543647 0 0.470575 9.332488 0 -1.889567 9.542662 0 -1.527893 12.150579 0 -1.185247 11.309318 0 -0.445678 3.297303 1 1.042222 6.105155 1 -0.618787 10.320986 0 1.152083 0.548467 1 0.828534 2.676045 1 -1.237728 10.549033 0 -0.683565 -2.166125 1 0.229456 5.921938 1 -0.959885 11.555336 0 0.492911 10.993324 0 0.184992 8.721488 0 -0.355715 10.325976 0 -0.397822 8.058397 0 0.824839 13.730343 0 1.507278 5.027866 1 0.099671 6.835839 1 -0.344008 10.717485 0 1.785928 7.718645 1 -0.918801 11.560217 0 -0.364009 4.747300 1 -0.841722 4.119083 1 0.490426 1.960539 1 -0.007194 9.075792 0 0.356107 12.447863 0 0.342578 12.281162 0 -0.810823 -1.466018 1 2.530777 6.476801 1 1.296683 11.607559 0 0.475487 12.040035 0 -0.783277 11.009725 0 0.074798 11.023650 0 -1.337472 0.468339 1 -0.102781 13.763651 0 -0.147324 2.874846 1 0.518389 9.887035 0 1.015399 7.571882 0 -1.658086 -0.027255 1 1.319944 2.171228 1 2.056216 5.019981 1 -0.851633 4.375691 1 -1.510047 6.061992 0 -1.076637 -3.181888 1 1.821096 10.283990 0 3.010150 8.401766 1 -1.099458 1.688274 1 -0.834872 -1.733869 1 -0.846637 3.849075 1 1.400102 12.628781 0 1.752842 5.468166 1 0.078557 0.059736 1 0.089392 -0.715300 1 1.825662 12.693808 0 0.197445 9.744638 0 0.126117 0.922311 1 -0.679797 1.220530 1 0.677983 2.556666 1 0.761349 10.693862 0 -2.168791 0.143632 1 1.388610 9.341997 0 0.317029 14.739025 0

下面具体实现梯度上升算法的代码:/#/*coding:utf-8/* from numpy import / /# 读取数据 def loadDataSet(filename): ''' 对于testSet.txt,每行前两个值分别是X1和X2,第三个值数据对应的类别标签 而且为了设置方便,该函数还将X0的值设置为1.0 :return: ''' dataMat = [] labelMat = [] fr = open(filename) for line in fr.readlines(): lineArr = line.strip().split() dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])]) labelMat.append(int(lineArr[2])) return dataMat,labelMat def sigmoid(inX): return 1.0/(1+exp(-inX)) def gradAscent(dataMatIn,classLabels): ''' :param dataMatIn: 是一个2维Numpy数组,每列分别代表每个不同的特征 每行则代表每个训练样本。 :param classLabels: 是类别标签,是一个1/100的行向量,为了便于矩阵运算,需要将行向量 转换为列向量,就是矩阵的转置,再将其赋值与labelMat。 :return: ''' dataMatrix = mat(dataMatIn) labelMat = mat(classLabels).transpose() /# labelMat = mat(classLabels).T m,n = shape(dataMatrix) /# alpha是向目标移动的步长 alpha = 0.001 /# 迭代次数 maxCycles = 500 weights = ones((n,1)) for k in range(maxCycles): h = sigmoid(dataMatrix/weights) error = (labelMat-h) weights = weights + alpha/dataMatrix.transpose()/*error return weights

测试结果如下:

if name == 'main': filename = 'testSet.txt' dataArr,labelMat = loadDataSet(filename) weightsres = gradAscent(dataArr,labelMat) print(weightsres) ''' [[ 4.12414349] [ 0.48007329] [-0.6168482 ]] '''

上面已经解出了一组回归系数,它确定了不同类别数据之间的分割线,那么怎样画出该分割线,从而使得优化的过程便于理解呢?下面代码来解决这个问题。

画出数据集和Logistic回归最佳拟合直线的函数代码:def plotBestFit(wei): import matplotlib.pyplot as plt weights = wei.getA() dataMat,labelMat = loadDataSet(filename) dataArr = array(dataMat) n = shape(dataArr)[0] xcord1 = [] ycord1 = [] xcord2 = [] ycord2 = [] for i in range(n): if int(labelMat[i]) ==1: xcord1.append(dataArr[i,1]) ycord1.append(dataArr[i,2]) else: xcord2.append(dataArr[i, 1]) ycord2.append(dataArr[i, 2]) fig = plt.figure() ax = fig.add_subplot(111) ax.scatter(xcord1,ycord1,s=30,c='red',marker='s') ax.scatter(xcord2,ycord2,s=30,c='green') x = arange(-3.0,3.0,0.1) y = (-weights[0]-weights[1] /* x) / weights[2] ax.plot(x,y) plt.xlabel('X1') plt.ylabel('X2') plt.show()

输出的结果和代码如下图所示:if name == 'main': filename = 'testSet.txt' dataArr,labelMat = loadDataSet(filename) weightsres = gradAscent(dataArr,labelMat) print(weightsres) plotBestFit(weights_res)

 

梯度上升算法在500次迭代后得到的Logistic回归最佳拟合直线

这个分类结果相当不错,从图上看,只错分了四个点。但是,尽管例子简单且数据集很小,这个方法却需要大量的计算(300次乘法),因此下一节将对算法稍作改进,从而使它可以用在真实数据集上。

8,训练算法:随机梯度上升

  梯度上升算法在每次更新回归系数时都需遍历整个数据集,该方法在处理100个左右的数据集尚可,但是若有数十亿样本和成千上万的特征,那么该方法的计算复杂度就太高了。一种改进方法是一次仅用一个样本点来更新回归系数,该方法称为随机梯度上升算法。由于可以在新样本到来时对分类器进行增量式更新,因而随机梯度上升算法是一个在线学习算法,与“在线学习”相对应,一次处理所有数据被称作是“批处理”。

随机梯度上升算法可以写成如下的伪代码:所有回归系数初始化为1 对数据集中每个样本 计算该样本的梯度 使用alpha/*gradient 更新回归系数值 返回回归系数值

以下是随机梯度上升算法的实现代码:

/# 随机梯度上升算法 def stocGradAscent0(dataMatrix,classLabels): m,n = shape(dataMatrix) alpha = 0.01 weights = ones(n) for i in range(m): h = sigmoid(sum(dataMatrix[i]/*weights)) error = classLabels[i] - h weights = weights + alpha/*error/*dataMatrix[i] return weights

实现的代码如下:

if name == 'main': filename = 'testSet.txt' dataArr,labelMat = loadDataSet(filename) weightsres = stocGradAscent0(array(dataArr),labelMat) print(weightsres) plotBestFit(weights_res)

图5-5  随机梯度上升算法在上述数据集上的执行结果,最佳拟合直线并非最佳分类线

可以看出,拟合出来的直线效果还不错,但并不像,但是不像上面那个完美,这里的分类器错分了三分之一的样本。

直接比较结果两个结果是不公平的,后者的结果是在整个数据集上迭代了500次才得到的。一个判断优化算法优劣的可靠方法是看它是否收敛,也就是说参数是否达到了稳定值,是否还会不断地变化?对此,我们在上面的的随机梯度算法上做了些修改,使其在整个数据集上运行200次,最终绘制的三个回归系数的变化情况如下图所示:

上图展示了随机梯度上升算法在200次迭代过程中回归系数的变化情况,其中的系数2,也就是图5-5中的X2只经过了50次迭代就达到了稳定值,但系数1和0则需要更多次的迭代。另外值得注意的是,在大的波动停止后,还有一些小的周期性波动。不难理解,产生这种现象的原因是存在一些不能正确分类的样本点(数据集并非现象可分),在每次迭代时会引发系数的剧烈改变。我们期望算法能避免来回波动,从而收敛到某个值。另外,收敛速度也需要加快。

改进的随机梯度上升算法代码如下:/# 改进的随机梯度上升算法 def stocGradAscent1(dataMatrix,classLabels,numIter=150): m,n = shape(dataMatrix) weights = ones(n) for j in range(numIter): dataIndex = list(range(m)) for i in range(m): alpha = 4/(1.0+j+i)+0.01 randIndex = int(random.uniform(0,len(dataIndex))) h = sigmoid(sum(dataMatrix[randIndex]/*weights)) error = classLabels[randIndex] - h weights = weights + alpha /*error/*dataMatrix[randIndex] del(dataIndex[randIndex]) return weights

上述代码大体上与之前的随机梯度上升算法一致,修改了两处,一处是alpha在每次迭代的时候都会调整,这会环节之前的数据波动或者高频波动。另外,虽然alpha会随着迭代次数不断减少,但永远不会减少到0,。必须这样做的原因是为了保证在多次迭代之后新数据仍然具有一定的影响。如果要处理的问题是动态变化的,那么可以适当增加常数项,来确保新的值获得更大的回归系数。另外一点值得注意的是,在降低alpha的函数中,alpha每次减少1/(j+1),其中j是迭代次数,i是样本点的下标,这样当j

与stocGradAscent1()类似,下图显示了每次迭代时各个回归系数的变化情况。

比较5-7和5-6可以看到两点不同,第一点是,图5-7中的系数没有像5-6里那样出现周期性的波动,这归功于stocGradAscent1()里的样本随机选择机制,第二点是5-7的水平轴比5-6的短了很多,这是由于stocGradAscent1()可以收敛的更快,这次我们仅仅对数据集做了20次遍历,之前是500次。

下面看看在同一个数据集上的分类效果,将程序运行可以看到:if name == 'main': filename = 'testSet.txt' dataArr,labelMat = loadDataSet(filename) weightsres = stocGradAscent1(array(dataArr),labelMat) print(weightsres) plotBestFit(weights_res)

该分割线达到了与GradientAscent()差不多的效果,但是所使用的计算量更少。

默认的迭代次数是150次,但是我们通过stocGradAscent()的第三个参数来对此进行修改,例如:weights_res = stocGradAscent1(array(dataArr),labelMat,500)

 

迄今为止我们分析了回归系数的变化情况,但是还没有达到目的,,即完成具体的分类任务,下面我们将使用随机梯度上升算法来解决病马的生死预测问题。,

9,示例:从疝气病症预测病马的死亡率

本次将使用logistic回归来预测患有疝气的马的存活问题,这里的数据包含了368个样本和28个特征。(疝气指的是马胃肠痛的术语,然而这种病不一定源于马 的肠胃问题,其他问题也可以引发疝气)该数据集包含了医院检测马疝气病的一些指标,有的指标比较主观,有的指标难以预测,例如马的疼痛级别

使用Logistic回归估计马疝气病的死亡率的流程

(1)收集数据:使用给定数据文件

(2)准备数据:用Python解析文本文件并填充缺失值

(3)分析数据:可视化并观察数据

(4)训练算法:使用优化算法,找到最佳的系数

(5)测试算法:为了量化回归的结果,需要观察错误率,根据错误率决定是否回退到训练阶段,通过改变迭代的次数和步长等参数来得到更好的回归系数

(6)使用算法:实现一个简单的命令行程序来收集马的症状并输出预测结果

 

 

准备数据:处理数据中的缺失值

数据中的缺失值是个非常棘手的问题,有很少文献都致力于解决这个问题。那么,数据缺少究竟带来了什么问题?假设有100个样本和20个特征,这些数据都是机器收集回来的,若机器上的某个传感器损坏导致一个特征无效时该怎么办?此时是否要扔掉整个数据?这种情况下,另外19个特征怎么办?它们是否还可用?答案是肯定的。因为有时候数据相当昂贵,扔掉和重新获取都是不可取的,所以必须采取一些方法来解决这个问题。

下面给出了一些可选的做法:

  • 使用可用特征的均值来填补缺失值;
  • 使用特征值来填充缺失值,如-1
  • 忽略有缺失值的样本
  • 使用相似样本的均值填补缺失值
  • 使用另外的机器学习算法预测缺失值

  现在,我们对下一节要用的数据集进行预处理,使其可以顺利地使用分类算法。在预处理阶段需要做两件事:第一,所有的缺失值必须用一个实数值来替换,因为我们使用的Numpy数据类型不允许包含缺失值。这里选择实数0来替换,因为我们使用的Numpy数据类型不允许包括缺失值,这里选择实数0来替换所有缺失值,恰好能适应于Logistic回归。这样做的直觉在于,我们需要的是一个在更新时不会影响系数的值,回归系数的更新公式如下:weights = weights + alpha /error/dataMatrix[randIndex]

如果dataMatirx的某特征对应值为0,那么该特征的系数将不做更新,即:

weights = weights

另外,由于sigmoid(0) = 0.5 ,即对它结果的预测不具有任何倾向性,因此上述做法也不会对误差项造成任何影响,基于上述原因,将缺失值用0代替既可以保留现有数据,也不需要对优化算法进行修改,此外,数据集中的特征值一般不取0,因此在某种意义上说它也满足“特殊值”这个要求。

预处理中做的第二件事,是如果在测试数据集中发现了一条数据的类别标签以及缺失,那么我们的简单做法是将该条数据丢弃。这是因为类别标签与特征不同,很难确定采用某个合适的值来替换,采用Logistic回归进行预处理之后保存两个文件,horseColicTest.txt和horseColicTraining.txt。如果想对于原始数据和预处理之后的数据做个比较。

我们有一个“干净”可用的数据集和一个不错的优化算法,下面将这些部分融合在一起训练出一个分类器,然后利用该分类器来预测病马的生死问题。

horseColicTest.txt的数据:2 1 38.50 54 20 0 1 2 2 3 4 1 2 2 5.90 0 2 42.00 6.30 0 0 1 2 1 37.60 48 36 0 0 1 1 0 3 0 0 0 0 0 0 44.00 6.30 1 5.00 1 1 1 37.7 44 28 0 4 3 2 5 4 4 1 1 0 3 5 45 70 3 2 1 1 1 37 56 24 3 1 4 2 4 4 3 1 1 0 0 0 35 61 3 2 0 2 1 38.00 42 12 3 0 3 1 1 0 1 0 0 0 0 2 37.00 5.80 0 0 1 1 1 0 60 40 3 0 1 1 0 4 0 3 2 0 0 5 42 72 0 0 1 2 1 38.40 80 60 3 2 2 1 3 2 1 2 2 0 1 1 54.00 6.90 0 0 1 2 1 37.80 48 12 2 1 2 1 3 0 1 2 0 0 2 0 48.00 7.30 1 0 1 2 1 37.90 45 36 3 3 3 2 2 3 1 2 1 0 3 0 33.00 5.70 3 0 1 2 1 39.00 84 12 3 1 5 1 2 4 2 1 2 7.00 0 4 62.00 5.90 2 2.20 0 2 1 38.20 60 24 3 1 3 2 3 3 2 3 3 0 4 4 53.00 7.50 2 1.40 1 1 1 0 140 0 0 0 4 2 5 4 4 1 1 0 0 5 30 69 0 0 0 1 1 37.90 120 60 3 3 3 1 5 4 4 2 2 7.50 4 5 52.00 6.60 3 1.80 0 2 1 38.00 72 36 1 1 3 1 3 0 2 2 1 0 3 5 38.00 6.80 2 2.00 1 2 9 38.00 92 28 1 1 2 1 1 3 2 3 0 7.20 0 0 37.00 6.10 1 1.10 1 1 1 38.30 66 30 2 3 1 1 2 4 3 3 2 8.50 4 5 37.00 6.00 0 0 1 2 1 37.50 48 24 3 1 1 1 2 1 0 1 1 0 3 2 43.00 6.00 1 2.80 1 1 1 37.50 88 20 2 3 3 1 4 3 3 0 0 0 0 0 35.00 6.40 1 0 0 2 9 0 150 60 4 4 4 2 5 4 4 0 0 0 0 0 0 0 0 0 0 1 1 39.7 100 30 0 0 6 2 4 4 3 1 0 0 4 5 65 75 0 0 0 1 1 38.30 80 0 3 3 4 2 5 4 3 2 1 0 4 4 45.00 7.50 2 4.60 1 2 1 37.50 40 32 3 1 3 1 3 2 3 2 1 0 0 5 32.00 6.40 1 1.10 1 1 1 38.40 84 30 3 1 5 2 4 3 3 2 3 6.50 4 4 47.00 7.50 3 0 0 1 1 38.10 84 44 4 0 4 2 5 3 1 1 3 5.00 0 4 60.00 6.80 0 5.70 0 2 1 38.70 52 0 1 1 1 1 1 3 1 0 0 0 1 3 4.00 74.00 0 0 1 2 1 38.10 44 40 2 1 3 1 3 3 1 0 0 0 1 3 35.00 6.80 0 0 1 2 1 38.4 52 20 2 1 3 1 1 3 2 2 1 0 3 5 41 63 1 1 1 1 1 38.20 60 0 1 0 3 1 2 1 1 1 1 0 4 4 43.00 6.20 2 3.90 1 2 1 37.70 40 18 1 1 1 0 3 2 1 1 1 0 3 3 36.00 3.50 0 0 1 1 1 39.1 60 10 0 1 1 0 2 3 0 0 0 0 4 4 0 0 0 0 1 2 1 37.80 48 16 1 1 1 1 0 1 1 2 1 0 4 3 43.00 7.50 0 0 1 1 1 39.00 120 0 4 3 5 2 2 4 3 2 3 8.00 0 0 65.00 8.20 3 4.60 1 1 1 38.20 76 0 2 3 2 1 5 3 3 1 2 6.00 1 5 35.00 6.50 2 0.90 1 2 1 38.30 88 0 0 0 6 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 38.00 80 30 3 3 3 1 0 0 0 0 0 6.00 0 0 48.00 8.30 0 4.30 1 1 1 0 0 0 3 1 1 1 2 3 3 1 3 6.00 4 4 0 0 2 0 0 1 1 37.60 40 0 1 1 1 1 1 1 1 0 0 0 1 1 0 0 2 2.10 1 2 1 37.50 44 0 1 1 1 1 3 3 2 0 0 0 0 0 45.00 5.80 2 1.40 1 2 1 38.2 42 16 1 1 3 1 1 3 1 0 0 0 1 0 35 60 1 1 1 2 1 38 56 44 3 3 3 0 0 1 1 2 1 0 4 0 47 70 2 1 1 2 1 38.30 45 20 3 3 2 2 2 4 1 2 0 0 4 0 0 0 0 0 1 1 1 0 48 96 1 1 3 1 0 4 1 2 1 0 1 4 42.00 8.00 1 0 1 1 1 37.70 55 28 2 1 2 1 2 3 3 0 3 5.00 4 5 0 0 0 0 1 2 1 36.00 100 20 4 3 6 2 2 4 3 1 1 0 4 5 74.00 5.70 2 2.50 0 1 1 37.10 60 20 2 0 4 1 3 0 3 0 2 5.00 3 4 64.00 8.50 2 0 1 2 1 37.10 114 40 3 0 3 2 2 2 1 0 0 0 0 3 32.00 0 3 6.50 1 1 1 38.1 72 30 3 3 3 1 4 4 3 2 1 0 3 5 37 56 3 1 1 1 1 37.00 44 12 3 1 1 2 1 1 1 0 0 0 4 2 40.00 6.70 3 8.00 1 1 1 38.6 48 20 3 1 1 1 4 3 1 0 0 0 3 0 37 75 0 0 1 1 1 0 82 72 3 1 4 1 2 3 3 0 3 0 4 4 53 65 3 2 0 1 9 38.20 78 60 4 4 6 0 3 3 3 0 0 0 1 0 59.00 5.80 3 3.10 0 2 1 37.8 60 16 1 1 3 1 2 3 2 1 2 0 3 0 41 73 0 0 0 1 1 38.7 34 30 2 0 3 1 2 3 0 0 0 0 0 0 33 69 0 2 0 1 1 0 36 12 1 1 1 1 1 2 1 1 1 0 1 5 44.00 0 0 0 1 2 1 38.30 44 60 0 0 1 1 0 0 0 0 0 0 0 0 6.40 36.00 0 0 1 2 1 37.40 54 18 3 0 1 1 3 4 3 2 2 0 4 5 30.00 7.10 2 0 1 1 1 0 0 0 4 3 0 2 2 4 1 0 0 0 0 0 54 76 3 2 1 1 1 36.6 48 16 3 1 3 1 4 1 1 1 1 0 0 0 27 56 0 0 0 1 1 38.5 90 0 1 1 3 1 3 3 3 2 3 2 4 5 47 79 0 0 1 1 1 0 75 12 1 1 4 1 5 3 3 0 3 5.80 0 0 58.00 8.50 1 0 1 2 1 38.20 42 0 3 1 1 1 1 1 2 2 1 0 3 2 35.00 5.90 2 0 1 1 9 38.20 78 60 4 4 6 0 3 3 3 0 0 0 1 0 59.00 5.80 3 3.10 0 2 1 38.60 60 30 1 1 3 1 4 2 2 1 1 0 0 0 40.00 6.00 1 0 1 2 1 37.80 42 40 1 1 1 1 1 3 1 0 0 0 3 3 36.00 6.20 0 0 1 1 1 38 60 12 1 1 2 1 2 1 1 1 1 0 1 4 44 65 3 2 0 2 1 38.00 42 12 3 0 3 1 1 1 1 0 0 0 0 1 37.00 5.80 0 0 1 2 1 37.60 88 36 3 1 1 1 3 3 2 1 3 1.50 0 0 44.00 6.00 0 0 0

horseColicTraining.txt的数据:2.000000 1.000000 38.500000 66.000000 28.000000 3.000000 3.000000 0.000000 2.000000 5.000000 4.000000 4.000000 0.000000 0.000000 0.000000 3.000000 5.000000 45.000000 8.400000 0.000000 0.000000 0.000000 1.000000 1.000000 39.200000 88.000000 20.000000 0.000000 0.000000 4.000000 1.000000 3.000000 4.000000 2.000000 0.000000 0.000000 0.000000 4.000000 2.000000 50.000000 85.000000 2.000000 2.000000 0.000000 2.000000 1.000000 38.300000 40.000000 24.000000 1.000000 1.000000 3.000000 1.000000 3.000000 3.000000 1.000000 0.000000 0.000000 0.000000 1.000000 1.000000 33.000000 6.700000 0.000000 0.000000 1.000000 1.000000 9.000000 39.100000 164.000000 84.000000 4.000000 1.000000 6.000000 2.000000 2.000000 4.000000 4.000000 1.000000 2.000000 5.000000 3.000000 0.000000 48.000000 7.200000 3.000000 5.300000 0.000000 2.000000 1.000000 37.300000 104.000000 35.000000 0.000000 0.000000 6.000000 2.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 0.000000 74.000000 7.400000 0.000000 0.000000 0.000000 2.000000 1.000000 0.000000 0.000000 0.000000 2.000000 1.000000 3.000000 1.000000 2.000000 3.000000 2.000000 2.000000 1.000000 0.000000 3.000000 3.000000 0.000000 0.000000 0.000000 0.000000 1.000000 1.000000 1.000000 37.900000 48.000000 16.000000 1.000000 1.000000 1.000000 1.000000 3.000000 3.000000 3.000000 1.000000 1.000000 0.000000 3.000000 5.000000 37.000000 7.000000 0.000000 0.000000 1.000000 1.000000 1.000000 0.000000 60.000000 0.000000 3.000000 0.000000 0.000000 1.000000 0.000000 4.000000 2.000000 2.000000 1.

版权声明
本文为[战争热诚]所创,转载请带上原文链接,感谢
https://www.cnblogs.com/wj-1314/p/10181876.html

编程之旅,人生之路,不止于编程,还有诗和远方。
阅代码原理,看框架知识,学企业实践;
赏诗词,读日记,踏人生之路,观世界之行;

支付宝红包,每日可领