zoukankan      html  css  js  c++  java
  • 泰坦尼克号预测生存可能性

    import pandas as pd
    data = pd.read_csv("train.csv")
    #确定每一列,或者叫每一个series下,是否有空数据
    columns_name = data.columns.tolist()
    columns_name_true_false={}
    print(type(columns_name))
    print(columns_name[0])
    for i in columns_name:
        lenth = len(data[data[i].isnull()==True])
        columns_name_true_false[i]=lenth
    print(columns_name_true_false)
    #确定每一列,或者叫每一个series下,是否有空数据
    #输出发现,'Age'、'Cabin'和'Embarked'有空数据,下一步要填补这些空数据。

    输出:

    {'PassengerId': 0, 'Survived': 0, 'Pclass': 0, 'Name': 0, 'Sex': 0, 'Age': 177, 'SibSp': 0, 'Parch': 0, 'Ticket': 0, 'Fare': 0, 'Cabin': 687, 'Embarked': 2}

    下面要处理这些空数据。

    #处理'Embarked',计算'Embarked'中C、S、Q出现的次数,用出现次数多的填补空位置。
    Embarked_list=['S','C','Q']
    Embarked_list_times = {}
    for i in Embarked_list:
        times = len(data[data['Embarked']==i])
        Embarked_list_times[i]=times
    print(Embarked_list_times)
    #处理'Embarked',计算'Embarked'中C、S、Q出现的次数,用出现次数多的填补空位置。

    输出:

    {'S': 644, 'C': 168, 'Q': 77}

    发现‘S’的次数最高,那就用S填补这些空位置。

    data.fillna(axis=0,value='S',inplace=True)

    'Cabin'缺失值太多,舍掉这个特征。

    data.drop('Cabin',axis =1,inplace=True)

    下边处理Age空缺的问题,一般可以用中值和均值填补空缺位置。这里两种情况都试一下,看下结果有什么差异。

    data1 = data['Age'].dropna(axis=0)
    zhongshu = data1.median()
    data['Age'].fillna(value=zhongshu,inplace=True) #用中值弥补空缺位置
    #data['Age'].fillna(value=data1.mean(),inplace=True)   #用均值弥补空缺位置
    data['Sex']下和data['Embarked']有字符串,将字符串转成对应的数字,方便预测。其实这里转成数字不太合适,用one_hot比较合适,后边有时间用one_hot做一下。
    #data['Sex']一列下有男女,将男女转为0和1
    data['Sex'].replace('male',0,inplace=True)
    data['Sex'].replace('female',1,inplace=True)
    #data['Sex']一列下有男女,将男女转为0和1
    
    #同上,将data['Embarked']一列'S','C','Q'转成0、1、2
    data['Embarked'].replace('S',0,inplace=True)
    data['Embarked'].replace('C',1,inplace=True)
    data['Embarked'].replace('Q',2,inplace=True)
    #同上,将data['Embarked']一列'S','C','Q'转成0、1、2

    数据预处理完毕,下边用线性回归模型预测。

    #下一步,利用回归预测
    from sklearn.linear_model import LinearRegression
    from sklearn.model_selection import KFold
    alg = LinearRegression()
    kf = KFold(3,shuffle=False)
    data_list=['Pclass','Sex','Age','SibSp','Parch','Fare','Embarked']  #提取有效的特征,name这类的暂时没用
    predict_values=[]
    for train,test in kf.split(data):
        #alg.fit(data.iloc[train],)
        data_train = data[data_list].iloc[train]
        data_train_label = data['Survived'].iloc[train]
        alg.fit(data_train,data_train_label) #fit(x,y) x是分割的训练集的数据部分,y是训练集的标签部分
        predict_value = alg.predict(data[data_list].iloc[test])#利用刚训练好的模型,预测测试集部分
        #注意预测的结果也就是predict_value是一个list,内容是一个获救的概率。
        predict_values.append(predict_value)#最终的predict_values是一个二维list,行数为3
    predict_values = [i for item in predict_values for i in item]
    #将predict_values由二维转一维,需要注意的是,前边正则交叉时,test部分是按照顺序来的,也就是第一次分割是[0-296],第二次是[297-594],第三次是[595-981]
    #这是能够转成一维的前提,因为后边要用predict_values和data['Survived']对比,所以数据一一对应是前提
    prediction=[]  #将概率转成0或1
    for i in predict_values:
        if i>0.5:
            prediction.append(1)
        else:
            prediction.append(0)
    j = 0#j是预测成功的数量
    for i in range(len(prediction)):
        if prediction[i]==data['Survived'].tolist()[i]:
            j = j+1
    print('percent: {:.6%}'.format(j/len(prediction)))

    输出:percent: 78.338945%

    如果用均值填补Age空缺部分,输出是:78.563412%,差不多。

    利用逻辑回归解这个问题:

    把上边注释掉

    kf = KFold(3,shuffle=False)
    lr = LogisticRegression(solver='liblinear')
    data_list=['Pclass','Sex','Age','SibSp','Parch','Fare','Embarked']
    predict_values=[]
    for train,test in kf.split(data):
        data_train = data[data_list].iloc[train]
        data_train_label = data['Survived'].iloc[train]
        lr.fit(data_train,data_train_label) #fit(x,y) x是分割的训练集的数据部分,y是训练集的标签部分
        predict_value = lr.predict(data[data_list].iloc[test])#利用刚训练好的模型,预测测试集部分
        predict_values.append(predict_value)
    print('-------')
    predict_values = [i for item in predict_values for i in item]
    j = 0#j是预测成功的数量
    for i in range(len(predict_values)):
        if predict_values[i]==data['Survived'].tolist()[i]:
            j = j+1
    print('percent: {:.6%}'.format(j/len(predict_values)))

    输出:percent: 79.124579%。相比简单的线性回归,有所提高。

    用随机森林再次预测,把上边代码注释掉。

    #下边是用随机森林预测结果
    from sklearn.model_selection import cross_val_score
    #cross_val_score用来做交叉验证,新版本的sklenrn中是在model_selection模块下
    from sklearn.ensemble import RandomForestClassifier #RandomForestClassifier是随机森林函数
    data_list=['Pclass','Sex','Age','SibSp','Parch','Fare','Embarked']
    kf = KFold(3,shuffle=False)
    lr = RandomForestClassifier(n_estimators=10,min_samples_split=2,min_samples_leaf=1)
    #n_estimators是树的数量,min_samples_split是当样本节点数小于2时,不再继续划分,min_samples_leaf是需要在叶子结点上的最小样本数量:
    score = cross_val_score(estimator=lr,X=data[data_list],y=data['Survived'],cv=kf)
    print(score.mean())
    #上边是用随机森林预测结果

    调节RandomForestClassifier()里的参数min_samples_split,min_samples_leaf可以提高预测准确率,可以防止过拟合现象。

    例如:lr = RandomForestClassifier(n_estimators=200,min_samples_split=10,min_samples_leaf=2)

    输出:0.8215488215488215

    下边,对特征进行分析,找出对结果影响比较高的特征。用SelectKBest。额外加了3个特征,名字长度、称呼、家庭成员数量。

    from sklearn.feature_selection import SelectKBest,f_classif
    import re #提取姓名的中间部分,需要用到正则表达式
    data_name=[]  #data_name用来放所有人名的中间的称呼
    for i in data['Name'].tolist():
        name = re.search(r' (w+)',i).group(1)
        #这是正则表达式的用法re.search().group()返回的才是提取到的内容。group()的话提取到的内容带空格,group(1)是去掉空格的部分,也就是group(0)是空格
        data_name.append(name)
    data["Name_middle"] = data_name
    print(data["Name_middle"].value_counts())  #可以查看不同的称呼内容以及出现的次数
    data_name_list=[]
    for i in data_name:  #把所有出现过的称呼组成一个列表,放入data_name_list中,也就相当于data_name去重之后的内容
        if i not in data_name_list:
            data_name_list.append(i)
    data_name_list_number=list(range(0,len(data_name_list)))
    name_dic = dict(zip(data_name_list,data_name_list_number))
    #将所有称呼进行编码,组成一个字典,key是称呼,value是编码
    for i,j in name_dic.items(): #将data["Name_middle"]的称呼转为对应的编码
        data["Name_middle"].replace(i,j,inplace=True)
    print(data["Name_middle"].value_counts())  #检查下,发现转换前后没有问题,转换成功
    data['family_nubmer'] =data['SibSp']+data['Parch']
    name_length_list=[] #计算所有人的姓名的长度
    for i in data['Name'].tolist():
        name_length_list.append(len(i))
    data['name_length'] =name_length_list
    data_list=['Pclass','Sex','Age','SibSp','Parch','Fare','Embarked',
              'name_length',"Name_middle",'family_nubmer']
    selector = SelectKBest(f_classif) #SelectKBest新版sklearn不用写常数项参数。
    selector.fit(data[data_list],data['Survived'])
    print("pvalues_:",selector.pvalues_)  # p-values 越小,置信度越高,特征越重要
    print("scores_:",selector.scores_)  # scores_得分越高,特征越重要
    print(type(selector.scores_))

    输出:

    pvalues_: [2.53704739e-25 1.40606613e-69 5.27606885e-02 2.92243929e-01
     1.47992454e-02 6.12018934e-15 1.40831242e-03 2.02679507e-24
     1.81233819e-04 6.19891122e-01]
    scores_: [1.15031272e+02 3.72405724e+02 3.76152805e+00 1.11057220e+00
     5.96346384e+00 6.30307642e+01 1.02593551e+01 1.10388690e+02
     1.41353649e+01 2.46193112e-01]

    下面画柱状图分析下:

    #画柱状图,将pvalues_和scores_都反应到一张图上。
    name_list = data_list
    num_list = pvalues_list
    num_list2 = selector.scores_
    x = list(range(len(num_list)))
    total_width, n = 0.8, 2
    width = total_width / n
    plt.bar(x, num_list, width=width, label='pvalues', fc='b')
    for i in range(len(x)):
        x[i] += width
    plt.bar(x, num_list2, width=width, label='scores', tick_label=name_list, fc='g')
    plt.xticks(rotation=90)
    plt.legend()
    plt.show()

    输出:

     发现:Pclass、Sex、Fare、name_length影响最大。下边,应该利用这些特征,应用在集成算法上,继续计算生存率。集成算法现在还没有学到,大体上是说,把很多算法融合在一起,每一个算法计算一个生存率,再求平均值。这种集成算法应用比较广,再很多比赛里用这样的算法可以提高预测精度。但是比较耗费时间。这是集成算法中的一类。这些请参考https://blog.csdn.net/wp_python/article/details/79815191。

    另外,在写完结束的到时候,发现有一篇类似的文章,https://www.cnblogs.com/my-love-is-python/p/9514546.html。和唐宇迪的写的几乎是一样的,代码比较简洁。

    无意中看到了GridSearchCV函数,这个函数说白了就是通过遍历的方式,找到算法某个参数中比较好的值,在以后的论文中一定能用到。

  • 相关阅读:
    Tabindex
    bootStrap下拉菜单 点击下拉列表某个元素,列表不隐藏
    ionic--分模块
    ionic--配置路由
    ionic —指令
    一个简单的Makefile的编写【用自己的话,解释清楚这些】
    使用ptrace向已运行进程中注入.so并执行相关函数
    StrictMode模式介绍
    adb server is out of date. killing...
    交叉编译lsof for android
  • 原文地址:https://www.cnblogs.com/lgwdx/p/13508819.html
Copyright © 2011-2022 走看看