前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >机器学习之逻辑回归

机器学习之逻辑回归

作者头像
润森
发布2019-09-17 11:44:51
9620
发布2019-09-17 11:44:51
举报
文章被收录于专栏:毛利学Python

文中的所有数据集链接:https://pan.baidu.com/s/1TV4RQseo6bVd9xKJdmsNFw

提取码:8mm4

什么是逻辑回归

回想一下线性回归,它被用于确定一个连续因变量的值。逻辑回归通常用于分类目的。与线性回归不同,因变量只能采用有限数量的值,即因变量是分类的。当可能结果的数量只有两个时,它被称为二元逻辑回归。

从大的类别上来说,逻辑回归是一种有监督的统计学习方法,主要用于对样本进行分类

逻辑回归与线性回归的关系

逻辑回归也被称为广义线性回归模型,它与线性回归模型的形式基本上相同,都具有 ax+b,其中a和b是待求参数,其区别在于他们的因变量不同,多重线性回归直接将ax+b作为因变量,即y = ax+b,而logistic回归则通过函数S将ax+b对应到一个隐状态p,p = S(ax+b),然后根据p与1-p的大小决定因变量的值。这里的函数S就是Sigmoid函数,就是因为这个函数的使用才能分类

在这里插入图片描述

该函数具有如下的特性:当x趋近于负无穷时,y趋近于0;当x趋近于正无穷时,y趋近于1;当x= 0时,y=0.5.

假设现在有一个函数 y = a*x1 +b *x2 +c*x3 +b x1,x2,x3 带入sigmoid函数中 得到y 如果大于0.5,分类为1,小于0.5,分类为0

德国信用卡欺诈数据集

欧洲的信用卡持卡人在2013年9月2天时间里的284807笔交易数据,其中有492笔交易是欺诈交易,占比0.172%。数据采用PCA变换映射为V1,V2,…,V28 数值型属性,只有交易时间和金额这两个变量没有经过PCA变换。输出变量为二值变量,1为正常,0为欺诈交易。

在这里插入图片描述 读取excel文件

代码语言:javascript
复制
data = pd.read_csv("../credit-a.csv", header=None) 
data.head()

在这里插入图片描述 我们可以从图上可以看到有15个特征,一个分类结果 相当于y = a1*x1 +…… +a15 *x15 +b

逻辑回归和分类数据集

代码语言:javascript
复制
from sklearn.model_selection import train_test_split
from sklearn.linear_model.logistic import  LogisticRegression

将x 作为特征数据,y作为分类结果,因为输出变量为二值变量,1为正常,0为欺诈交易,而我这是-1代表欺诈和交易,所以用replace方法把-1,变为0

代码语言:javascript
复制
x = data[data.columns[:-1]] #
y = data[data.columns[15]].replace(-1,0)

将x和y分为训练集和测试集

代码语言:javascript
复制
x_train,x_test,y_train,y_test = train_test_split(x,y)
len(x_train),len(x_test)
OUT:
(489, 164)

和线性回归一样的操作

代码语言:javascript
复制
model = LogisticRegression()  #用逻辑回归建立模型
model.fit(x_train,y_train)  #fit 和predict 
model.predict(x_test)
OUT:
array([1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0,
       0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0,
       0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0,
       0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0,
       0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0,
       1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0,
       0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0,
       1, 0, 0, 1, 0, 1, 1, 0, 1, 1], dtype=int64)
       #这里有164个结果

predict_proba 方法可以得到概率(Sigmoid的x和y)

代码语言:javascript
复制
model.predict_proba(x_test)

在这里插入图片描述

第一个数[1.42575343e-02, 9.85742466e-01] 也就是x = 0.014, y=0.9>0.5 分类结果为1

对于精确性如何,导入accuracy_score

代码语言:javascript
复制
from sklearn.metrics import accuracy_score 
accuracy_score(model.predict(x_test), y_test)
OUT:
0.8719512195121951

也就是在168个测试样本中168*0.8719512195121951个是正确的

预测Titanic乘客是否生还

来源kaggle
1. 导入工具库和数据
代码语言:javascript
复制
import numpy as np 
import pandas as pd 

from sklearn import preprocessing
import matplotlib.pyplot as plt 
plt.rc("font", size=14)
import seaborn as sns
sns.set(style="white") #设置seaborn画图的背景为白色
sns.set(style="whitegrid", color_codes=True)

# 将数据读入 DataFrame
df = pd.read_csv("./titanic_data.csv")

# 预览数据
df.head()

代码语言:javascript
复制
print('数据集包含的数据个数 {}.'.format(df.shape[0]))

数据集包含的数据个数 1310.

2. 查看缺失数据
代码语言:javascript
复制
# 查看数据集中各个特征缺失的情况
df.isnull().sum()
out:
    pclass         1
    survived       1
    name           1
    sex            1
    age          264
    sibsp          1
    parch          1
    ticket         1
    fare           2
    cabin       1015
    embarked       3
    dtype: int64
2.1. 年龄
代码语言:javascript
复制
# "age" 缺失的百分比 
print('"age" 缺失的百分比  %.2f%%' %((df['age'].isnull().sum()/df.shape[0])*100))
"age" 缺失的百分比  20.15%

约 20% 的乘客的年龄缺失了. 看一看年龄的分别情况.

代码语言:javascript
复制
ax = df["age"].hist(bins=15, color='teal', alpha=0.6)
ax.set(xlabel='age')
plt.xlim(-10,85)
plt.show()

在这里插入图片描述 由于“年龄”的偏度不为0, 使用均值替代缺失值不是最佳选择, 这里可以选择使用中间值替代缺失值

在数量上,偏度为负(负偏态)就意味着在概率密度函数左侧的尾部比右侧的长,绝大多数的值(不一定包括中位数在内)位于平均值的右侧。偏度为正(正偏态)就意味着在概率密度函数右侧的尾部比左侧的长,绝大多数的值(不一定包括中位数)位于平均值的左侧。偏度为零就表示数值相对均匀地分布在平均值的两侧,但不一定意味着其为对称分布。

代码语言:javascript
复制
# 年龄的均值
print('The mean of "Age" is %.2f' %(df["age"].mean(skipna=True)))
# 年龄的中间值
print('The median of "Age" is %.2f' %(df["age"].median(skipna=True)))

The mean of "Age" is 29.88 The median of "Age" is 28.00

2.2. 仓位
代码语言:javascript
复制
# 仓位缺失的百分比
print('"Cabin" 缺失的百分比 %.2f%%' %((df['cabin'].isnull().sum()/df.shape[0])*100))
代码语言:javascript
复制
"Cabin" 缺失的百分比 77.48%

约 77% 的乘客的仓位都是缺失的, 最佳的选择是不使用这个特征的值.

2.3. 登船地点
代码语言:javascript
复制
# 登船地点的缺失率
print('"Embarked" 缺失的百分比 %.2f%%' %((df['embarked'].isnull().sum()/df.shape[0])*100))
代码语言:javascript
复制
"Embarked" 缺失的百分比 0.23%

只有 0.23% 的乘客的登船地点数据缺失, 可以使用众数替代缺失的值.

代码语言:javascript
复制
print('按照登船地点分组 (C = Cherbourg, Q = Queenstown, S = Southampton):')
print(df['embarked'].value_counts())
sns.countplot(x='embarked', data=df, palette='Set2')
plt.show()
代码语言:javascript
复制
按照登船地点分组 (C = Cherbourg, Q = Queenstown, S = Southampton):
S    914
C    270
Q    123
Name: embarked, dtype: int64

在这里插入图片描述

代码语言:javascript
复制
print('乘客登船地点的众数为 %s.' %df['embarked'].value_counts().idxmax())
代码语言:javascript
复制
乘客登船地点的众数为 S.

由于大多数人是在南安普顿(Southhampton)登船, 可以使用“S”替代缺失的数据值

2.4. 根据缺失数据情况调整数据

基于以上分析, 我们进行如下调整:

  • 如果一条数据的 "Age" 缺失, 使用年龄的中位数 28 替代.
  • 如果一条数据的 "Embarked" 缺失, 使用登船地点的众数 “S” 替代.
  • 由于太多乘客的 “Cabin” 数据缺失, 从所有数据中丢弃这个特征的值.
代码语言:javascript
复制
data = df.copy()
data["age"].fillna(df["age"].median(skipna=True), inplace=True)
data["embarked"].fillna(df['embarked'].value_counts().idxmax(), inplace=True)
data.drop('cabin', axis=1, inplace=True)
代码语言:javascript
复制
# 确认数据是否还包含缺失数据
data.isnull().sum()
代码语言:javascript
复制
pclass      1
survived    1
name        1
sex         1
age         0
sibsp       1
parch       1
ticket      1
fare        2
embarked    0
dtype: int64
代码语言:javascript
复制
#处理仍然存在缺失数据的情况
final.dropna(inplace=True)
代码语言:javascript
复制
# 预览调整过的数据
data.head()

查看年龄在调整前后的分布
代码语言:javascript
复制
plt.figure(figsize=(15,8))
ax = df["age"].hist(bins=15, normed=True, stacked=True, color='teal', alpha=0.6)
df["age"].plot(kind='density', color='teal')
ax = data["age"].hist(bins=15, normed=True, stacked=True, color='orange', alpha=0.5)
data["age"].plot(kind='density', color='orange')
ax.legend(['Raw Age', 'Adjusted Age'])
ax.set(xlabel='Age')
plt.xlim(-10,85)
plt.show()

在这里插入图片描述

[

2.4.1. 其它特征的处理

数据中的两个特征 “sibsp” (一同登船的兄弟姐妹或者配偶数量)与“parch”(一同登船的父母或子女数量)都是代表是否有同伴同行. 为了预防这两个特征具有多重共线性, 我们可以将这两个变量转为一个变量 “TravelAlone” (是否独自一人成行)

注: 多重共线性(multicollinearity)是指多变量线性回归中,变量之间由于存在高度相关关系而使回归估计不准确。比如虚拟变量陷阱(英语:Dummy variable trap)即有可能触发多重共线性问题。

代码语言:javascript
复制
## 创建一个新的变量'TravelAlone'记录是否独自成行, 丢弃“sibsp” (一同登船的兄弟姐妹或者配偶数量)与“parch”(一同登船的父母或子女数量)
data['TravelAlone']=np.where((data["sibsp"]+data["parch"])>0, 0, 1)
data.drop('sibsp', axis=1, inplace=True)
data.drop('parch', axis=1, inplace=True)

对类别变量(categorical variables)使用独热编码(One-Hot Encoding), 将字符串类别转换为数值

代码语言:javascript
复制
# 对 Embarked","Sex"进行独热编码, 丢弃 'name', 'ticket'
final =pd.get_dummies(data, columns=["embarked","sex"])
final.drop('name', axis=1, inplace=True)
final.drop('ticket', axis=1, inplace=True)

final.head()

3. 数据分析

3.1. 年龄
代码语言:javascript
复制
plt.figure(figsize=(15,8))
ax = sns.kdeplot(final["age"][final.survived == 1], color="darkturquoise", shade=True)
sns.kdeplot(final["age"][final.survived == 0], color="lightcoral", shade=True)
plt.legend(['Survived', 'Died'])
plt.title('Density Plot of Age for Surviving Population and Deceased Population')
ax.set(xlabel='Age')
plt.xlim(-10,85)
plt.show()

在这里插入图片描述

生还与遇难群体的分布相似, 唯一大的区别是生还群体中用一部分低年龄的乘客. 说明当时的人预先保留了孩子的生还机会.
3.2. 票价
代码语言:javascript
复制
plt.figure(figsize=(15,8))
ax = sns.kdeplot(final["fare"][final.survived == 1], color="darkturquoise", shade=True)
sns.kdeplot(final["fare"][final.survived == 0], color="lightcoral", shade=True)
plt.legend(['Survived', 'Died'])
plt.title('Density Plot of Fare for Surviving Population and Deceased Population')
ax.set(xlabel='Fare')
plt.xlim(-20,200)
plt.show()

在这里插入图片描述

生还与遇难群体的票价分布差异比较大, 说明这个特征对预测乘客是否生还非常重要. 票价和仓位相关, 也许是仓位影响了逃生的效果, 我们接下来看仓位的分析.

3.3. 仓位
代码语言:javascript
复制
sns.barplot('pclass', 'survived', data=df, color="darkturquoise")
plt.show()

在这里插入图片描述 如我们所料, 一等舱的乘客生还几率最高.

3.4. 登船地点
代码语言:javascript
复制
sns.barplot('embarked', 'survived', data=df, color="teal")
plt.show()

在这里插入图片描述

从法国 Cherbourge 登录的乘客生还率最高

3.5. 是否独自成行
代码语言:javascript
复制
sns.barplot('TravelAlone', 'survived', data=final, color="mediumturquoise")
plt.show()

在这里插入图片描述

独自成行的乘客生还率比较低. 当时的年代, 大多数独自成行的乘客为男性居多.

3.6. 性别
代码语言:javascript
复制
sns.barplot('sex', 'survived', data=df, color="aquamarine")
plt.show()

在这里插入图片描述 很明显, 女性的生还率比较高

4. 使用Logistic Regression做预测

代码语言:javascript
复制
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

# 使用如下特征做预测
cols = ["age","fare","TravelAlone","pclass","embarked_C","embarked_S","sex_male"] 

# 创建 X (特征) 和 y (类别标签)
X = final[cols]
y = final['survived']

# 将 X 和 y 分为两个部分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=2)



# 训练模型,  

model = LogisticRegression()
model.fit(X_train,y_train.values.reshape(-1,1))
# 根据模型, 以 X_test 为输入, 生成变量 y_pred
print('Train/Test split results:')
y_pred = model.predict(X_test)
print("准确率为 %2.3f" % accuracy_score(y_test, y_pred))

Train/Test split results: 准确率为 0.817

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-09-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小刘IT教程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是逻辑回归
  • 逻辑回归与线性回归的关系
  • 德国信用卡欺诈数据集
  • 预测Titanic乘客是否生还
    • 来源kaggle
      • 1. 导入工具库和数据
        • 2. 查看缺失数据
          • 2.1. 年龄
            • 2.2. 仓位
              • 2.3. 登船地点
                • 2.4. 根据缺失数据情况调整数据
                  • 查看年龄在调整前后的分布
                    • 2.4.1. 其它特征的处理
                    • 3. 数据分析
                      • 3.1. 年龄
                        • 生还与遇难群体的分布相似, 唯一大的区别是生还群体中用一部分低年龄的乘客. 说明当时的人预先保留了孩子的生还机会.
                      • 3.2. 票价
                        • 3.3. 仓位
                          • 3.4. 登船地点
                            • 3.5. 是否独自成行
                              • 3.6. 性别
                              • 4. 使用Logistic Regression做预测
                              领券
                              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档