甲乙小朋友的房子

甲乙小朋友很笨,但甲乙小朋友不会放弃

0%

这位前辈写的很好。今天也没有时间看视频。看看他的博客也就足够了。混合和装袋

bagging

bagging——基于数据随机重抽样的分类器构建方法。

boosting

新的分类器根据已训练出的分类器的性能来进行训练; 分类结果基于所有分类器的加权求和得到。

bagging和boosting区别

Bagging 是 Bootstrap Aggregating 的简称,意思就是再取样 (Bootstrap) 然后在每个样本上训练出来的模型取平均。各模型分布近似相同,但不独立。

  1. 从偏差角度看。由于$Bais = $ ,所以 Bagging后的偏差与单个模型相近。
  2. 从方差角度看。如果各模型独立,整体方差 =$ Var(E[X_i]) =​$ (这是方差的性质);如果各模型完全一样,则\(Var(E[X_i]) = Var(Xi)​\)。那么因此Bagging可以减少方差。

而随机森林通过随机选取特征子集做拟合的方式修正了各子树,因此随机森林中基学习器的多样性不仅来自于样本扰动,还来自于特征扰动。使得方差进一步降低,提高了泛化能力。

Boosting 则是迭代算法,每一次迭代都根据上一次迭代的预测结果对样本进行加权,所以随着迭代不断进行,误差会越来越小,所以模型的 bias 会不断降低。而这种sequential、adaptive的策略导致各子模型之前强相关,也就是以上分析中,如果各模型完全一样,那么方差就不会有很大的降低。这种算法无法并行,例子比如 Adaptive Boosting.

参考文献

  1. Bias/Variance Tradeoff

最近看各种机器学习算法,感觉没有实战,总是空空的。刚好这个月没什么事情,趁此机会拿赛题练习一下。 # 资料整理 1. 阿里天池O2O优惠券消费行为预测竞赛优胜方案。第一名。北大。解题思路。 2. O2O优惠券使用预测思路总结。16名。解题思路。 3. O2O优惠券使用预测复赛第三名思路。3名。PPT. 4. 各竞赛QQ群 5. 竞赛官网 6. 论坛专区 7. 天池新人实战赛[o2o优惠券使用预测] 8. 也可以去天池官网上,点学习入口,下面的视频,这边也有对这次020比赛的一些视频解说 9. 数加平台指南+文档、视频、FAQ及精华帖干货集锦 10. 数据科学完整学习路径

赛题背景

  • O2O(Online to Offline)消费
  • O2O:是指将线下的商务机会与互联网结合,让互联网成为线下交易的平台
  • 以优惠券盘活老用户或吸引新客户进店消费是O2O的一种重要营销方式

赛题目标

  • 个性化投放优惠券,提高核销率
  • 通过分析建模,精准预测用户是否会在规定时间内使用相应优惠券
  • 已知:用户在2016年1月1日至2016年6月30日之间真实线上线下消费行为
  • 预测:用户在2016年7月领取优惠券后15天以内的使用情况
  • 评价标准:优惠券核销预测的平均AUC(ROC曲线下面积)。即对每个优惠券coupon_id单独计算核销预测的AUC值,再对所有优惠券的AUC值求平均作为最终的评价标准。 关于AUC的含义与具体计算方法,可参考维基百科

数据描述及分析

数据描述

  • Table 1: 用户线下消费和优惠券领取行为,ccf_offline_stage1_train.csv
  • Table 2: 用户线上点击/消费和优惠券领取行为,ccf_online_stage1_train
  • Table 3:用户O2O线下优惠券使用预测样本,ccf_offline_stage1_test_revised.csv
  • Table 4:选手提交文件字段,其中user_id,coupon_id和date_received均来自Table 3,而Probability为预测值

** TABLE 1: 用户线下消费和优惠券领取行为 **

** Table 2: 用户线上点击/消费和优惠券领取行为**

** Table 3:用户O2O线下优惠券使用预测样本**

** Table 4选手提交文件字段** 其中user_id,coupon_id和date_received均来自Table 3,而Probability为预测值

数据分析

初步分析

** TABLE 1 分析 **

  • 特点: -- 标题:用户线下消费和优惠券领取行为 -- 场景:线下 -- 行为:消费、优惠券领取 -- 数据:优惠券领取、使用情况,消费情况,用户常活动地点与最近门店距离
  • 分析1:用户行为有三种情况 -- 领了优惠券 && 未消费 = 负样本 (Date=null & Coupon_id != null) -- 没领优惠券 && 已消费(Date!=null & Coupon_id = null) -- 领了优惠券 && 已消费(Date!=null & Coupon_id != null) -- 总结:本数据作为刻画用户特点的主要依据较为合理
  • 分析2:优惠率 -- 总结:有可能用户会根据优惠率来决定是否进行消费
  • 分析3:距离 -- 离用户近的门店可能会总领取优惠券,但不一定会使用。 -- 离用户远的门店如果有优惠券,则可能会为了很大的优惠率专程去使用。
  • 总结 -- 本数据集主要刻画线下用户特征。

** TABLE 2 分析 **

  • 特点: -- 标题:用户线上点击/消费和优惠券领取行为 -- 场景:线上 -- 行为:点击、消费、优惠券领取 -- 数据:用户是否点击。购买。领取优惠券。
  • 分析1:用户行为有三种情况 -- 领了优惠券 && 未消费 = 负样本(Date=null & Coupon_id != null) -- 没领优惠券 && 已消费 (Date!=null & Coupon_id = null) -- 领了优惠券 && 已消费 (Date!=null & Coupon_id != null)
  • 分析2:用户点击、消费、优惠券情况 -- 用户点击了 && 没领优惠券 && 未消费 = 负样本 -- 用户点击了 && 领了优惠券 && 未消费 -- 用户点击了 && 领了优惠券 && 已消费 -- 用户点击了 && 没领优惠券 && 已消费 -- 用户没点击
  • 总结 -- 本数据集主要刻画线上用户特征。

** Table 3:用户O2O线下优惠券使用预测样本 **

  • 测试集

认识数据

感谢wepon的无私奉献

对提供的数据做一些基本的统计,有助于对赛题的理解,可以熟悉业务逻辑,也方便后面的特征工程。

特征提取

  • 特征提取:将原始特征转换为一组具有明显物理意义(Gabor、几何特征[角点、不变量]、纹理[LBP HOG])或者统计意义或核的特征
  • 经验上来说,这些特征提取的越多越好,并不用担心特征过多,因为推荐系统的数据量都比较大,并且基于一些规则可以很好的筛选特征。
  • 第一次做特征提取,很多东西想得不够周到。参考了很多第一名的思想。

用户特征

用途:描述用户消费偏好

线下: 1. 领取优惠券率(领取次数/总次数) 2. 优惠券核销率(优惠券使用次数/优惠券领取次数) 3. 消费率(消费次数/总次数) 4. 核销时的优惠率 5. 领取、使用优惠券间隔 6. user经常活动的地点离平均/最大/最小用户-商家的最近门店距离 7. 消费频数 8. 优惠券领取频数 9. 优惠券使用频数 10. 用户满减优惠券核销率(满减优惠券使用次数/优惠券领取次数) 11. 用户满减优惠券核销比重(满减优惠券使用次数/优惠券使用次数) 12. 核销优惠券的平均/最低/最高消费打率 13. 核销过的商户数量,以及不同商家的比重 14. 核销过的不同优惠券数量,以及其与优惠券种类数的比重 15. 平均每个商家核销多少张优惠券

线上: 1. 优惠券领取率(领取/总) 2. 点击频数 3. 优惠券领取频数 4. 优惠券使用频数 5. 优惠券核销率(使用/领取) 6. 消费频数 7. 消费率(消费次数/总) 8. 核销时的优惠率 9. 领取、使用优惠券间隔 10. 用户线上不消费次数 11. 用户线下不消费次数占线上线下总的不消费次数的比重 12. 用户线下的优惠券核销次数占线上线下总的优惠券核销次数的比重

线下消费的优惠券特征

  1. 优惠率
  2. 优惠券被领取次数
  3. 优惠券核销率
  4. 领取、使用优惠券间隔

线上商户特征

  1. 点击频数
  2. 购买频数
  3. 优惠券被领取频数
  4. 优惠券被使用频数
  5. 消费率(购买/总)
  6. 优惠券领取率(领取/总)
  7. 优惠券核销率(使用/领取)
  8. 优惠率
  9. 领取、使用优惠券间隔

现在遇到了一些瓶颈。参考了前人的教程数据科学完整学习路径,发现自己基础还是不够扎实。决定先看看机器学习技法教程,再进行下一步。

=======2017.3.1======

看了一下GBDT,发现我的疑问还是不能解决。

  • 多类特征,怎么处理?
  • 处理的流程究竟是怎样的?

为了解决上述问题,我决定开始深入分析第一名的队伍的阿里天池O2O优惠券消费行为预测竞赛优胜方案源码。

=======2017.3.8======

算是大致看完了前辈的代码。见本博客文章“O2O优惠券预测——对第一名的思路源码分析”

这其中的奥妙深不可测。

知识累积不是一蹴而就的。加油吧。

=======2017.3.12======

SVM简介

SVM - Support Vector Machines, 支持向量机。是二分类模型。

线性可分SVM

概念复习

参考文献

输入空间:输入所有可能的取值的集合

特征向量:每个具体的输入

特征空间:所有特征向量存在的空间。特征空间可以是输入空间,也可以由输入空间映射得到。模型定义在特征空间上。

输出空间:输出所有可能的取值的集合

线性可分SVM学习目标

在特征空间找到一个分离超平面 \(wx+b=0\),并且间隔最大。

SVM与PLA区别

PLA:误分类最小策略,求得分离超平面。解不唯一。 线性可分SVM:间隔最大化,求得分离超平面。解唯一。

函数间隔和几何间隔

  • 一个点距离分离超平面的远近|wx+b| 是 分类预测的确信程度。例如将A分为0的确信度很高,而将C分为0的确信度较低
  • wx+by的符号一致,则分类正确
  • 函数间隔y(wx+b),表示分类的正确性及确信度
  • 超平面的函数间隔*:min{y(wx+b)}
  • 几何间隔:规范化||w||=1,即为\(y(\frac{w}{||w||}\cdot x + \frac{b}{||w||})\),使得间隔固定。(因为w和b成比例增加时,超平面不会改变,但函数间隔会变大)

SVM基本算法

标准问题

算法的推导

  • 一开始的目标是: -- 目标:求得一个x,使得margin最大 -- 条件: --- 每个点都被正确分类(b被塞入了w矩阵里) --- magin是最近的点的距离

  • 从距离的理解入手,如图所示

  • w的理解 -- 灰色是分割平面 -- \(x'\)\(x''\)是平面上的两个点,则它俩满足\(w^T X' = -b\)\(w^T x'' = -b\) -- 两式相减,得到 \(w^T(x'' - x')=0\) -- 则w垂直于平面,即w是平面的法向量 -- 那么dist是向量\(x' x''\)w上的投影

  • y(wx+b)>0,则距离可以表示为:

  • 因此,新的算法目标为

  • 归一化条件:margin=y(wx+b)=1,得到新目标

  • 对目标进行放缩,方便解

  • 再将最大化变为最小化,也拿走||w||的根号

支持向量

  • 在线性可分的情况下,训练数据集的样本点中与分离超平面距离最近的样本点的实例,叫做支持向量(support vector)
  • 支持向量是使得约束条件等号成立的点
  • 决定分离超平面时,只有支持向量起作用,而其他点不起作用
  • 在H1,H2上的点就是支撑向量(很少,但很重要的点)

间隔 margin

H1,H2之间,\(margin=\frac{2}{||w||}\)

间隔边界

H1,H2

标准问题的求解

  • 目标是二次的,条件是线性的

  • 则这是一个二次规划问题,有固定的解

  • 我们的标准问题:

  • 标准二次规划问题:

  • 系数代入:

在说LR之前,我们先回顾一下logistic分布。

logistic分布

如果连续随机变量\(X\)服从logistic分布,则\(X\)具有下列分布函数和密度函数

\[ F(x)=P(X<=x)=\frac{1}{1+e^{-(x-u)/r}} \]

\[ f(x)=F'(x)=\frac{e^{-(x-u)/r}}{r(1+e^{-(x-u)/r})^2} \]

其中

\(u\)为位置参数

\(r>0\)为形状参数

其中,密度函数与分布函数的形状如图所示

备注:分布密度函数与分布函数

概率密度函数\(f(x)\):表示瞬时值落在某区间的概率,是幅值的概率。++用来描述连续型随机变量取值的密集程度的。++\(f(x)\)表示X=x的概率是\(\int_0^1f(x)\)

\(P(X=x|x \in (0,1))=\int_0^1f(x)\)

分布函数\(F(x)\):描述随机变量落在任一区间的概率。

\(F(x)=P(X<=x)\)

关系:

分布函数\(F(x)\)是概率密度函数\(f(x)\)从负无穷到正无穷上的积分;

在坐标轴上,概率密度函数的函数值y表示落在x点上的概率为y;分布函数的函数值y则表示x落在区间(-∞上的概率。

二项logistic回归模型

用途:估计某个值的为哪一类的概率

logistic回归是分类问题。前面我们讲的分类问题的输出都是 “yes”或者“no”。但是在现实生活中,我们并不是总是希望结果那么肯定,而是概率(发生的可能性)。比如,我们希望知道这个房子在第三个星期被卖出去的概率。那么以前的分类算法就无法使用了,这时logistic 回归就派上了用场。

定义

二项logistic回归模型是如下的条件概率分布:

\[ P(Y=1|x)=\frac{exp(wx+b)}{1+exp(wx+b)} \]

\[ P(Y=0|x)=\frac{1}{1+exp(wx+b)} \]

其中: \(x \in R^n\) :输入

\(Y \in (0,1)\) :输出

给定\(x\),可以求得\(P(Y=1|x)\)\(P(Y=0|x)\)

logistic回归模型的特点

几率(odds)= 该事件发生的概率/该事件不该发生的概率,则对数几率:

\[ log(odds)=log(\frac{p}{1-p})=log(\frac{P(Y=1|x)}{1-P(Y=1|x)})=wx \]

则:输出Y=1的对数几率=输入x的线性函数

模型参数估计

输入: 一堆(x,y)

目标:估计参数w,b

方法:极大似然法

总结

  1. 逻辑回归是一种预测y的各类别的概率的模型,即计算P(Y=1|x)或者P(Y=0|x)
  2. 与机器学习过程类似,即 通过已知的大量(x,y),拟合计算参数w,b;再用y=wx+b来计算新的x下的y;把y输入sigmoid函数中,得到y为1的概率。

LR推导(sigmoid,损失函数,梯度,参数更新公式)

这篇文章非常详细地介绍了逻辑回归的推导。非常有用。我在此处进行了转载。

声明

  1. $ x(1),x(2),...,x(m) $ 表示 n 维空间的一个样本,\(x(i)\) 表示第i个样本,\(x(i)_j\) 表示第i个样本的第j维的数据(因为\(x\)是一个n维向量)。
  2. \(y(1),y(2),...,y(m)\) 表示 k 维空间的一个观测结果,记k从1,2,...,k变化,即分类问题中的k个类别,也可以0为下标开始,不影响推导。
  3. \(\pi()\)是我们学习到的概率函数,实现样本数据到预测结果的映射:\(R^n\rightarrow R^k\),(其实就是样本经过函数 \(\pi()\)计算后得到各个类别的预测概率,即一个k维向量), \(\pi(x)_u​\)表示数据样本x属于类别u的概率,我们希望\(\pi()​\)具有如下性质:
  1. \(\pi(x)_v>0\) (样本x属于类别v的概率大于0,显然概率必须大于0)
  2. \(\sum_{v=1}^k\pi(x)_v = 1\),样本x属于各个类别的概率和为1
  3. \(\pi(x(i))_{y(i)}在所有类别概率中最大\)
  1. \(A(u,v)\)是一个指示函数,\(当u=v时A(u,v)=1,当u\neq v时A(u,v)=0,如A(u,y(i))\)表示第i个观测结果是否为u

逻辑回归求解分类问题过程

对于二分类问题有k=2,对线性回归函数\(\lambda x\)进行非线性映射得到:

\[ \pi(x)_1 = \frac{\rm e^{\lambda \cdot x}}{\rm e^{\lambda \cdot x}+1}\tag{1} \] \[ \pi(x)_2 = 1-\pi(x)_1= \frac{1}{\rm e^{\lambda \cdot x}+1}\tag{2} \] 对于多分类问题有: \[ \pi(x) = \frac{\rm e^{\lambda _v\cdot x}}{\sum_{u=1}^m\rm e^{\lambda_u \cdot x}}\tag{3} \]\(\lambda\)求偏导可得:

\[ \begin{aligned} u = v 时, \frac {\partial\,\pi (x)_v}{\lambda_{v,j}} &= \frac{x_j\rm e^{\lambda _{v,j}\cdot x}\cdot \sum_{u=1}^m\rm e^{\lambda_{u,j} \cdot x}-x_j\rm e^{\lambda _{v,j}\cdot x}\rm e^{\lambda _{v,j}\cdot x}}{(\sum_{u=1}^m\rm e^{\lambda_{u,j} \cdot x})^2}\\ & = \frac{x_j\rm e^{\lambda _{v,j}\cdot x}}{\sum_{u=1}^m\rm e^{\lambda_{u,j} \cdot x}} \cdot \frac{\sum_{u=1}^m\rm e^{\lambda_{u,j} \cdot x}-\rm e^{\lambda_{v,j}\cdot x}}{\sum_{u=1}^m\rm e^{\lambda_{u,j} \cdot x}}\\& = x_j \pi(x)_v(1-\pi(x)_v)\end{aligned}\tag{4} \]

\[ \begin{aligned} u \neq v 时 \frac {\partial\,\pi (x)_v}{\lambda_{u,j}}&=-\frac{\rm e^{\lambda_{v,j} \cdot x} \cdot (x_j\rm e^{\lambda_{u,j} \cdot x})}{(\sum_{u=1}^m\rm e^{\lambda_{u,j} \cdot x})^2} \\ &= -x_j \pi(x)_v\pi(x)_u, u\neq v时 \end{aligned} \tag{5} \] 该分类问题的最大似然函数为: \[ L(\lambda)=\prod_{i=1}^m \pi(x(i))_{y(i)}\tag{6} \] 取对数得: \[ f(\lambda)=\log L(\lambda)=\sum_{i=1}^m \log(\pi(x(i))_{y(i)})\tag{7} \] 求似然函数最大值,令: \[ \begin{aligned} \frac{\partial\,f(\lambda)}{\partial \,\lambda_{u,j}} &=\frac{\partial}{\partial \,\lambda_{u,j}}\sum_{i=1}^m \log(\pi(x(i))_{y(i)}) \\ &= \sum_{i=1}^m \frac{1}{\pi(x(i))_{y(i)}}\frac{\partial}{\partial \,\lambda_{u,j}}\pi(x(i))_{y(i)} \\ &= \sum_{\begin{array}{c}i=1,\\y(i)=u\end{array}}^m \frac{1}{\pi(x(i))_{y(i)}}\frac{\partial}{\partial \,\lambda_{u,j}}\pi(x(i))_{u} + \sum_{\begin{array}{c}i=1,\\y(i)\neq u\end{array}}^m \frac{1}{\pi(x(i))_{y(i)}}\frac{\partial}{\partial \,\lambda_{u,j}}\pi(x(i))_{y(i)}\\ &= \sum_{\begin{array}{c}i=1,\\y(i)=u\end{array}}^m \frac{1}{\pi(x(i))_{y(i)}}x(i)_j\pi(x(i))_u(1-\pi(x(i))_u) \\ &\quad - \sum_{\begin{array}{c}i=1,\\y(i)\neq u\end{array}}^m \frac{1}{\pi(x(i))_{y(i)}}x(i)_j\pi(x(i))_{y(i)} \pi(x(i))_u\\ &= \sum_{\begin{array}{c}i=1,\\y(i)=u\end{array}}^m x(i)_j(1-\pi(x(i))_u)-\sum_{\begin{array}{c}i=1,\\y(i)\neq u\end{array}}^m x(i)_j \pi(x(i))_u \\ &= \sum_{\begin{array}{c}i=1,\\y(i)=u\end{array}}^m x(i)_j - \sum_{i=1}^m x(i)_j\pi(x(i))_u \\ &= 0 \end{aligned} \tag{8} \] 得: \[ \sum_{\begin{array}{c}i=1,\\y(i)=u\end{array}}^m x(i)_j = \sum_{i=1}^m x(i)_j\pi(x(i))_u\tag{9} \] 代入\(A(u,y(i))=1\)得: \[ \sum_{i=1}^m x(i)_j\pi(x(i))_u = \sum_{i=1}^m x(i)_jA(u,y(i))\tag{10} \] 综上有: \[ \frac{\partial\,f(\lambda)}{\partial \,\lambda_{u,j}}=\sum_{i=1}^m x(i)_j(A(u,y(i))-\pi(x(i))_u)\tag{11} \] 则参数更新公式为:

\[ \begin{aligned}\lambda_{u,j} &= \lambda_{u,j} - \alpha \cdot \frac{\partial\,f(\lambda)}{\partial \,\lambda_{u,j}} \\&= \lambda_{u,j} - \alpha \cdot \sum_{i=1}^m x(i)_j(A(u,y(i))-\pi(x(i))_u)\end{aligned}\tag{12} \]

sigmoid函数的由来(最大熵)

由上文已知\(\pi()\)具应有如下性质:

  1. 样本x属于类别v的概率大于0,显然概率必须大于0\(\pi(x)_v>0\tag{13}\)
  2. 样本x属于各个类别的概率和为1 \(\sum_{v=1}^k\pi(x)_v = 1\tag{14}\)
  3. \(\pi(x(i))_{y(i)}在所有类别概率中最大\)

其中对最后一个条件等价于尽可能的让\(\pi(x(i))\rightarrow y(i)\)\(\pi(x(i))\rightarrow A(u,y(i))\),理想情况为\(\pi(x(i))= A(u,y(i))\)固有: \[ \sum_{i=1}^m x(i)_j\pi(x(i))_u = \sum_{i=1}^m x(i)_jA(u,y(i))\tag{15},对所有的u,j都成立 \]

对所有类别及所有样本取\(\pi()\)的熵,得: \[ f(v,i)=-\sum_{v=1}^k\sum_{i=1}^m\pi(x(i))_v \log(\pi(x(i))_v)\tag{16} \] 得到一个优化问题:

\[\left\{ \begin{aligned} max f(v,i)=max (-\sum_{v=1}^k \sum_{i=1}^m pi(x(i))_v log(π(x(i))_v))\\ \pi(x)_v>0\\ \sum_{v=1}^k π(x)_v = 1\\ \sum_{i=1}^m x(i)_j π(x(i))_u = \sum_{i=1}^m x(i)_j A(u,y(i)) \end{aligned} \right. \tag{17}\] 利用拉格朗日对偶性求这个优化问题的对偶问题,首先引入拉格朗日函数:

\[ \begin{aligned}L &= \sum_{j=1}^n\sum_{v=1}^k\lambda_{v,j} \left( \sum_{i=1}^m\pi(x(i))_vx(i)_j-A(v,y(i))x(i)_j \right)\\&+ \sum_{v=1}^k\sum_{i=1}^m\beta_i(\pi(x(i))_v-1)\\&- \sum_{v=1}^k\sum_{i=1}^m\pi(x(i))_v\log(\pi(x(i))_v)\end{aligned}\tag{18} \] 其中 \[ \beta<0 \] ,由KKT条件有: \[ \frac{\partial\,L}{\partial \,\pi(x(i))_u} = \lambda_u\cdot x(i)+\beta_i-\log(\pi(x(i))_u) - 1 = 0 \quad对所有i,u \tag{19}\]

\[则:\pi(x(i))_u = e^{\lambda_u \cdot x(i)+\beta_i-1} \tag{20}\]

则: \[\pi(x(i))_u = e^{\lambda_u \cdot x(i)+\beta_i-1} \tag{20}\] 由(14)式得到: \[ \sum_{v=1}^k e^{\lambda_u \cdot x(i)+\beta_i-1} = 1\\ \] 即: \[e^\beta=\frac{1}{\sum_{v=1}^ke^{\lambda_u \cdot x(i)-1}} \tag{21} \] 代入(21)式消去常数项得: \[ \pi(x(i))_u=\frac{e^{\lambda_u \cdot x}}{\sum_{v=1}^ke^{\lambda_u \cdot x}}\tag{22} \] 即多分类问题对应的sigmoid函数

其它文献

  1. Logistic Regression 的前世今生(理论篇)

简介

场景

从某一结果集中地逐一读记录 ### 游标本质 能从包括多条数据记录的结果集中每次提取一条记录的机制。

我们知道关系数据库管理系统实质是面向集合的,在MS SQL SERVER 中并没有一种描述表中单一记录的表达形式,除非使用where 子句来限制只有一条记录被选中。因此我们必须借助于游标来进行面向单条记录的数据处理。 ### 游标种类 - Transact_SQL 游标 - API 游标 - 客户游标

游标操作

使用游标有四种基本的步骤:声明游标、打开游标、提取数据、关闭游标。

声明游标

游标的声明包括两个部分:游标的名称 + 这个游标所用到的SQL语句。

例:要声明一个叫作Cus-tomerCursor的游标用以查询地址在北京的客户的姓名、帐号及其余额:

1
2
3
4
DECLARE CustomerCursor CURSOR FOR 
SELECT acct_no,name,balance
FROM customer
WHERE province="北京";

TIPS:

  • 声明游标的这一段代码行是不执行的,不能将debug时的断点设在这一代码行上,也不能用IF语句来声明两个同名的游标,如下列的代码就是错误的。
1
2
3
4
5
6
7
8
9
10
11
IF Is_prov="北京"THEN 
DECLARE CustomerCursor CURSOR FOR
SELECT acct_no,name,balance
FROM customer
WHERE province="北京";
ELSE
DECLARE CustomerCursor CURSOR FOR
SELECT acct_no,name,balance
FROM customer
WHERE province〈〉"北京";
END IF

打开游标

打开游标是执行与其相关的一段SQL语句

1
OPEN CustomerCursor;

提取数据

必须用FETCH语句来取得数据。

一条FETCH语句一次可以将一条记录放入程序员指定的变量中。

事实上,++FETCH语句是游标使用的核心++。

用游标提取一条数据:

1
2
3
4
FETCH CustmerCur-sor 
INTO:ls_acct_no,
:ls_name,
:ll_balance;

用游标遍历很多条数据:

而在多数情况下,我们所想要作的是在数据库中从第一条记录开始提取,一直到结束。所以我们一般要将游标提取数据的语句放在一个循环体内,直至将结果集中的全部数据提取后,跳出循环圈。

通过检测SQLCA.SQL-CODE的值,可以得知最后一条FETCH语句是否成功。

一般,当SQLCODE值为0时表明一切正常,100表示已经取到了结果集的末尾,而其它值均表明操作出了问题,这样我们可以编写以下的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
lb_continue=True 
ll_total=0
DO WHILE lb_continue
FETCH CustomerCur-sor
INTO:ls_acct_no,
:ls_name,
:ll_balance;
If sqlca.sqlcode=0 Then #如果SQLCA.SQL-CODE==0,则一切正常
ll_total+=ll_balance
Else #跳出循环
lb_continue=False
End If
LOOP

关闭游标

1
CLOSE CustomerCursor;

使用Where子句子

我们可以动态地定义游标中的Where子句的参数,例如在本例中我们是直接定义了查询省份是北京的记录,但也许在应用中我们要使用一个下拉式列表框,由用户来选择要查询的省份,我们该怎样做呢? 我们在前面曾经提到过,DECLARE语句的作用只是定义一个游标,在OPEN语句中这个游标才会真正地被执行。了解了这些,我们就可以很方便地实现这样的功能,在DECLARE的Where子句中加入变量作参数,如下所示:

1
2
3
4
5
6
DECLARE CustomerCursor CURSOR FOR 
SELCECT acct_no,name,balance
FROM customer
WHERE province=:ls_province;
∥定义ls_province的值
OPEN CustomerCursor;

游标的类型

同其它变量一样,我们也可以定义游标的访问类型:全局、共享、实例或局部,游标变量的命名规范建议也同其它变量一样。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
--声明游标
declare my_cursor cursor keyset for select * from info
--删除游标资源
deallocate my_cursor
--打开游标,在游标关闭或删除前都有效
open my_cursor
--关闭游标
close my_cursor
--声明局部变量
declare @id int,@name varchar(20),@address varchar(20)
--定位到指定位置的记录
fetch absolute 56488 from my_cursor into @id,@name,@address
select @id as id,@name as name,@address as address
--定位到当前记录相对位置记录
fetch relative -88 from my_cursor into @id,@name,@address
select @id as id,@name as name,@address as address
--定位到当前记录前一条
fetch prior from my_cursor into @id,@name,@address
select @id as id,@name as name,@address as address
--定位到当前记录后一条
fetch next from my_cursor into @id,@name,@address
select @id as id,@name as name,@address as address
--定位到首记录
fetch first from my_cursor into @id,@name,@address
select @id as id,@name as name,@address as address
--定位到尾记录
fetch last from my_cursor into @id,@name,@address
select @id as id,@name as name,@address as address

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
use database1
declare my_cursor cursor scroll dynamic
/**//*scroll表示可随意移动游标指针(否则只能向前),dynamic表示可以读写游标(否则游标只读)*/
for
select productname from product
open my_cursor
declare @pname sysname
fetch next from my_cursor into @pname
while(@@fetch_status=0)
begin
print 'Product Name: ' + @pname
fetch next from my_cursor into @pname
end
fetch first from my_cursor into @pname
print @pname
/**//*update product set productname='zzg' where current of my_cursor */
/**//*delete from product where current of my_cursor */
close my_cursor
deallocate my_cursor

动手前先动脑,这句话献给自己。

目标

从出租车行驶数据中,筛选出OD点。 ## 数据集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
名称:2012年11月1日 北京市出租车GPS数据

格式:txt文本文件

数据项及顺序:车辆标识,触发事件,运营状态,GPS时间,GPS经度,GPS纬度,GPS速度,GPS方向,GPS状态
车辆标识:6个字符
触发事件:0=变空车,1=变载客,2=设防,3=撤防,4=其它
运营状态:0=空车,1=载客,2=驻车,3=停运,4=其它
GPS时间
GPS经度
GPS纬度
GPS速度:取值000-255内整数,以公里/小时为单位
GPS方位:取值000-360内整数,以度为单位
GPS状态:0=无效,1=有效
结束串:回车符+换行符

数据示例:
123456,0,0,20110414160613,116.4078674,40.2220650,21,274,1

思路

  1. 将数据点按照“车牌号、运营时间、运营状态”依次从小到大排序
  2. 筛出同一车牌号的运营状态变化的时刻的数据

方法

  • 方法一:导入数据库,再写脚本操作数据。可能是我对数据库实在没缘分,这个方法没有成功。

  • 方法二:将车牌号分段后,在每段上进行如上思路所示的操作。

为了更好地分段,我们先对车牌号段进行分析。 ### 车牌号段分析

查询车的数目:12409个

1
SELECT COUNT(DISTINCT id) FROM SET1

脚本名:data1IDcount.py

地址:81服务器上,D:

听说数据集有三千多万,所以我决定每一千个数据取一条进行粗略分析。

车牌号分布:

结果: 1. 车牌号分布在1-800000之间 2. 100000-200000的车最多 3. 一共有32885600条数据

分段

脚本名:data2cut.py

分段法:将车牌号分为10段,其中100000-200000为三段,其余段均分。 简单起见,还是将车牌号均分为十段了(ERROR:Errcode: 28 - No space left on device))

还是采用了数据库。是福不是祸,是祸躲不过呀。

伪代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
for i = 0:10000:800000
# 为本区间数据建立新表,并插入数据
CREATE TABLE to this range
INSERT data
#将本区间数据排序
ORDER BY id,timen,opevent
#遍历,筛出本段的OD点
for line in this range table

#如果本条数据是跳跃点,则插入到OD表中
#vehicle:上一条数据的车牌号
#pre:上一条数据的opevent

#第一条数据
if vehicle=="":
vehicle = row[0]
pre=row[2]
else:#从第二条记录开始
# 如果与上一条是一个车
if vehicle==row[0]:
#如果与上一条记录是同一个车,且event有变化
if pre!=row[2]:
INSERT to OD_table
pre=row[2]
vehicle=row[0]
else:
continue
#如果与上一条不是同一个车
else:
vehicle=row[0]
pre=row[2]

结果

原始数据:data.set1,32885600个

OD点:data.set1_od ,645271个

AUC定义

用途:用来度量分类模型好坏的一个标准 背景: - 有些时候,仅仅依靠正确率是不妥当的。 - 能客观反映对正样本、负样本综合预测的能力,还要考虑消除样本倾斜的影响。

ROC

  • ROC:Receiver Operating Characteristic
  • ROC曲线:横坐标是false positive rate(FPR),纵坐标是true positive rate(TPR)。
  • 对某个分类器而言,我们可以根据其在测试样本上的表现得到一个TPR和FPR点对。这样,此分类器就可以映射成ROC平面上的一个点。
  • 调整这个分类器分类时候使用的阈值,我们就可以得到一个经过(0, 0),(1, 1)的曲线,这就是此分类器的ROC曲线。

tip:FPR和TPR 先来看一个普遍的二分类问题的结果,预测值和实际值有4种组合情况,看下面的表格: 我们定义 \[ TruePositiveRate(TPR) = \frac{TP}{TP+FN=P} = \frac{正确预测1}{正确预测1+错误预测1=1的数量}=实际正样本正确预测的比例\] \[ FalsePositiveRate(FPR) = \frac{FP}{FP+TN=N} = \frac{错误预测0}{错误预测0+正确预测0=0的数量}=实际负样本错误预测的比例\]

如何一个分类器的画ROC曲线

概率输出:即表示分类器认为某个样本具有多大的概率属于正样本(或负样本),来动态调整一个样本是否属于正负样本 例: - 图中共有20个测试样本 - “Class”一栏表示每个测试样本真正的标签(p表示正样本,n表示负样本) - “Score”表示每个测试样本属于正样本的概率。 步骤: - 从高到低,依次将“Score”值作为阈值,当测试样本属于正样本的概率大于或等于这个阈值时,我们认为它为正样本,否则为负样本。 - 举例来说,对于图中的第4个样本,其“Score”值为0.6,那么样本1,2,3,4都被认为是正样本,因为它们的“Score”值都大于等于0.6,而其他样本则都认为是负样本。 - 每次选取一个不同的阈值,我们就可以得到一组FPR和TPR,即ROC曲线上的一点。这样一来,我们一共得到了20组FPR和TPR的值,将它们画在ROC曲线的结果如下图: - 当我们将阈值设置为1和0时,分别可以得到ROC曲线上的(0,0)和(1,1)两个点。将这些(FPR,TPR)对连接起来,就得到了ROC曲线。 - 当阈值取值越多,ROC曲线越平滑。

AUC

  • AUC的值就是处于ROC curve下方的那部分面积的大小
  • 通常,AUC的值介于0.5到1.0之间
  • 较大的AUC代表了较好的performance

计算AUC的方法

  • 直接计算AUC是很麻烦的,所以就使用了AUC的一个性质(它和Wilcoxon-Mann-Witney Test是等价的)来进行计算。
  • Wilcoxon-Mann-Witney Test就是测试任意给一个正类样本和一个负类样本,正类样本的score有多大的概率大于负类样本的score。
  • 有了这个定义,我们就得到了另外一中计算AUC的办法:得到这个概率。
方法一

统计一下所有的 M×N(M为正类样本的数目,N为负类样本的数目)个正负样本对中,有多少个组中的正样本的score大于负样本的score。当二元组中正负样本的 score相等的时候,按照0.5计算。然后除以MN。实现这个方法的复杂度为O(n^2)。n为样本数(即n=M+N)。

方法二

第二种方法实际上和上述方法是一样的,但是复杂度减小了。

  • 首先对score从大到小排序
  • 然后令最大score对应的sample 的rank为n,第二大score对应sample的rank为n-1,以此类推
  • 然后把所有的正类样本的rank相加,再减去正类样本的score为最小的那M个值的情况。
  • 得到的就是所有的样本中有多少对正类样本的score大于负类样本的score。
  • 然后再除以M×N。即 AUC=((所有的正例位置相加)-M*(M+1))/(M*N)

另外,特别需要注意的是,再存在score相等的情况时,对相等score的样本,需要 赋予相同的rank(无论这个相等的score是出现在同类样本还是不同类的样本之间,都需要这样处理)。具体操作就是再把所有这些score相等的样本 的rank取平均。然后再使用上述公式。

参考文献

  1. 评价分类器性能指标之AUC、ROC
  2. AUC(Area Under roc Curve)学习笔记

感觉自己记性越来越差。寒假前看的东西,回来忘得一干二净。从此认真做笔记,不能再重蹈覆辙。——题记 (第一次使用markdown,不太习惯,后面的公式没有继续打。现在去学习一下好用一些的公式编辑方法) # 简介 定义:感知机是二类分类的线性模型。

输入:实例的特征向量

输出:实例的类别(±1)

感知机模型

感知机——由输入空间到输出空间的函数:

\[ f(x)=sign(wx+b) \]

###Tips: $ w R^n $:权值,weight $ b R \(:偏值,bias 输入空间(特征空间):\) X R^n $ 输出空间:$ y={+1,-1} $ 输入:$ x X \(表示实例的特征向量,对应于输入空间的点 输出:\) y Y $,表示实例的类别

感知机学习策略

  1. 感知机学习目标:求得一个能将训练集正实例点和负实例点完全正确分开的分离超平面 = 确定模型参数w,b。
  2. 感知机学习策略:定义(经验)损失函数并将损失函数极小化。
  3. 损失函数的选择:
  • 《统计学习方法》中介绍到的损失函数:所有误分类点到超平面S的总距离: 一般不考虑w,即损失函数为: M:误分类点的个数
  • 《西瓜书》里提到的误差是均方误差: 然后用最小二乘法求解w,b。
  1. 误分类点越少,损失函数越小。

将感知机学习问题转化为求解损失函数最优化问题
# 感知机学习算法 ## 感知机学习算法的原始形式

算法的收敛性

可算是把博客布置得差不多了。还有很多功能待完善,先记下来,日后再说。

1.RSS订阅功能

2.新浪微博圈

3.搜索功能

4.评论功能

5.访问量统计

6.数学公式支持。已解决。参考文献,程数的博客

7.图片一键上传到图床,已解决。参考文献MarkdownPicPicker-master

8.sublime text编辑mdWEB实时刷新sublime实时保存

  1. 站长统计
  2. 搜索引擎
1
2
3
4

9.一键发布功能[已解决](http://blog.csdn.net/anonymalias/article/details/50528946)

10.[为Hexo博客标题自动添加序号:hexo-heading-index](http://www.qingpingshan.com/jianzhan/cms/212734.html)

很多东西看了就忘。一定要好好做笔记。

本节主要记录《机器学习基石》的常见符号。

基础符号

输入: $ x X $ 输出: $y Y $ 目标函数: $f:XY $ (理想中的,实际得不到) 假设函数:$g:XY $ ,又称为hypothesis(学习到的g,希望跟f越像越好) $g H $ 假设函数集合:$H = \{h_k\} $ hypothesis set 训练集:\(D=\\{(x_1,y_1),...,(x_N,y_N)\\}\) 机器学习演算法:\(A\)

机器学习流程

  • 从数据集D出发
  • 通过演算法A,来计算出一个g,使得g很接近f

误差E

不知道为什么公式显示不出来,只好手动展图了 输入误差:

\[E_{in}(h)=\frac{1}{N} \sum_{n=1}^N(h(x_n)-y_n)^2\]

  • 样本(训练集)中出现的错误率

输出误差:

\[E_{out}(h)=\mathcal{E}_{(x,y)\text~P}(w^Tx-y)^2\]

  • 总体(测试集+训练集)中出现的错误率