第一课、*高级模型评估
# 第一部分:处理缺失值 import pandas as pd url = 'https://raw.githubusercontent.com/justmarkham/DAT8/master/data/titanic.csv';; titanic = pd.read_csv(url, index_col='PassengerId') titanic.shape # 检查缺少的值 titanic.isnull().sum() #一个可能的策略是**丢失缺失值**: #删除任何缺少值的行 titanic.dropna().shape # 删除年龄缺失的行 titanic[titanic.Age.notnull()].shape #有时候更好的策略是**推测缺失值**: # 平均年龄 titanic.Age.mean() #中年的 titanic.Age.median() # 最常见的年龄 titanic.Age.mode() # 填写年龄中位数的缺失值 titanic.Age.fillna(titanic.Age.median(), inplace=True) # ##第2部分:处理分类特征(复审) titanic.head(10) # 编码Sex_Female功能 titanic['Sex_Female'] = titanic.Sex.map({'male':0, 'female':1}) # 创建一个虚拟变量的数据框 embarked_dummies = pd.get_dummies(titanic.Embarked, prefix='Embarked') embarked_dummies.drop(embarked_dummies.columns[0], axis=1, inplace=True) # 连接原始DataFrame和虚拟DataFrame titanic = pd.concat([titanic, embarked_dummies], axis=1) titanic.head(1) # 定义X和y feature_cols = ['Pclass', 'Parch', 'Age', 'Sex_Female', 'Embarked_Q', 'Embarked_S'] X = titanic[feature_cols] y = titanic.Survived # train/test 分割 from sklearn.cross_validation import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1) # 训练逻辑回归模型 from sklearn.linear_model import LogisticRegression logreg = LogisticRegression(C=1e9) logreg.fit(X_train, y_train) # 对测试集进行预测 y_pred_class = logreg.predict(X_test) # 计算测试精度 from sklearn import metrics print metrics.accuracy_score(y_test, y_pred_class) # ## 第3部分:ROC曲线和AUC # 预测生存概率 y_pred_prob = logreg.predict_proba(X_test)[:, 1] import matplotlib.pyplot as plt plt.rcParams['figure.figsize'] = (8, 6) plt.rcParams['font.size'] = 14 # 绘制ROC曲线 # ROC曲线指受试者工作特征曲线 / 接收器操作特性曲线(receiver operating characteristic curve), \ # 是反映敏感性和特异性连续变量的综合指标,是用构图法揭示敏感性和特异性的相互关系, # 它通过将连续变量设定出多个不同的临界值,从而计算出一系列敏感性和特异性,再以敏感性为纵坐标、(1-特异性)为横坐标绘制成曲线, # 曲线下面积越大,诊断准确性越高。在ROC曲线上,最靠近坐标图左上方的点为敏感性和特异性均较高的临界值。 fpr, tpr, thresholds = metrics.roc_curve(y_test, y_pred_prob) plt.plot(fpr, tpr) plt.xlim([0.0, 1.0]) plt.ylim([0.0, 1.0]) plt.xlabel('False Positive Rate (1 - Specificity)') plt.ylabel('True Positive Rate (Sensitivity)') # 计算AUC # AUC(Area Under Curve)被定义为ROC曲线下的面积,显然这个面积的数值不会大于1。 # 又由于ROC曲线一般都处于y=x这条直线的上方,所以AUC的取值范围在0.5和1之间。 # 使用AUC值作为评价标准是因为很多时候ROC曲线并不能清晰的说明哪个分类器的效果更好,而作为一个数值,对应AUC更大的分类器效果更好。 print metrics.roc_auc_score(y_test, y_pred_prob) #除了允许您计算AUC之外,查看ROC曲线可以帮助您选择一个阈值,**以平衡灵敏度和特异性**的方式对特定上下文有意义。 #根据实际响应值分组的预测概率直方图 df = pd.DataFrame({'probability':y_pred_prob, 'actual':y_test}) df.hist(column='probability', by='actual', sharex=True, sharey=True) #如果您在绘制ROC曲线或计算AUC时使用了** y_pred_class **而不是** y_pred_prob **,会发生什么? # 使用y_pred_class的ROC曲线 - 错误! fpr, tpr, thresholds = metrics.roc_curve(y_test, y_pred_class) plt.plot(fpr, tpr) # AUC使用y_pred_class - 错误! print metrics.roc_auc_score(y_test, y_pred_class) #如果使用** y_pred_class **,它将把0和100解释为预测概率0%和100%。 ## ##奖金:ROC曲线只对预测概率的排名顺序敏 #打印前10个预测概率 y_pred_prob[:10] # 取预测概率的平方根(使它们全部变大) import numpy as np y_pred_prob_new = np.sqrt(y_pred_prob) # 打印修改后的预测概率 y_pred_prob_new[:10] # 预测概率的直方图已经改变 df = pd.DataFrame({'probability':y_pred_prob_new, 'actual':y_test}) df.hist(column='probability', by='actual', sharex=True, sharey=True) # ROC曲线没有改变 fpr, tpr, thresholds = metrics.roc_curve(y_test, y_pred_prob_new) plt.plot(fpr, tpr) #AUC没有改变 print metrics.roc_auc_score(y_test, y_pred_prob_new) ##第四部分:交叉验证 #计算交叉验证的AUC from sklearn.cross_validation import cross_val_score cross_val_score(logreg, X, y, cv=10, scoring='roc_auc').mean() # 添加票价模型 feature_cols = ['Pclass', 'Parch', 'Age', 'Sex_Female', 'Embarked_Q', 'Embarked_S', 'Fare'] X = titanic[feature_cols] # 重新计算AUC cross_val_score(logreg, X, y, cv=10, scoring='roc_auc').mean()
###第二课、交叉验证参数调整,模型选择和特征选择、
##目标:评估模型评估程序、需要一种在机器学习模型之间进行选择的方法 # 估计**样本外的数据的可能性能 from sklearn.datasets import load_iris from sklearn.cross_validation import train_test_split from sklearn.neighbors import KNeighborsClassifier from sklearn import metrics # 读入iris数据 iris = load_iris() # 创建X(特征)和Y(响应) X = iris.data y = iris.target # 使用train / test拆分不同的random_state值 # train_test_split是交叉验证中常用的函数,功能是从样本中随机的按比例选取train data和test data,形式为: # 参数代表含义: # train_data:所要划分的样本特征集 # train_target:所要划分的样本结果 # test_size:样本占比,如果是整数的话就是样本的数量 # random_state:是随机数的种子。 X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=4) #用K = 5检查KNN的分类精度 knn = KNeighborsClassifier(n_neighbors=5) knn.fit(X_train, y_train) y_pred = knn.predict(X_test) print metrics.accuracy_score(y_test, y_pred) # 模拟将25个观察数据集分成5个等级 from sklearn.cross_validation import KFold kf = KFold(25, n_folds=5, shuffle=False) # 打印每个训练和测试集的内容 print '{} {:^61} {}'.format('Iteration', 'Training set observations', 'Testing set observations') for iteration, data in enumerate(kf, start=1): print '{:^9} {} {:^25}'.format(iteration, data[0], data[1]) # - 数据集包含** 25个观察**(编号0到24) # - 5倍交叉验证,因此它运行** 5次迭代** # - 对于每一次迭代,每个观察值都在训练集或测试集**中,但不是两者** # - 每个观察都在测试集**中,只有一次** ###比较交叉验证到训练/测试分割 # **交叉验证的优点:** # - 更准确地估计样本外的准确性 # - 更有效地使用数据(每次观察都用于培训和测试) # **列车/测试分组的优点:** # - 比K-fold交叉验证运行速度快K倍 # - 更简单地检查测试过程的详细结果 ##交叉验证示例:参数调整 #**目标:**为iris数据集上的KNN选择最佳调整参数(又名“超参数”) from sklearn.cross_validation import cross_val_score # 对于KNN(n_neighbors参数),K = 5的10倍交叉验证 knn = KNeighborsClassifier(n_neighbors=5) scores = cross_val_score(knn, X, y, cv=10, scoring='accuracy') print scores # 使用平均精度作为样本外精度的估计 print scores.mean() #为KNN搜索K的最优值 k_range = range(1, 31) k_scores = [] for k in k_range: knn = KNeighborsClassifier(n_neighbors=k) scores = cross_val_score(knn, X, y, cv=10, scoring='accuracy') k_scores.append(scores.mean()) print k_scores import matplotlib.pyplot as plt # 绘制KNN(x轴)的K值与交叉验证的精度(y轴) plt.plot(k_range, k_scores) plt.xlabel('Value of K for KNN') plt.ylabel('Cross-Validated Accuracy') ###交叉验证示例:模型选择 #**目标:**比较最佳KNN模型和iris数据集上的逻辑回归 #用最好的KNN模型进行10次交叉验证 knn = KNeighborsClassifier(n_neighbors=20) print cross_val_score(knn, X, y, cv=10, scoring='accuracy').mean() # 逻辑回归10倍交叉验证 from sklearn.linear_model import LogisticRegression logreg = LogisticRegression() print cross_val_score(logreg, X, y, cv=10, scoring='accuracy').mean() # ##交叉验证示例:功能选择 # #**目标**:选择报纸特征是否应包含在广告数据集的线性回归模型中 import pandas as pd import numpy as np from sklearn.linear_model import LinearRegression # 读入广告数据集 data = pd.read_csv('http://www-bcf.usc.edu/~gareth/ISL/Advertising.csv';;, index_col=0) # 创建三个功能名称的Python列表 feature_cols = ['TV', 'radio', 'newspaper'] #注意key值还区分大小写 # 使用列表来选择DataFrame(X)的一个子集 X = data[feature_cols] # 选择Sales列作为回应(y) y = data.sales # 所有三个功能的10倍交叉验证 lm = LinearRegression() scores = cross_val_score(lm, X, y, cv=10, scoring='neg_mean_squared_error') print scores # 修复MSE分数的标志 mse_scores = -scores print mse_scores #从MSE转换到RMSE rmse_scores = np.sqrt(mse_scores) print rmse_scores # 计算平均RMSE print rmse_scores.mean() # 具有两种功能的10倍交叉验证(不包括报纸) feature_cols = ['TV', 'radio'] X = data[feature_cols] print np.sqrt(-cross_val_score(lm, X, y, cv=10, scoring='neg_mean_squared_error')).mean() ##改进交叉验证 # **重复交叉验证** # - 多次重复交叉验证(使用**不同的随机分割**数据)并对结果进行平均 # - 通过**减少与交叉验证的单个试验相关联的方差**,更可靠地估计样本外的表现 # **创建一个保留集** # **在开始模型构建过程之前,“拿出”一部分数据** # - 使用剩余数据的交叉验证找到最佳模型,并使用保留集**对其进行测试** # - 样本外表现更可靠的估计,因为持有集**是真正的样本外** # **交叉验证迭代中的特征工程和选择** # - 通常,在交叉验证之前,要素工程和选择发生** # - 而是在每次交叉验证迭代中执行所有特征工程和选择** # - 更可靠的样本外表现评估,因为它更好地模拟**模型在样本外的应用
#第三课、 初识朴素贝叶斯分类
# P( 类别 | 特征) = P ( 特征 | 类别 ) * P( 类别) / P(特征)
import pandas as pd import numpy as np # 将iris数据读入DataFrame url = 'http://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data';; col_names = ['sepal_length', 'sepal_width', 'petal_length', 'petal_width', 'species'] #萼片(sepal)、花瓣(petal) species(种类) iris = pd.read_csv(url, header=None, names=col_names) iris.head() # 将天花板函数应用于数字列 iris.loc[:, 'sepal_length':'petal_width'] = iris.loc[:, 'sepal_length':'petal_width'].apply(np.ceil) iris.head() # ## 决定如何进行预测 #假设我有一个**样本外的光圈**,具有以下测量值:** 7,3,5,2 **。 我如何预测这个物种? #显示所有具有以下特征的观察值:7,3,5,2 iris[(iris.sepal_length==7) & (iris.sepal_width==3) & (iris.petal_length==5) & (iris.petal_width==2)] # 为这些观测计数物种 iris[(iris.sepal_length==7) & (iris.sepal_width==3) & (iris.petal_length==5) & (iris.petal_width==2)].species.value_counts() # 计数tr所有观察物种fo iris.species.value_counts()
# 第四课、朴素贝叶斯分类处理文本文件
from sklearn.feature_extraction.text import CountVectorizer # 从一个简单的例子开始 simple_train = ['call you tonight', 'Call me a cab', 'please call me... PLEASE!'] # 学习训练数据的“词汇” vect = CountVectorizer() vect.fit(simple_train) vect.get_feature_names() # 将训练数据转换成“文档 - 术语矩阵” simple_train_dtm = vect.transform(simple_train) simple_train_dtm #打印稀疏矩阵 print simple_train_dtm # 将稀疏矩阵转换为稠密矩阵 simple_train_dtm.toarray() # 一起检查词汇和文档项目矩阵 import pandas as pd pd.DataFrame(simple_train_dtm.toarray(), columns=vect.get_feature_names()) #> - 每个单独的标记出现频率(标准化或不标准)被视为一个**功能**。 #> - 给定文档的所有标记频率的矢量被认为是一个多元**样本**。 #因此,**文档**可以由一个矩阵表示,每个文档有一行**和每个记号**有一列(例如单词)出现在语料库中。 #>我们把**矢量化称为将文本文档集合转化为数字特征向量的一般过程。这个具体的策略(标记化,计数和标准化)被称为**袋子或**袋子的代表。 # 文档通过单词出现来描述,而完全忽略文档中单词的相对位置信息。 #将测试数据转换成文档术语矩阵(使用现有的词汇) simple_test = ["please don't call me"] simple_test_dtm = vect.transform(simple_test) simple_test_dtm.toarray() # 一起检查词汇和文档项目矩阵 pd.DataFrame(simple_test_dtm.toarray(), columns=vect.get_feature_names()) #**总结:** # - `vect.fit(train)`学习训练数据的词汇 # - `vect.transform(train)`使用拟合词汇从训练数据建立一个文档项矩阵 # - `vect.transform(test)`使用拟合的词汇从测试数据中建立一个文档项矩阵(并忽略它以前没见过的记号) # ## Part 2: 读取SMS数据 # 读取制表符分隔的文件 url = 'https://raw.githubusercontent.com/justmarkham/DAT8/master/data/sms.tsv';; col_names = ['label', 'message'] sms = pd.read_table(url, sep='\t', header=None, names=col_names) print sms.shape sms.head(20) sms.label.value_counts() #将标签转换为数字变量 sms['label'] = sms.label.map({'ham':0, 'spam':1}) # 定义X和y X = sms.message y = sms.label #分成训练和测试集 from sklearn.cross_validation import train_test_split X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=1) print X_train.shape print X_test.shape # ## Part 3: 向量化SMS数据 # 实例化矢量化器 vect = CountVectorizer() # 学习训练数据词汇,然后创建文档术语矩阵 vect.fit(X_train) X_train_dtm = vect.transform(X_train) X_train_dtm # 替代方法:将适合和变换合并为一个步骤 X_train_dtm = vect.fit_transform(X_train) X_train_dtm # 将测试数据(使用拟合的词汇)转换成文档术语矩阵 X_test_dtm = vect.transform(X_test) X_test_dtm # ## Part 4: 检查令牌和他们的计数 # 存储令牌名称 X_train_tokens = vect.get_feature_names() # 前50个令牌 print X_train_tokens[:50] # 最后50个令牌 print X_train_tokens[-50:] # 将X_train_dtm视为一个稠密矩阵 X_train_dtm.toarray() # 计算每个令牌在X_train_dtm中的所有消息中出现多少次 import numpy as np X_train_counts = np.sum(X_train_dtm.toarray(), axis=0) X_train_counts X_train_counts.shape # 用它们的计数创建一个令牌的DataFrame pd.DataFrame({'token':X_train_tokens, 'count':X_train_counts}).sort_values('count') # ## 计算每个令牌的“spamminess” #为火腿和垃圾邮件创建单独的数据框 sms_ham = sms[sms.label==0] sms_spam = sms[sms.label==1] #学习所有消息的词汇并保存 vect.fit(sms.message) all_tokens = vect.get_feature_names() # 为火腿和垃圾邮件创建文档术语矩阵 ham_dtm = vect.transform(sms_ham.message) spam_dtm = vect.transform(sms_spam.message) # 计算EACH令牌在所有的火腿消息中出现的次数 ham_counts = np.sum(ham_dtm.toarray(), axis=0) # 统计每个垃圾邮件中每个令牌的显示次数 spam_counts = np.sum(spam_dtm.toarray(), axis=0) # 使用单独的火腿和垃圾邮件计数创建一个令牌数据框 token_counts = pd.DataFrame({'token':all_tokens, 'ham':ham_counts, 'spam':spam_counts}) # 添加一个火腿和垃圾邮件计数以避免被零除(在下面的步骤中) token_counts['ham'] = token_counts.ham + 1 token_counts['spam'] = token_counts.spam + 1 #计算每个令牌的垃圾邮件到火腿的比例 token_counts['spam_ratio'] = token_counts.spam / token_counts.ham token_counts.sort_values('spam_ratio') # 第5部分:建立一个朴素贝叶斯模型 from sklearn.naive_bayes import MultinomialNB nb = MultinomialNB() nb.fit(X_train_dtm, y_train) # 对X_test_dtm进行类别预测 y_pred_class = nb.predict(X_test_dtm) # 计算类别预测的准确性 from sklearn import metrics print metrics.accuracy_score(y_test, y_pred_class) # 混乱矩阵 print metrics.confusion_matrix(y_test, y_pred_class) # 预测(校准不良)概率 y_pred_prob = nb.predict_proba(X_test_dtm)[:, 1] y_pred_prob # 计算AUC print metrics.roc_auc_score(y_test, y_pred_prob) #打印错误信息的消息文本 X_test[y_test < y_pred_class] # 打印消息文本的错误否定 X_test[y_test > y_pred_class] # 你有什么注意到这个漏报? X_test[3132] # ## Part 6: 比较朴素贝叶斯和逻辑回归 # 进口/实例化/ FIT from sklearn.linear_model import LogisticRegression logreg = LogisticRegression(C=1e9) logreg.fit(X_train_dtm, y_train) # 类别预测和预测概率 y_pred_class = logreg.predict(X_test_dtm) y_pred_prob = logreg.predict_proba(X_test_dtm)[:, 1] # 计算准确度和AUC print metrics.accuracy_score(y_test, y_pred_class) print metrics.roc_auc_score(y_test, y_pred_prob)
未经允许不得转载:同乐学堂 » Python数据分析实战4