快乐学习
前程无忧、中华英才非你莫属!

Python数据分析实战3

第一课: 线性回归分析bikes数据

# 读取数据并将日期时间设置为索引
import pandas as pd
url = 'https://raw.githubusercontent.com/justmarkham/DAT8/master/data/bikeshare.csv';;
bikes = pd.read_csv(url, index_col='datetime', parse_dates=True)
bikes.head()

# **问题:**
#  - 每个观察代表什么?
#  - 什么是响应变量(由Kaggle定义)?
#  - 有多少功能?
# #“count”是一种方法,所以最好把这个列命名为别的

bikes.rename(columns={'count':'total'}, inplace=True)

# ## 可视化数据

import seaborn as sns
import matplotlib.pyplot as plt
plt.rcParams['figure.figsize'] = (8, 6)
plt.rcParams['font.size'] = 14

# 大熊猫散点图
bikes.plot(kind='scatter', x='temp', y='total', alpha=0.2)

# Seaborn散点图与回归线
sns.lmplot(x='temp', y='total', data=bikes, aspect=1.5, scatter_kws={'alpha':0.2})

##线性回归的形式:$y = \beta_0 + \beta_1x_1 + \beta_2x_2 + ... + \beta_nx_n$

# - $ y $是回应
# - $ \ beta_0 $是拦截
# - $ \ beta_1 $是$ x_1 $的系数(第一项功能)
# - $ \ beta_n $是$ x_n $的系数(第n个特征)
#$ $ beta $值被称为**模型系数**:

# - 在模型拟合过程中使用**最小平方标准**估计(或“学习”)这些值。
# - 具体来说,我们找到最小化**平方残差**(或“平方误差之和”)的线(数学)。
# - 一旦我们学习了这些系数,我们可以使用模型来预测响应

#创建X和Y.
feature_cols = ['temp']
X = bikes[feature_cols]
y = bikes.total

# 导入,实例化,拟合
from sklearn.linear_model import LinearRegression
linreg = LinearRegression()
linreg.fit(X, y)

#打印系数
print linreg.intercept_
print linreg.coef_

# 解释**拦截**($ \ beta_0 $):
#  - 当$ x $ = 0时,它是$ y $的值。
#  - 因此,当温度为0摄氏度时,这是预计的租金数量。
#  - **注意:**解释截取并不总是有意义的。 (为什么?)
# 解读**“临时”系数**($ \ beta_1 $):
#  - $ y $的变化除以$ x $的变化,或“斜率”。
#  - 因此,1摄氏度的温度升高**与9.17辆自行车的租金增加相关**。
#  - 这不是一个因果关系的陈述。
#  - $ \ beta_1 $如果温度上升与租金下降**相关,则**为负**。

# ###使用模型进行预测
# #如果温度是25摄氏度,我们可以预测多少辆自行车出租?

# 手动计算预测
linreg.intercept_ + linreg.coef_*25

# 使用预测方法
linreg.predict(25)

# ##功能的规模是否重要?
# 假设温度是用华氏度来衡量的,而不是摄氏度。 这将如何影响模型?
# 为华氏温度创建一个新的列
bikes['temp_F'] = bikes.temp * 1.8 + 32
bikes.head()

# Seaborn散点图与回归线
sns.lmplot(x='temp_F', y='total', data=bikes, aspect=1.5, scatter_kws={'alpha':0.2})

# 创建X和Y.
feature_cols = ['temp_F']
X = bikes[feature_cols]
y = bikes.total

# 实例化和拟合
linreg = LinearRegression()
linreg.fit(X, y)

# 打印系数
print linreg.intercept_
print linreg.coef_

# 将华氏温度转换成华氏25度
25 * 1.8 + 32

# 预测租金为华氏77度
linreg.predict(77)

# **结论:**线性回归模型的特征尺度是**不相关**。 在改变比例尺的时候,我们只是简单的改变**系数的**解释。
# 删除temp_F列
bikes.drop('temp_F', axis=1, inplace=True)

# 探索更多功能
feature_cols = ['temp', 'season', 'weather', 'humidity']

#在Seaborn多个散点图
sns.pairplot(bikes, x_vars=feature_cols, y_vars='total', kind='reg')

# 熊猫中的多个散点图
fig, axs = plt.subplots(1, len(feature_cols), sharey=True)
for index, feature in enumerate(feature_cols):
    bikes.plot(kind='scatter', x=feature, y='total', ax=axs[index], figsize=(16, 3))

# 你有没有看到你没有想到的事情?

# 季节和月份的交叉列表
pd.crosstab(bikes.season, bikes.index.month)

# 方块租金,按季节分组
bikes.boxplot(column='total', by='season')

# 值得注意的是:
#  - 行不能捕获非线性关系。
#  - 冬天有更多的租金比春天(?)
bikes.total.plot()

# 这告诉我们什么?
# 冬天比春天有更多的租金,但仅仅是因为系统正在经历**整体增长**而冬季月份恰好在春季之后。
# 相关矩阵(范围从1到-1)
bikes.corr()#计算列的成对相关性,不包括NA /空值

# 使用热图可视化Seaborn中的相关矩阵
sns.heatmap(bikes.corr())

# 你注意到了什么关系?
# ##为模型添加更多功能
# 创建一个功能列表

feature_cols = ['temp', 'season', 'weather', 'humidity']

# 创建X和Y.
X = bikes[feature_cols]
y = bikes.total

# 实例化和拟合
linreg = LinearRegression()
linreg.fit(X, y)

# 打印系数
print linreg.intercept_
print linreg.coef_

# 将要素名称与系数配对
zip(feature_cols, linreg.coef_)

# #解读系数:
#  - 固定所有其他功能,**温度增加1个单位**与**租赁增加7.86个自行车相关**。
#  - 固定所有其他功能,在**季节增加1个单位**与**租赁增加22.5个自行车相关**。
#  - 固定所有其他功能,**天气增加1个单位**与**租金增加6.67个自行车相关**。
#  - 固定所有其他功能,**湿度增加1个单位**与**减少3.12个自行车** **相关。

# 有什么看起来不正确?
###功能选择
# 我们如何选择模型中包含哪些功能?我们将要使用** train / test split **(最终**交叉验证**)。

# 为什么不使用** p值**或** R平方**来进行特征选择?
#  - 线性模型依赖**很多假设**(如特征是独立的),如果违反这些假设,则p值和R平方不太可靠。训练/测试分割依赖于较少的假设。
#  - 与响应无关的特征仍然可以具有**显着的p值**。
#  - 向你的模型添加与响应无关的特征将总是**增加R平方值**,而调整后的R平方不能充分解释这一点。

# 对于我们的泛化目标,P值和R平方是**代理**,而列车/测试分割和交叉验证尝试**直接估计**模型将如何推广到样本外数据。
#  更普遍:
#  - 有不同的方法可以用来解决任何给定的数据科学问题,本课程遵循**机器学习方法**。
#  - 本课程重点讨论**通用方法**,可以应用于任何模型,而不是模型特定的方法。

###回归问题的评估指标
# 分类问题的评估指标,如**准确性**,对回归问题没有用处。我们需要评估指标来比较**连续值**。
# 下面是回归问题的三个常见评估指标:
# **平均绝对误差**(MAE)是误差绝对值的平均值:
# $$ \ frac 1n \ sum_ {i = 1} ^ n | y_i- \ hat {y} _i | $$
# **均方误差**(MSE)是平方误差的均值:
# $$ \ frac 1n \ sum_ {i = 1} ^ n(y_i- \ hat {y} _i)^ 2 $$
# **均方根误差**(RMSE)是平方误差平均值的平方根:

# #$$ \ sqrt {\ frac 1n \ sum_ {i = 1} ^ n(y_i- \ hat {y} _i)^ 2} $$
#
# #示例真实和预测的响应值
true = [10, 7, 5, 5]
pred = [8, 6, 5, 10]

# 手工计算这些指标!
from sklearn import metrics
import numpy as np
print 'MAE:', metrics.mean_absolute_error(true, pred)
print 'MSE:', metrics.mean_squared_error(true, pred)
print 'RMSE:', np.sqrt(metrics.mean_squared_error(true, pred))

# 比较这些指标:
#  - ** MAE **是最容易理解的,因为这是平均误差。
#  - ** MSE **比MAE更受欢迎,因为MSE“惩罚”更大的错误,这在现实世界中往往是有用的。
#  - ** RMSE **比MSE更受欢迎,因为RMSE可以用“y”单位来解释。
# 所有这些都是**损失函数**,因为我们想要最小化它们。
# 这是另一个示例,演示MSE / RMSE如何惩罚更大的错误:
# 与上面相同的真值

true = [10, 7, 5, 5]

# 新的一组预测值
pred = [10, 7, 5, 13]

# MAE和以前一样
print 'MAE:', metrics.mean_absolute_error(true, pred)

# MSE和RMSE比以前更大
print 'MSE:', metrics.mean_squared_error(true, pred)
print 'RMSE:', np.sqrt(metrics.mean_squared_error(true, pred))

# ##将模型与训练/测试分离和RMSE进行比较

from sklearn.cross_validation import train_test_split

# 定义一个接受功能列表并返回测试RMSE的函数
def train_test_rmse(feature_cols):
    X = bikes[feature_cols]
    y = bikes.total
    X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=123)
    linreg = LinearRegression()
    linreg.fit(X_train, y_train)
    y_pred = linreg.predict(X_test)
    return np.sqrt(metrics.mean_squared_error(y_test, y_pred))

# 比较不同的功能集
print train_test_rmse(['temp', 'season', 'weather', 'humidity'])
print train_test_rmse(['temp', 'season', 'weather'])
print train_test_rmse(['temp', 'season', 'humidity'])

# 使用这些功能是不允许的!
print train_test_rmse(['casual', 'registered'])

# ##比较测试RMSE和空RMSE
# 无效RMSE是可以通过总是预测平均响应值**来实现的RMSE。 这是您可能想要衡量您的回归模型的基准。
# 把X和Y分成训练和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=123)

# 创建一个与y_test形状相同的NumPy数组
y_null = np.zeros_like(y_test, dtype=float)

# 用y_test的平均值填充数组
y_null.fill(y_test.mean())
y_null

# 计算空值RMSE
np.sqrt(metrics.mean_squared_error(y_test, y_null))

###处理分类特征
# scikit-learn期望所有功能都是数字。 那么我们如何在模型中包含分类特征呢?
#  - **有序类别:**将它们转换为合理的数值(例如:small = 1,medium = 2,large = 3)
#  - **无序的类别:**使用虚拟编码(0/1)
#数据集中的分类特征是什么?
#  - **有序类别:**天气(已经用合理的数值编码)
#  - **无序类别:**季节(需要虚拟编码),节假日(已经虚拟编码),工作日(已经虚拟编码)
# 对于季节,我们不能简单地将编码保留为1 =春天,2 =夏天,3 =秋天,4 =冬天,因为那意味着**有序的关系**。
# 相反,我们创建**多个虚拟变量:**

# 创建虚拟变量
season_dummies = pd.get_dummies(bikes.season, prefix='season')

# 打印5个随机行
season_dummies.sample(n=5, random_state=1)

# 但是,我们实际上只需要**三个虚拟变量(而不是四个)**,因此我们将放弃第一个虚拟变量。
# 为什么? 因为三个假人捕捉了关于季节特征的所有“信息”,并且隐含地将春季(季节1)定义为**基线水平:**
# #放下第一列
season_dummies.drop(season_dummies.columns[0], axis=1, inplace=True)

#打印5个随机行
season_dummies.sample(n=5, random_state=1)

# 一般来说,如果您有** k个可能值**的分类特征,则可以创建** k-1个虚拟变量**。
#如果这是令人困惑的,那么考虑一下为什么我们只需要一个虚拟变量来放假,而不是两个虚拟变量(holiday_yes和holiday_no)。
# #连接原始DataFrame和虚拟DataFrame(axis = 0表示行,axis = 1表示列)
bikes = pd.concat([bikes, season_dummies], axis=1)

# 打印5个随机行
bikes.sample(n=5, random_state=1)

# 在模型中包含季节的虚拟变量
feature_cols = ['temp', 'season_2', 'season_3', 'season_4', 'humidity']
X = bikes[feature_cols]
y = bikes.total
linreg = LinearRegression()
linreg.fit(X, y)
zip(feature_cols, linreg.coef_)

# 我们如何解读季节系数? 他们是**相对于基线(春季)**测量的:
#  - 保持所有其他功能固定,**夏季**与**租金减少3.39辆自行车**相比,春天。
#  - 保持所有其他功能固定,**下降**与租金减少41.7辆自行车**相比,春天。
#  - 保持所有其他功能固定,**冬季**与64.4辆自行车**相比,春季出租增加**。
# 如果我们改变哪个赛季被定义为基线,这会有影响吗?
# - 不,它只会改变我们**系数的解释。
# **重要:**虚拟编码与所有机器学习模型相关,而不仅仅是线性回归模型。
# 比较原始季节变量与虚拟变量
print train_test_rmse(['temp', 'season', 'humidity'])
print train_test_rmse(['temp', 'season_2', 'season_3', 'season_4', 'humidity'])

# ##特征工程
#看看你是否可以创建以下功能:
#  - **小时:**作为单个数字功能(0到23)
#  - **小时:**作为分类特征(使用23个虚拟变量)
# - **白天:**作为单个分类特征(白天=上午7点到晚上8点,否则白天= 0)
# 然后,尝试使用`train_test_rmse`三个功能中的每一个(用它自己)来看哪一个功能最好!
# 小时作为数字功能
bikes['hour'] = bikes.index.hour

# 小时作为分类特征
hour_dummies = pd.get_dummies(bikes.hour, prefix='hour')
hour_dummies.drop(hour_dummies.columns[0], axis=1, inplace=True)
bikes = pd.concat([bikes, hour_dummies], axis=1)

# 白天作为一个明确的特征
bikes['daytime'] = ((bikes.hour > 6) & (bikes.hour < 21)).astype(int)

print train_test_rmse(['hour'])
print train_test_rmse(bikes.columns[bikes.columns.str.startswith('hour_')])
print train_test_rmse(['daytime'])

# ##比较线性回归与其他模型
# 线性回归的优点:
#  - 简单解释
#  - 高度可解释的
#  - 模型训练和预测是快速的
#  - 不需要调整(不包括正规化)
#  - 功能不需要缩放
#  - 可以在少量的观察中表现良好
#  - 完全了解

# 线性回归的缺点:
#  - 设定功能和响应之间的线性关系
#  - 由于高偏见,表现(通常)与最好的监督式学习方法没有竞争力

第二课 用Yelp投票线性回归作业

# 介绍
# 此作业使用Kaggle的[Yelp Business Rating Prediction](https://www.kaggle.com/c/yelp-recsys-2013)竞赛中的一小部分数据。

#  - 此数据集中的每个观察结果都是特定用户对特定业务的评论。
#  - “星号”列是审阅者分配给企业的星号(1到5)。 (更高的星星更好。)换句话说,这是撰写评论的人的业务评级。
#  - “酷”栏是本评论从其他Yelp用户收到的“酷”票数。
# 所有的评论都是从0票“冷静”开始的,评论可以获得多少“酷”的票数是没有限制的。
# 换句话说,这是对评论本身的评价,而不是对评论的评价。
#  - “有用”和“有趣”列与“酷”栏相似。

# 将`yelp.csv`读入DataFrame。
# 使用相对路径访问yelp.csv

import pandas as pd
yelp = pd.read_csv('yelp.csv')
yelp.head(1)

###任务1(奖金)
# 忽略`yelp.csv`文件,并从`yelp.json`自己构建这个DataFrame。
# 这包括将数据读入Python,解码JSON,将其转换为DataFrame,并为每个投票类型添加单独的列。
# 从yelp.json读取数据到行列表中
# 使用json.loads()将每行解码成字典
import json
with open('yelp.json', 'rU') as f:
    data = [json.loads(row) for row in f]

# 显示第一个评论
data[0]

# 将字典列表转换为DataFrame
yelp = pd.DataFrame(data)
yelp.head(1)

#添加DataFrame列以获得很酷,有用和有趣的内容
yelp['cool'] = [row['votes']['cool'] for row in data]
yelp['useful'] = [row['votes']['useful'] for row in data]
yelp['funny'] = [row['votes']['funny'] for row in data]

#放弃选票栏
yelp.drop('votes', axis=1, inplace=True)
yelp.head(1)

# ###任务2
#探索每种投票类型(酷/有用/有趣)和星星数量之间的关系。
#把星星当成一个分类变量,寻找组间的差异
yelp.groupby('stars').mean()

#相关矩阵
import seaborn as sns
sns.heatmap(yelp.corr())

# 多个散点图
sns.pairplot(yelp, x_vars=['cool', 'useful', 'funny'], y_vars='stars', size=6, aspect=0.7, kind='reg')

# ## Task 3
#
# 定义酷/有用/有趣的功能,明星作为响应。

feature_cols = ['cool', 'useful', 'funny']
X = yelp[feature_cols]
y = yelp.stars

# ## Task 4
#
# 拟合线性回归模型并解释系数。 这些系数对你来说有直觉意义吗? 浏览Yelp网站,查看是否检测到类似的趋势。
from sklearn.linear_model import LinearRegression
linreg = LinearRegression()
linreg.fit(X, y)
zip(feature_cols, linreg.coef_)

# ## Task 5
#
# 通过将模型分解为训练集和测试集并计算RMSE来评估模型。 RMSE是否对你有直觉意义?
from sklearn.cross_validation import train_test_split
from sklearn import metrics
import numpy as np

# 定义一个接受功能列表并返回测试RMSE的函数

# 做回归分析,常用的误差主要有均方误差根(RMSE)和R-平方(R2)。
# RMSE是预测值与真实值的误差平方根的均值
# R2方法是将预测值跟只使用均值的情况下相比,看能好多少

def train_test_rmse(feature_cols):
    X = yelp[feature_cols]
    y = yelp.stars
    X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1)
    linreg = LinearRegression()
    linreg.fit(X_train, y_train)
    y_pred = linreg.predict(X_test)
    return np.sqrt(metrics.mean_squared_error(y_test, y_pred))

# 用所有三个特征计算RMSE
train_test_rmse(['cool', 'useful', 'funny'])

# ## Task 6
#
# 尝试删除一些功能,看看RMSE是否改善。

print train_test_rmse(['cool', 'useful'])
print train_test_rmse(['cool', 'funny'])
print train_test_rmse(['useful', 'funny'])

# ## Task 7 (Bonus)
#
# 思考一下可以从现有数据创建的一些新功能,这些功能可以预测响应。
# 找出如何在Pandas中创建这些功能,将它们添加到您的模型中,并查看RMSE是否得到改善。
# 新功能:评论长度(字符数)
yelp['length'] = yelp.text.apply(len)

# 新功能:评论是否包含“爱”或“讨厌”
yelp['love'] = yelp.text.str.contains('love', case=False).astype(int)
yelp['hate'] = yelp.text.str.contains('hate', case=False).astype(int)

# 为模型添加新功能并计算RMSE
train_test_rmse(['cool', 'useful', 'funny', 'length', 'love', 'hate'])

# ## Task 8 (Bonus)
#
# 把你最好的RMSE和测试集合中的RMSE比较为“空模型”,这是忽略所有特征的模型,并简单地预测测试集合中的平均响应值。

#分割数据(在函数之外)
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1)

# 创建一个与y_test形状相同的NumPy数组
y_null = np.zeros_like(y_test, dtype=float)
# 用y_test的均值填充数组
y_null.fill(y_test.mean())
# 计算零均方根误差
print np.sqrt(metrics.mean_squared_error(y_test, y_null))

# ## Task 9 (Bonus)
#
#不要把它看作是一个回归问题,而应该把它看作一个分类问题,看看用KNN可以达到什么样的测试精度。
#导入并实例化KNN
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=50)

# 分类模型将自动将响应值(1/2/3/4/5)视为无序类别knn.fit(X_train, y_train)
knn.fit(X_train, y_train)
y_pred_class = knn.predict(X_test)
print metrics.accuracy_score(y_test, y_pred_class)

# ## Task 10 (Bonus)
# 找出如何使用线性回归进行分类,并将其分类精度与KNN的准确度进行比较。

# 使用线性回归进行连续预测
linreg = LinearRegression()
linreg.fit(X_train, y_train)
y_pred = linreg.predict(X_test)

# 将其预测整理为最接近的整数
y_pred_class = y_pred.round()

# 计算舍入预测的分类准确度
print metrics.accuracy_score(y_test, y_pred_class)

第三课:指数函数和对数

import math
import numpy as np

# ## 指数函数

# 什么是** e **? 这只是一个数字(被称为欧拉数):

math.e

#** e **是一个重要的数字,因为它是所有持续增长的流程共享的基础增长率。
#例如,如果我有** 10美元**,而且在1年内增长100%(持续复利),我会以** 10 \ * e ^ 1美元结束**:

# 1年增长100%
10 * np.exp(1)
# 100%增长2年
10 * np.exp(2)

#注意:当e上升到一个幂时,它被称为**指数函数**。
# 从技术上讲,任何数字都可以作为基数,它仍然被称为**指数函数**(如2 ^ 5)。
# 但是在我们的情况下,指数函数的基础被假定为e。
#无论如何,如果我只有20%的增长,而不是100%的增长呢?

# 1年增长20%
10 * np.exp(0.20)
# 2年增长20%
10 * np.exp(0.20 * 2)

###对数
#(自然对数)**是什么? 它给你所需的时间达到一定的增长水平。
# 例如,如果我想增长2.718倍,则需要1个单位的时间(假设增长率为100%):
#需要增加1个单位到2.718个单位

np.log(2.718)

#如果我要增长7.389倍,那么我需要2个单位的时间:
# 需要增加1个单位到7.389个单位
np.log(7.389)

# 如果我想要增长1倍,它会花费我0个单位的时间:
# 需要将1个单位增加到1个单位的时间
np.log(1)

#如果我想要增长0.5倍,它将花费我-0.693个单位的时间(这就像是在回顾时间):
#需要增加1个单位到0.5个单位
np.log(0.5)

##连接概念
#正如你所看到的那样,指数函数和自然对数是**反转**:

np.log(np.exp(5))
np.exp(np.log(5))

第四课、 Logistic回归

#--logistic回归又称logistic回归分析,是一种广义的线性回归分析模型,常用于数据挖掘,疾病自动诊断,经济预测等领域

# ## Part 1: 预测连续响应

# 玻璃鉴定数据集
import pandas as pd
url = 'http://archive.ics.uci.edu/ml/machine-learning-databases/glass/glass.data';;
col_names = ['id','ri','na','mg','al','si','k','ca','ba','fe','glass_type']
glass = pd.read_csv(url, names=col_names, index_col='id')
glass.sort_values('al', inplace=True)
glass.head()

# **问题:**假装我们要预测** ri **,而我们唯一的特征是** al **。 我们怎么能使用机器学习呢?
# **答案:**我们可以将其作为一个回归问题,并使用** al **作为唯一特征和** ri **作为响应的线性回归模型。

# **问题:**我们如何将**这个模型可视化?
# **答案:**用x轴上的** al **和y轴上的** ri **创建一个散点图,并画出最适合的线。

import seaborn as sns
import matplotlib.pyplot as plt
sns.set(font_scale=1.5)

sns.lmplot(x='al', y='ri', data=glass, ci=None)

#**问题:**我们如何在不使用Seaborn的情况下画出这个情节?

# 散点图使用熊猫
glass.plot(kind='scatter', x='al', y='ri')

# 使用Matplotlib的等效散点图
plt.scatter(glass.al, glass.ri)
plt.xlabel('al')
plt.ylabel('ri')

# 拟合线性回归模型
from sklearn.linear_model import LinearRegression
linreg = LinearRegression()
feature_cols = ['al']
X = glass[feature_cols]
y = glass.ri
linreg.fit(X, y)

# 预测X的所有值
glass['ri_pred'] = linreg.predict(X)
glass['ri_pred'].head()

# 绘制一条线连接的预测
plt.plot(glass.al, glass.ri_pred, color='red')
plt.xlabel('al')
plt.ylabel('Predicted ri')

# 把这些情节放在一起
plt.scatter(glass.al, glass.ri)
plt.plot(glass.al, glass.ri_pred, color='red')
plt.xlabel('al')
plt.ylabel('ri')

###进修:解释线性回归系数

#线性回归方程:$ y = \ beta_0 + \ beta_1x $

#使用公式计算al = 2的预测

linreg.intercept_ + linreg.coef_ * 2

# 使用预测方法计算al = 2的预测
linreg.predict(2)

# 检查系数
zip(feature_cols, linreg.coef_)

#**解释:**'al'增加1个单位与'ri'减少0.0025个单位相关。

#将al加1(使得al = 3)将ri减小0.0025
1.51699012 - 0.0024776063874696243

# 使用预测方法计算对于al = 3的预测
linreg.predict(3)

##第2部分:预测分类响应

#检查glass_type
glass.glass_type.value_counts().sort_index()

#1,2,3是窗户玻璃
#5,6,7型是家用玻璃
glass['household'] = glass.glass_type.map({1:0, 2:0, 3:0, 5:1, 6:1, 7:1})
glass.head()

# #让我们改变我们的任务,以便我们使用** al **预测**家庭**。 让我们通过可视化的关系找出如何做到这一点:
plt.scatter(glass.al, glass.household)
plt.xlabel('al')
plt.ylabel('household')

# 让我们画一条**回归线**,就像我们之前做的那样:

# 拟合线性回归模型并存储预测
feature_cols = ['al']
X = glass[feature_cols]
y = glass.household
linreg.fit(X, y)
glass['household_pred'] = linreg.predict(X)

#包含回归线的散点图
plt.scatter(glass.al, glass.household)
plt.plot(glass.al, glass.household_pred, color='red')
plt.xlabel('al')
plt.ylabel('household')

#如果** al = 3 **,我们预测哪一类家庭?****1
#如果** al = 1.5 **,我们预测什么样的家庭类?**0**
#我们预测了al的** lower **值的0类,以及al的** higher **值的1个类。
#我们的截止值是多少? 在** al = 2 **附近,因为这是线性回归线跨越预测0级和1级之间的中点的地方。

#因此,如果** household_pred> = 0.5 **,我们预测** 1 **类,否则我们预测** 0 **类。

#理解np.where
import numpy as np
nums = np.array([5, 15, 8])

# 如果条件为True,则np.where返回第一个值,如果条件为False,则返回第二个值
np.where(nums > 10, 'big', 'small')

# 将household_pred转换为1或0
glass['household_pred_class'] = np.where(glass.household_pred >= 0.5, 1, 0)
glass.head()

# 绘制类别预测
plt.scatter(glass.al, glass.household)
plt.plot(glass.al, glass.household_pred_class, color='red')
plt.xlabel('al')
plt.ylabel('household')

###第三部分:使用Logistic回归
#逻辑回归可以做我们刚刚做的事情:

#适合逻辑回归模型并存储类别预测
from sklearn.linear_model import LogisticRegression
logreg = LogisticRegression(C=1e9)
feature_cols = ['al']
X = glass[feature_cols]
y = glass.household
logreg.fit(X, y)
glass['household_pred_class'] = logreg.predict(X)

# 绘制类别预测
plt.scatter(glass.al, glass.household)
plt.plot(glass.al, glass.household_pred_class, color='red')
plt.xlabel('al')
plt.ylabel('household')

#如果我们想要**预测概率**,而不是仅仅**类预测**,那么理解我们在给定预测中有多自信?

#存储第1类的预测概率
glass['household_pred_prob'] = logreg.predict_proba(X)[:, 1]

# 绘制预测概率
plt.scatter(glass.al, glass.household)
plt.plot(glass.al, glass.household_pred_prob, color='red')
plt.xlabel('al')
plt.ylabel('household')

# 检查一些示例预测
print logreg.predict_proba(1)
print logreg.predict_proba(2)
print logreg.predict_proba(3)

###第4部分:概率,赔率,电子,日志,对数

# 创建一个概率与赔率的表
table = pd.DataFrame({'probability':[0.1, 0.2, 0.25, 0.5, 0.6, 0.8, 0.9]})
table['odds'] = table.probability/(1 - table.probability)
table

#什么是** e **? 这是所有持续增长的进程共享的基本增长率:

#指数函数:e ^ 1
np.exp(1)

#什么是**(自然)日志**? 它给你所需的时间达到一定的增长水平:

#需要增加1个单位到2.718个单位
np.log(2.718)

# 这也是指数函数的**反**。

np.log(np.exp(5))

# 添加日志赔率到表中
table['logodds'] = np.log(table.odds)
table

# ## ###第五部分:什么是Logistic回归?

# **线性回归:**连续响应被建模为这些特征的线性组合:
#
# $$y = \beta_0 + \beta_1x$$
#
# 逻辑回归:**分类回答为“真”(1)的对数可能性被建模为这些特征的线性组合#
# $$\log \left({p\over 1-p}\right) = \beta_0 + \beta_1x$$
#
# 这被称为** logit函数**。

###第六部分:解释Logistic回归系数
#再次绘制预测概率
plt.scatter(glass.al, glass.household)
plt.plot(glass.al, glass.household_pred_prob, color='red')
plt.xlabel('al')
plt.ylabel('household')

# 使用equ计算al = 2的预测对数
logodds = logreg.intercept_ + logreg.coef_[0] * 2
logodds

# 将对数赔率转换为赔率
odds = np.exp(logodds)
odds

# 赔率转换为概率
prob = odds/(1 + odds)
prob

# 使用predict_proba方法计算al = 2的预测概率
logreg.predict_proba(2)[:, 1]

#检查al的系数
zip(feature_cols, logreg.coef_[0])

#**解释:**“1”增加1个单位,与“家庭”的对数增加4.18个单位相关。
#增加1(这样al = 3)使对数增加4.18
logodds = 0.64722323 + 4.1804038614510901
odds = np.exp(logodds)
prob = odds/(1 + odds)
prob

# 使用predict_proba方法计算al = 3的预测概率
logreg.predict_proba(3)[:, 1]

#**底线:**正系数增加响应的对数(从而增加概率),负系数减少响应的对数(从而降低概率)。
#检查拦截
logreg.intercept_

#**解释:**对于“al”值为0,“家庭”的对数为-7.71。
#把log-odds转换成概率

logodds = logreg.intercept_
odds = np.exp(logodds)
prob = odds/(1 + odds)
prob

###第7部分:使用具有分类特征的Logistic回归

#逻辑回归仍然可以与**分类特征**一起使用。 让我们看看是什么样的:

#创建一个分类功能
glass['high_ba'] = np.where(glass.ba > 0.5, 1, 0)

#使用Seaborn绘制逻辑曲线:

#原创(连续)功能
sns.lmplot(x='ba', y='household', data=glass, ci=None, logistic=True)

# 分类特征
sns.lmplot(x='high_ba', y='household', data=glass, ci=None, logistic=True)

# 分类功能,添加了抖动
sns.lmplot(x='high_ba', y='household', data=glass, ci=None, logistic=True, x_jitter=0.05, y_jitter=0.05)

# 拟合逻辑回归模型
feature_cols = ['high_ba']
X = glass[feature_cols]
y = glass.household
logreg.fit(X, y)

# 检查high_ba的系数
zip(feature_cols, logreg.coef_[0])

###第八部分:比较Logistic回归与其他模型
# 逻辑回归的优点:
#  - 高度可解释的(如果你还记得的话)
#  - 模型训练和预测是快速的
#  - 不需要调整(不包括正规化)
#  - 功能不需要缩放
#  - 可以在少量的观察中表现良好
#  - 输出经过良好校准的预测概率

# 逻辑回归的缺点:
#  - 设定特征和响应的对数之间的线性关系
#  - 表现(通常)与最好的监督式学习方法没有竞争力
#  - 无法自动学习功能交互

第五课与泰坦尼克号数据进行逻辑回归练习

# # 用泰坦尼克数据进行逻辑回归练习

# ## Step 1: 将数据读入Pasnda

import pandas as pd
titanic = pd.read_csv('titanic.csv', index_col='PassengerId')
titanic.head()

# ## Step 2: 创建X和Y
#
# 定义** Pclass **和** Parch **作为特征,** Survived **作为响应。

feature_cols = ['Pclass', 'Parch']
X = titanic[feature_cols]
y = titanic.Survived

# ## Step 3: 将数据分解成训练和测试集。

from sklearn.cross_validation import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1)

# ## Step 4: 拟合逻辑回归模型并检查系数
#
# 确认系数具有直觉意义。

from sklearn.linear_model import LogisticRegression
logreg = LogisticRegression(C=1e9)
logreg.fit(X_train, y_train)
zip(feature_cols, logreg.coef_[0])

# ## Step 5: 对测试集进行预测并计算精度

# 类预测(不是预测概率)
y_pred_class = logreg.predict(X_test)

# 计算分类精度
from sklearn import metrics
print metrics.accuracy_score(y_test, y_pred_class)

# ## Step 6: 将您的测试准确性与零准确度进行比较

# 这个工程不管类的数量
y_test.value_counts().head(1) / len(y_test)

# 这只适用于编码为0/1的二进制分类问题
max(y_test.mean(), 1 - y_test.mean())

#泰坦尼克号预测的混淆矩阵#

#打印混淆矩阵
print metrics.confusion_matrix(y_test, y_pred_class)

#保存混淆矩阵并切片成四块
confusion = metrics.confusion_matrix(y_test, y_pred_class)
TP = confusion[1][1]
TN = confusion[0][0]
FP = confusion[0][1]
FN = confusion[1][0]

print 'True Positives:', TP
print 'True Negatives:', TN
print 'False Positives:', FP
print 'False Negatives:', FN

# 计算灵敏度
print TP / float(TP + FN)
print 44 / float(44 + 51)

#计算特异性
print TN / float(TN + FP)
print 105 / float(105 + 23)

# 存储预测的概率
y_pred_prob = logreg.predict_proba(X_test)[:, 1]

# 预测概率的直方图
import matplotlib.pyplot as plt
plt.hist(y_pred_prob)
plt.xlim(0, 1)
plt.xlabel('Predicted probability of survival')
plt.ylabel('Frequency')

# 通过降低预测生存的阈值来提高灵敏度
import numpy as np
y_pred_class = np.where(y_pred_prob > 0.3, 1, 0)

# 旧混淆矩阵
print confusion

# 新的混淆矩阵
print metrics.confusion_matrix(y_test, y_pred_class)

#新的灵敏度(比以前更高)
print 63 / float(63 + 32)

# 新的特异性(低于以前)
print 72 / float(72 + 56)
打赏
赞(0) 打赏
未经允许不得转载:同乐学堂 » Python数据分析实战3

特别的技术,给特别的你!

联系QQ:1071235258QQ群:710045715

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

error: Sorry,暂时内容不可复制!