# 第一课: 线性回归分析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))
# 第五课与泰坦尼克号数据进行逻辑回归练习#
# # 用泰坦尼克数据进行逻辑回归练习 # ## 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)未经允许不得转载:同乐学堂 » Python数据分析实战3