专栏名称: 挖地兔
金融数据采集与挖掘,开启量化金融的第一扇大门。
目录
相关文章推荐
吉林果粉天天报  ·  吉林市两所学校揭牌成立 ·  4 小时前  
吉林果粉天天报  ·  吉林市两所学校揭牌成立 ·  4 小时前  
51好读  ›  专栏  ›  挖地兔

图文实例教会你逻辑回归

挖地兔  · 公众号  ·  · 2020-03-31 09:18

正文



金融与技术学习兴趣小组

编译整理 | 一只小绿怪兽



逻辑回归(Logistic regression) ,虽然名字中带有回归两个字,但其实它解决的并不是回归问题,而是分类问题。先来看一下它的定义:





在统计学中,逻辑回归是用来对某一类别或事件发生的 概率 进行建模的模型,比如,通过/失败、赢/输、存活/死亡,健康/生病。它也可以应用于多分类的问题,比如,判断一个图片中是否包含猫、狗、狮子等等。每一个在图像中被检测的物体都会被赋予一个 概率, 这个概率的取值范围在0到1之间,且总和为1



我们在之前的文章中介绍过 KNN算法 ,该算法同样可用于解决分类问题, 它的分类依据是 距离 ,即如果一个样本在特征空间中的k个最相邻的样本中的大多数属于某一个类别,则该样本也属于这个类别,并具有这个类别上样本的特性。



对比来看的话,从定义中可以看出,逻辑回归是基于 概率 对事件进行分类的,也就是说, 逻辑回归解决的是分类问题,并且分类的依据是概率 。明白了这一点,下面我们就来看一下,它到底是怎么用概率进行分类的。



逻辑回归 vs 线性回归



逻辑回归和线性回归在原理上有很多相似之处,所以对比来看的话会更加清晰。



首先,回顾一下线性回归。假设有一组数据,包含两列,重量和尺寸,现在想看一下二者之间的关系,然后建立一个线性回归模型,用重量预测尺寸,具体步骤如下:



① 获取数据,包含重量和尺寸。





② 建立模型,拟合出一条直线。



在确定这条直线的时候,运用的方法是最小二乘法,它的思路是,计算每个点到拟合直线的距离(残差),先平方再求和,然后通过最小化残差平方和,确定直线的斜率和截距。





③ 预测。



利用重量和尺寸之间的线性关系,如果知道了重量的值,就可以预测对应的尺寸的值。





下面来看一下逻辑回归。和上面用线性回归预测连续值不同,逻辑回归用来预测分类问题,比如二分类的是/不是。如下图中,用重量来判断是否肥胖。



① 获取数据,包含重量和它所属的类别,即是否肥胖。





② 建立模型,拟合出一条S曲线。



与线性回归不同,逻辑回归拟合的是一条S曲线,并且曲线在纵轴的取值范围是0到1,代表的是以重量衡量时,属于肥胖的概率。





比如,对于B的重量,它属于肥胖的概率比较大,大约在0.9以上,对于A的重量,它属于肥胖的概率比较小,大约在0.5左右。



可以看出,相比于线性回归能够根据拟合直线预测出一个具体的值,逻辑回归则是根据拟合曲线预测出一个概率,然后再根据这个概率来判断它应该属于哪个类别。比如,设置一个临界值为0.5,如果得出的概率大于0.5,则归类为是肥胖,否则就归类为不是肥胖。



前面提到,在确定拟合直线时,线性回归用到的是最小二乘法,通过最小化残差平方和,得到直线的斜率和截距。而在逻辑回归中,没有残差的概念,所以也就不能用最小二乘法来确定拟合曲线,而是用最大似然估计。



最大似然估计



在线性回归中,为了估计直线的斜率和截距这两个参数,使用的方法是最小二乘法,即最小化残差平方和,而在逻辑回归中,为了估计参数,使用的方法是 最大似然估计 即最大化一个 似然函数 ,概念“似然”对应的是“可能性likelihood”, 所以也可以理解为最大化一个可能性函数,定义如下。





根据定义,如果想要估计参数,首先得有一个似然函数,然后通过最大化这个似然函数,得到参数的估计值。



在逻辑回归中,我们需要借助一个函数来构建似然函数,这个函数就是 sigmoid函数 ,也叫Logistic函数。先来看看它长什么样子,如下图。





从上图可以看出, sigmoid函数 的形状像一个S,自变量的取值范围是负无穷到正无穷,因变量的取值范围在0到1之间,而且,当自变量大于0时,因变量的值大于0.5,当自变量小于0时,因变量的值小于0.5。



在二分类问题中,因变量y的值只能是0或者1,利用sigmoid函数的特征,如果把临界值设置为0.5,则当自变量大于0,因变量的取值范围在0.5和1之间时,让y等于1,相反,当自变量小于0,因变量的取值范围在0和0.5之间时,让y等于0。



因此,借助sigmoid函数的上述特性,我们可以解决分类问题。明白了这一点,下面就来看一下具体的公式。





首先,在最开始,有自变量x和因变量h(θx),因变量的取值与自变量x和参数θ的取值有关,此时因变量h(θx)的取值范围没有限制,可以是从负无穷到正无穷,如上图例子,其中,θ是要估计的参数。



接下来,为了让h(θx)的取值范围压缩到0和1之间,需要借助sigmoid函数转换一下,最终得到公式(2)中的函数,又因为逻辑函数计算的是概率,因此,最终在等式的右边是一个概率值,含义是在给定自变量x和参数θ的条件下,y=1的概率。





整个分类过程的转换思路如上图所示,下面就来看一下具体的例子。




在上图的例子中,直线将平面分成两个区域,当其大于等于0时,y=1,即直线右侧包含星星的区域,小于0时,y=0,即直线左侧包含圆圈的区域。也就是说,通过这条直线,我们把y=1和y=0的值分开了,这条线叫做 决策边界(Decision boundary)





同样,在这个例子中,曲线将平面分成两个区域,当其大于等于0时,y=1,即曲线外侧包含星星的区域,小于0时,y=0,即曲线内部包含圆圈的区域,这条曲线是决策边界。



在上面给出的两个例子中,为了让大家更直观地观察图形效果,我们直接对参数θ进行了赋值,但其实这个参数θ是需要根据数据集估计的,下面,就回到最开始的问题,如何用最大似然估计的方法得到参数θ。



由于原始式子(2)中的公式比较复杂,所以这里我们借助 logit函数 ,把原式转换成带有log的函数。





由定义可知,logit函数把原来取值范围在0到1之间的概率,转换成了负无穷到正无穷的范围,如下图。





此时,如果按照线性回归的思路,用最小二乘法,由于这里点到直线的距离可以是无穷大,没法求最小值,所以不能用该方法,而应该用最大似然估计。



第一步,计算这些点对应的log(odds)的值。





第二步,根据p和log(odds)之间的对应关系,求出p值。比如,看A点,计算出它的log(odds)等于-2.1,然后再带入p等式右侧,求出p值等于0.1。当把所有的点都按照上述方式对应到左侧之后,就能够拟合出一条S曲线。





第三步,计算该拟合曲线的可能性,将各样本点所代表的概率值相乘即可。这里需要注意的是,某一个点属于蓝色还是橙色的概率和为1,其中蓝色代表的是y=1,橙色代表的是y=0。因此,如果蓝色点的概率用p表示,则橙色点的概率则等于1-p。





在计算可能性likelihood的时候,通常习惯先取对数,然后拆分成加法计算,这里可以理解为,求likelihood的最大值和求log(likelihood)的最大值是一样的。



然后旋转第一步中右侧曲线的位置,重复执行上述操作,可以得到很多个不同的可能性likelihood的取值,最终,可能性最大的那条曲线拟合出的结果就是我们想要的预测曲线。



上面提到,我们要不断旋转第一步中右侧曲线的位置来计算可能性likelihood,然后取最大的那一个,但是旋转曲线的结果有无穷多个,如果没有一个规则的话,会经历很多次没必要的计算,浪费资源,也浪费感情。



因此,为了解决上述问题,需要介绍另外两个概念, 损失函数(loss function) 梯度下降(gradient descent)。



损失函数(loss function) 的概念,在之前介绍线性回归的文章中有介绍过,可以把它理解为真实值和根据模型预测得出的预测值之间的差异。





梯度下降(gradient descent) 是一种优化算法,它的目的是找到一个函数的局部最小值。





因此,我们可以利用梯度下降的方法,去求损失函数的最小值。当损失函数取最小值时,预测值和真实值之间的差距最小,此时得出的拟合曲线和估计出的参数是我们想要得到的最优结果。



首先,看一下在逻辑回归中,损失函数的表达式长什么样子。





如上图中的推导,将可能性likelihood按照y=1和y=0分成两个部分,分别求最大值,然后在各自前面添加一个负号,就转换成求最小值,从而可以推导出右侧的损失函数J(θ)。注意,在二分类问题中,y的值只能是1或者0。



有了损失函数J(θ),接下来,就可以用梯度下降的方法,去求损失函数J(θ)的最小值了,当J(θ)取最小值时的参数θ,就是通过最大似然估计得到的最优参数。



本文暂时不对梯度下降的具体原理和公式做过多介绍,大家只要先知道它是求最小值的一个优化算法就可以啦,下面直接看一下逻辑回归在Python中是如何调用的。



Python 实例



我们可以导入 sklearn.linear_model 模块中 LogisticRegression 类实现该算法,先利用训练集数据构建模型,再用测试集数据进行预测。



逻辑回归算法的实现步骤和KNN算法类似:

① 先导入相应的模块

② 划分训练集和测试集

③ 创建一个分类器

④ 放入训练集数据进行学习,得到预测模型

⑤ 在测试集数据上进行预测



【工具】Python 3

【数据】 tushare.pro

【注】本文注重的是方法的讲解,请大家灵活掌握。



import tushare as ts
import pandas as pd

pd.set_option("expand_frame_repr"False)       # 当列太多时不换行

# 设置token
ts.set_token('your token')
pro = ts.pro_api()

# 导入000002.SZ前复权日线行情数据,保留收盘价列
df = ts.pro_bar(ts_code='000002.SZ', adj='qfq', start_date='20190101', end_date='20191231')
df.sort_values('trade_date', inplace=True)
df['trade_date'] = pd.to_datetime(df['trade_date'])
df.set_index('trade_date', inplace=True)
df = df[['close']]

# 计算当前、未来1-day涨跌幅
df['1d_future_close'] = df['close'].shift(-1)
df['1d_close_future_pct'] = df['1d_future_close'].pct_change(1)
df['1d_close_pct'] = df['close'].pct_change(1)
df.dropna(inplace=True)
# ====1代表上涨,0代表下跌
df.loc[df['1d_close_future_pct'] > 0'未来1d涨跌幅方向'] = 1
df.loc[df['1d_close_future_pct'] <= 0'未来1d涨跌幅方向'] = 0

df = df[['1d_close_pct''未来1d涨跌幅方向']]
df.rename(columns={'1d_close_pct''当前1d涨跌幅'}, inplace=True)
print(df.head())

             当前1d涨跌幅  未来1d涨跌幅方向
trade_date                     
2019-01-03  0.007112        1.0
2019-01-04  0.035728        1.0
2019-01-07  0.004815        0.0
2019-01-08 -0.001997        1.0
2019-01-09  0.013203        0.0


from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split

# 创建特征 X 和标签 y
y = df['未来1d涨跌幅方向'].values
X = df.drop('未来1d涨跌幅方向', axis=1).values

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, random_state=42)

# 创建一个逻辑回归分类器
logreg = LogisticRegression(solver='liblinear')

# 放入训练集数据进行学习
logreg.fit(X_train, y_train)

# 在测试集数据上进行预测
new_prediction = logreg.predict(X_test)
print("Prediction: {}".format(new_prediction))

# 测算模型的表现:预测对的个数 / 总个数
print(logreg.score(X_test, y_test))

Prediction: [0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
 0. 0. 0. 0. 0. 0. 0. 0. 0.






请到「今天看啥」查看全文


推荐文章
吉林果粉天天报  ·  吉林市两所学校揭牌成立
4 小时前
吉林果粉天天报  ·  吉林市两所学校揭牌成立
4 小时前
滑州百事通  ·  滑县中心医院2016年年终总结表彰会
8 年前
米尔看天下  ·  牛掰!微信还能看撤回的消息!
8 年前
执业药师头条  ·  【西药】每日一练-10.22
7 年前