kaggle示例1—研究生录取判断问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haluoluo211/article/details/78767380

问题描述:

UCLA(加利福尼亚大学洛杉矶分校)研究生录取的二分类问题,数据来源:http://www.ats.ucla.edu/stat/data/binary.csv 使用的属性主要有下面四列(前三列为属性,最后一列为结果(类别能否被录用):

  1. gpa
  2. gre分数
  3. rank表示本科生母校的声望
  4. admit则是二分类目标变量(binary target variable),它表明考生最终是否被录取。

本文主要内容:

  1. 使用python pandas数据预处理,包括数据的统计信息,dummy variable(哑变量的处理),数据归一化
  2. 使用sklearn的不同分类方法:LogisticRegression, RandomForestClassifier, KNeighborsClassifier, xgboost对处理好的数据进行分类
  3. GridSearchCV自动参数寻优
  4. 对比数据不做dummy variable处理情况下的识别率。

开发环境建议使用anaconda(python2.7) + pychram


1 数据预处理

1.1 数据导入

下载上面连接的csv文件,命名为UCLA_dataset.csv

import pandas as pd
def get_data():
    f_path = "./dataset/UCLA_dataset.csv"
    df = pd.read_csv(f_path)
    print df.head()  ## 输出前五行

输出结果如下:

   admit  gre   gpa  rank
0      0  380  3.61     3
1      1  660  3.67     3
2      1  800  4.00     1
3      1  640  3.19     4
4      0  520  2.93     4

由于rank为pandas的DataFrame的列属性这里将其rename为prestige(n. 威望;声望)

    df.rename(columns={"rank": "prestige"}, inplace=True)
    print df.head()
    return df

前五行输出如下:

    admit gre   gpa  prestige
0      0  380  3.61         3
1      1  660  3.67         3
2      1  800  4.00         1
3      1  640  3.19         4
4      0  520  2.93         4

1.2 查看数据统计信息

def statistic_data(df):
    print df.describe()

输出如下:

            admit         gre         gpa   prestige
count  400.000000  400.000000  400.000000  400.00000
mean     0.317500  587.700000    3.389900    2.48500
std      0.466087  115.516536    0.380567    0.94446
min      0.000000  220.000000    2.260000    1.00000
25%      0.000000  520.000000    3.130000    2.00000
50%      0.000000  580.000000    3.395000    2.00000
75%      1.000000  660.000000    3.670000    3.00000
max      1.000000  800.000000    4.000000    4.00000

查看学校声望(1, 2, 3, 4)不同时,’admit’的情况:

print pd.crosstab(df['admit'], df['prestige'], rownames=['admit'])

输出如下:

prestige   1   2   3   4
admit                   
0         28  97  93  55
1         33  54  28  12

可见学校的声望越好(1最好),被录取的概率更高

查看gre不同时,’admit’的情况:

# 没有被录取的
no_admits = df[df.admit == 0]
print no_admits.shape
# 没有被录取的学生gre统计信息
print no_admits.gre.describe()

# 被录取的
admits = df[df.admit == 1]
print admits.shape
# 被录取的学生gre统计信息
print admits.gre.describe()

输出如下:

# 没有被录取的学生公有273个,的平均分为 573.18
(273, 4)
count    273.000000
mean     573.186813
std      115.830243
min      220.000000
25%      500.000000
50%      580.000000
75%      660.000000
max      800.000000
Name: gre, dtype: float64

# 被录取的学生公有127个,的平均分为 618.89
(127, 4)
count    127.000000
mean     618.897638
std      108.884884
min      300.000000
25%      540.000000
50%      620.000000
75%      680.000000
max      800.000000
Name: gre, dtype: float64

由此可见gre分数越高,越容易被录取。下面看下直方图:

f, (ax1, ax2) = plt.subplots(2, 1, sharex=True)
f.suptitle('gre per by class')
bins = 20
ax1.hist(no_admits.gre, bins=bins)
ax1.set_title('no_admits')

ax2.hist(admits.gre, bins=bins)
ax2.set_title('admits')

plt.xlabel('gre')
plt.ylabel('Number of gre')
plt.show()

查看数据的统计直方图

import matplotlib.pyplot as plt
import seaborn as sns
sns.set()

df.hist()
plt.show()

dummy variable(哑变量处理)

虚拟变量,也叫哑变量,可用来表示分类变量、非数量因素可能产生的影响。在计量经济学模型,需要经常考虑属性因素的影响。例如,职业、文化程度、季节等属性因素往往很难直接度量它们的大小。只能给出它们的“Yes—D=1”或”No—D=0”,或者它们的程度或等级。为了反映属性因素和提高模型的精度,必须将属性因素“量化”。通过构造0-1型的人工变量来量化属性因素。 pandas提供了一系列分类变量的控制。我们可以用get_dummies来将”prestige”一列虚拟化。 在本例中,prestige有四个级别:1,2,3以及4(1代表最有声望),prestige作为分类变量更加合适。当调用get_dummies时,会产生四列的dataframe,每一列表示四个级别中的一个。

def process_df(df):
    dummy_ranks = pd.get_dummies(df['prestige'], prefix='prestige')
    print dummy_ranks.tail()

输出如下:

      prestige_1    prestige_2   prestige_3  prestige_4
395         0.0         1.0         0.0         0.0
396         0.0         0.0         1.0         0.0
397         0.0         1.0         0.0         0.0
398         0.0         1.0         0.0         0.0
399         0.0         0.0         1.0         0.0

引入的虚拟变量列数应为虚拟变量总列数减1,减去的1列作为基准 .最终的构造数据如下:

cols_to_keep = ['admit', 'gre', 'gpa']

data = df[cols_to_keep].join(dummy_ranks.ix[:, 'prestige_2':])
print data.tail()

输出如下:

     admit  gre   gpa  prestige_2  prestige_3  prestige_4
395      0  620  4.00         1.0         0.0         0.0
396      0  560  3.04         0.0         1.0         0.0
397      0  460  2.63         1.0         0.0         0.0
398      0  700  3.65         1.0         0.0         0.0
399      0  600  3.89         0.0         1.0         0.0

数据集的归一化

考虑把gre, gpa两列数据归一化(数据的量级不是很大,大概100倍),不过实际使用中发现除了KNeighborsClassifier分类方法,对于其他的分类方法而言,归一化并没有提升分类准确率:

def process_df_norm(df):
    dummy_ranks = pd.get_dummies(df['prestige'], prefix='prestige')
    print dummy_ranks.tail()

    cols_to_keep = ['admit', 'gre', 'gpa']

    df = df[cols_to_keep].join(dummy_ranks.ix[:, 'prestige_2':])

    cols_norm = ['gre', 'gpa']
    f_norm = lambda x: (x - x.min()) / (x.max() - x.min())
    df[cols_norm] = df[cols_norm].apply(f_norm)
    print df.tail()
    return df

输出如下:

      admit     gre       gpa   prestige_2   prestige_3    prestige_4
395      0  0.689655  1.000000         1.0         0.0         0.0
396      0  0.586207  0.448276         0.0         1.0         0.0
397      0  0.413793  0.212644         1.0         0.0         0.0
398      0  0.827586  0.798851         1.0         0.0         0.0
399      0  0.655172  0.936782         0.0         1.0         0.0

数据集按照4:1划分

from sklearn.model_selection import train_test_split
def split_train_test(df):
    X = df.ix[:, 1:]
    Y = df.admit
    X_train, X_test, Y_train, Y_test = train_test_split(X, Y,
                                                        test_size=0.2, random_state=40)

    return X_train, X_test, Y_train, Y_test

2 模型训练以及测试

2.1 预测结果的准确率以及混淆矩阵输出

from sklearn.metrics import confusion_matrix, recall_score
from sklearn.metrics import accuracy_score

def print_cm_accuracy(Y_true, Y_pred):
    cnf_matrix = confusion_matrix(Y_true, Y_pred)
    print cnf_matrix
    accuracy_percent = accuracy_score(Y_true, Y_pred)
    print "accuracy is: %s%s" % (accuracy_percent * 100, '%')

2.2 LogisticRegression逻辑回归

from sklearn.linear_model import LogisticRegression
def lr_fit_test(X_train, X_test, Y_train, Y_test):
    lr = LogisticRegression()
    # lr = LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True,
    #                         intercept_scaling=1, penalty='l2', random_state=None, tol=0.0001)

    lr.fit(X_train, Y_train)
    Y_pred = lr.predict(X_test)
    print_cm_accuracy(Y_test, Y_pred)

输出如下: [[53 0] [23 4]] accuracy is: 71.25%

  1. 上面的:lr参数发现C=1.0时准确率最高
  2. 数据归一化之后,准确率竟然下降了1.25%

2.3 RandomForestClassifier随机森林

def rfc_fit_test(X_train, X_test, Y_train, Y_test):
    rf = RandomForestClassifier(n_jobs=4)
    rf.fit(X_train, Y_train)
    Y_pred = rf.predict(X_test)
    print_cm_accuracy(Y_test, Y_pred)

输出: [[46 7] [17 10]] accuracy is: 70.0%

相同的数据集,随机森林的精度较低(逻辑回归为71.25%)

下面看下数据归一化后的准确率:(原有的基础上面下降了) [[48 5] [20 7]] accuracy is: 68.75%


2.4 KNeighborsClassifier k近邻

下面给出K近邻的不同K值是准确度,以及数据是否归一化的对比:

def knn_fit_test(X_train, X_test, Y_train, Y_test):
    # 对比不同k值,准确率的变化
    ks = [1, 3, 5, 7]
    for k in ks:
        print 'KNeighborsClassifier k is %s' % k
        knn = KNeighborsClassifier(n_neighbors=k)
        knn.fit(X_train, Y_train)

        Y_pred = knn.predict(X_test)
        print_cm_accuracy(Y_test, Y_pred)

数据不归一化:

KNeighborsClassifier k is 1
[[41 12]
 [15 12]]
accuracy is: 66.25%
KNeighborsClassifier k is 3
[[44  9]
 [17 10]]
accuracy is: 67.5%
KNeighborsClassifier k is 5
[[47  6]
 [17 10]]
accuracy is: 71.25%
KNeighborsClassifier k is 7

……..太多了省略了

数据归一化:

KNeighborsClassifier k is 1
[[41 12]
 [15 12]]
accuracy is: 66.25%
KNeighborsClassifier k is 3
[[44  9]
 [14 13]]
accuracy is: 71.25%
KNeighborsClassifier k is 5
[[44  9]
 [15 12]]
accuracy is: 70.0%

当然K值也可以使用GridSearchCV网格参数寻优:

from sklearn.model_selection import GridSearchCV
from sklearn.metrics import classification_report

def knn_fit_test(X_train, X_test, Y_train, Y_test):
    paras = {'n_neighbors': [1, 3, 5, 7]}
    knn = KNeighborsClassifier()
    clf = GridSearchCV(knn, paras, n_jobs=-1)
    clf.fit(X_train, Y_train)
    print 'The parameters of the best model are: '
    print clf.best_params_

    for params, mean_score, scores in clf.grid_scores_:
        print("%0.3f (+/-%0.03f) for %r"
              % (mean_score, scores.std() * 2, params))

    Y_pred = clf.predict(X_test)
    print classification_report(Y_test, Y_pred)

输出如下:

0.616 (+/-0.060) for {'n_neighbors': 1}
0.656 (+/-0.049) for {'n_neighbors': 3}
0.669 (+/-0.055) for {'n_neighbors': 5}
0.666 (+/-0.063) for {'n_neighbors': 7}
             precision    recall  f1-score   support

          0       0.75      0.89      0.81        53
          1       0.65      0.41      0.50        27

avg / total       0.71      0.72      0.71        80

2.5 xgboost已经不使用dummy variable

前面已经发现,学校声望越高越容易被录取,而且学校声望已经按照顺序排列,因此考虑,直接使用原来的值(试验发现,准确率更高了):

对于K近邻算法:

对于每种方法,直接使用学校声望的值,对于每种方法结果准确率跟高了。

下面给出xgboost的预测代码:

def xgb_fit_test(X_train, X_test, Y_train, Y_test):
    import os
    mingw_path = 'C:/Program Files/mingw-w64/x86_64-6.2.0-posix-seh-rt_v5-rev1/mingw64/bin'
    os.environ['PATH'] = mingw_path + ';' + os.environ['PATH']
    from xgboost import XGBClassifier

    model = XGBClassifier()
    model.fit(X_train, Y_train)

    Y_pred = model.predict(X_test)
    print_cm_accuracy(Y_test, Y_pred)

注:这个示例不是来源与kaggle,但是这里方便文字归类,将其命名为kaggle

转载注明出处哈。

参考:

http://blog.yhat.com/posts/logistic-regression-python-rodeo.html

http://www.powerxing.com/logistic-regression-in-python/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏儿童编程

儿童创造力教育与编程教育的碰撞——MIT雷斯尼克教授最新理论梗概

儿童编程教育已经在我国各一线二线城市疯狂出现,颇有“烂大街”的趋势。我们不禁要问很多很多问题:

22370
来自专栏儿童编程

天干地支五行八卦的对应关系

19690
来自专栏FSociety

SQL中GROUP BY用法示例

GROUP BY我们可以先从字面上来理解,GROUP表示分组,BY后面写字段名,就表示根据哪个字段进行分组,如果有用Excel比较多的话,GROUP BY比较类...

5.2K20
来自专栏儿童编程

我不是算命先生,却对占卜有了疑惑——如何论证“占卜前提”的正确与否

事出有因,我对《周易》感兴趣了很多年。只是觉得特别有趣,断断续续学习了一些皮毛。这几天又偶然接触到了《梅花易数》,觉得很是精彩,将五行八卦天干地支都串联了起来。...

15310
来自专栏Ken的杂谈

【系统设置】CentOS 修改机器名

18130
来自专栏儿童编程

一张图理清《梅花易数》梗概

学《易经》的目的不一定是为了卜卦,但是了解卜卦绝对能够让你更好地了解易学。今天用一张思维导图对《梅花易数》的主要内容进行概括,希望能够给学友们提供帮助。

32240
来自专栏儿童编程

《动物魔法学校》儿童学编程Scratch之“外观”部分

导读:本文通过一个案例《动物魔法学校》来学习Scratch语言的“外观”部分。之后通过一系列其他功能的综合运用对作品功能进行了扩展。

19240
来自专栏儿童编程

声音功能让儿童编程更有创造性

导读:Scratch中声音功能非常强大,除了常规的音效,你甚至可以模拟各种乐器的各个发音、设置节拍、休止……如果你愿意,甚至可以用它创作一个交响乐。我们可以引导...

13840
来自专栏haifeiWu与他朋友们的专栏

复杂业务下向Mysql导入30万条数据代码优化的踩坑记录

从毕业到现在第一次接触到超过30万条数据导入MySQL的场景(有点low),就是在顺丰公司接入我司EMM产品时需要将AD中的员工数据导入MySQL中,因此楼主负...

29840
来自专栏儿童编程

什么样的人生才是有意义的人生——没有标准的标准答案

【导读】其实我们可以跳出这个小圈圈去更加科客观地看一下这个世界。在夜晚的时候我们仰望天空,浩瀚的宇宙中整个地球只是一粒浮尘,何况地球上一个小小的人类?在漫长的历...

1.8K50

扫码关注云+社区

领取腾讯云代金券

年度创作总结 领取年终奖励