在MLPClassifier(和其他分类器)的scikit低训练分数

时间:2017-07-17 13:46:41

标签: python machine-learning scikit-learn

(更新:Posted最终结果作为单独答案)

我开始尝试了解如何使用scikit模型进行培训。我已经尝试过众所周知的数据集,如iris,MNIST等 - 它们都是结构良好的数据,随时可以使用。这是我第一次尝试用自己的原始数据构建模型,结果不太理想。

过去3年,我选择使用的数据是NHSTA's crash data

以下是数据的快照,让您无需下载数据即可了解这些字段。

Snapshot of crash data columns

我的第一个实验很简单 - 尝试构建一个给出“许可证状态代码”和“年龄”的模型,尝试并预测性别(M或F)。

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
from sklearn.cluster import KMeans
from sklearn.decomposition import PCA
from sklearn.preprocessing import LabelEncoder
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn import metrics
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import learning_curve
from sklearn.model_selection import ShuffleSplit
import tensorflow.contrib.learn as skflow
from tensorflow.contrib.learn.python.learn.estimators import run_config
from sklearn.svm import SVC
import pickle, seaborn


def plot_learning_curve(estimator, title, X, y, ylim=None, cv=None,
                        n_jobs=1, train_sizes=np.linspace(.1, 1.0, 5)):
    #http://scikit-learn.org/stable/auto_examples/model_selection/plot_learning_curve.html
    plt.figure()
    plt.title(title)
    if ylim is not None:
        plt.ylim(*ylim)
    plt.xlabel("Training examples")
    plt.ylabel("Score")
    train_sizes, train_scores, test_scores = learning_curve(
        estimator, X, y, cv=cv, n_jobs=n_jobs, train_sizes=train_sizes)
    train_scores_mean = np.mean(train_scores, axis=1)
    train_scores_std = np.std(train_scores, axis=1)
    test_scores_mean = np.mean(test_scores, axis=1)
    test_scores_std = np.std(test_scores, axis=1)
    plt.grid()

    plt.fill_between(train_sizes, train_scores_mean - train_scores_std,
                     train_scores_mean + train_scores_std, alpha=0.1,
                     color="r")
    plt.fill_between(train_sizes, test_scores_mean - test_scores_std,
                     test_scores_mean + test_scores_std, alpha=0.1, color="g")
    plt.plot(train_sizes, train_scores_mean, 'o-', color="r",
             label="Training score")
    plt.plot(train_sizes, test_scores_mean, 'o-', color="g",
             label="Cross-validation score")

    plt.legend(loc="best")
    plt.show()

#MAIN

crashes = pd.read_csv("crashes.csv", nrows=100000)

# drop useless cols

crashes.drop(["Year","Case Individual ID", "Case Vehicle ID", "Transported    
By", "Injury Location", "Role Type"],axis=1, inplace=True)

crashes = crashes [pd.notnull(crashes['Age'])]
crashes = crashes[crashes.Age >= 10 ] # There are ages < 10 - likely junk data. I don't think they drive


# lets drop rows that are empty
crashes = crashes [pd.notnull(crashes['License State Code'])]
crashes = crashes [pd.notnull(crashes['Injury Severity'])]
crashes = crashes [pd.notnull(crashes['Safety Equipment'])]
crashes = crashes [pd.notnull(crashes['Sex'])]

# converts text fields to numerical values
le = LabelEncoder()
crashes = crashes[crashes.columns[:]].apply(le.fit_transform)
crashes = crashes._get_numeric_data()

# lets plot a heat map to show correlation
corr = crashes.corr()
ax = seaborn.heatmap (corr, xticklabels=corr.columns.values,    
yticklabels=corr.columns.values, annot=True)
plt.setp( ax.xaxis.get_majorticklabels(), rotation=45 )
plt.setp( ax.yaxis.get_majorticklabels(), rotation=-45 )
plt.show()

crashes_train, crashes_test = train_test_split(crashes, test_size = 0.2)
Y_train = crashes_train['Sex']
X_train =  crashes_train[[ 'Age',  'License State Code']]
Y_test = crashes_test['Sex']
X_test =  crashes_test[[ 'Age', 'License State Code']]


names_train  = crashes_train.columns.values

print "train size ",len (X_train)
print "test size",len (X_test)
#
# cls = RandomForestClassifier(verbose = True)
#
cls = MLPClassifier(hidden_layer_sizes=(10,10,10), max_iter=500, alpha=1e-4,
                  solver='sgd', verbose=10, tol=1e-4, random_state=1,
                  learning_rate_init=0.01)

#cls = tf.contrib.learn.DNNClassifier(feature_columns=feats, 
#                                               hidden_units=[50, 50, 50], 
#                                              n_classes=3)

#
#

#cls = SVC(verbose = True)

print "Fitting..."
cls.fit(X_train, Y_train)

plot_learning_curve(cls,"Crash Learning", X_train, Y_train)


print("Training set score: %f" % cls.score(X_train, Y_train))
print("Test set score: %f" % cls.score(X_test, Y_test))

我尝试了多种模式(从RandomForest到SVC再到MLP等) - 他们都得到了大约0.56的训练分数和0.6x的损失

最后,这是在当前配置中为MLP生成的图: enter image description here

这是我切换到RandomForest时的情节。 enter image description here

看起来在RandomForest中得分减少,但总体而言它与MLP类似。我做错了什么,如何改进这种方法?感谢

编辑:基于下面的两个答案,我做了所有列之间相关性的热图(在删除了明显无用之后) - 这很糟糕,但这是正确的方法吗?我也可以做一个PCA,但是如果基本的场间相关性很差,它是否表明数据集在挖掘预测时基本没用了?

heatmap vis <code>df.corr</code>

3 个答案:

答案 0 :(得分:2)

  

我的第一个实验很简单 - 尝试建立一个给定的模型   &#34;许可证状态代码&#34;和&#34;年龄&#34;,尝试并预测性别(M或F)。

嗯,事情并非那么简单。您不能简单地获取任何数据并尝试预测某些内容。数据至少需要相互关联。

要做的一些好事:

  • 绘制数据。绘制这3个变量(年龄与性别,许可证状态代码与性别)并查看它们是否存在某种相关性。
  • 计算变量之间的相关性,例如Person's Correlation Coefficient
  • 使用您拥有的所有功能和RandomForest / DecisionTree分类器,它们具有名为feature_importances_的属性。此属性告诉您哪些功能在数据集中最重要(相应于当然的模型) 功能重要性(功能越高,功能越重要)。
  • 详细了解MLP和分类器的工作原理。

分类算法简单地将输入数据映射到类别。但是,如果输入和输出之间没有任何关系,则此任务不可行。特征选择是机器学习中非常重要的一个领域。来自wikipedia

  

在机器学习和统计中,特征选择(也称为变量选择,属性选择或变量子集选择)是选择用于模型构建的相关特征(变量,预测变量)子集的过程。

答案 1 :(得分:1)

问题不在于模型,而在于数据。 &#39;年龄&#39;和#34;许可证状态代码&#39;不是确定“性别”的最佳参数。 。

尝试使用相同的模型来预测伤害严重程度&#39;与安全设备&#39;你应该得到更好的结果。

答案 2 :(得分:0)

我想感谢@gnobre和@Giantrun指出我正确的方向。我不想放弃我的最终目标,试图看看我是否能够预测一种模式来预测性别&#39; (性别)来自任何其他专栏,并且能够更好地关联我的交叉验证和测试/训练图表。

首先,我在所有列之间运行了一个简单的关联,结果看起来非常糟糕。我不确定我是否正在使用正确的数据集。

enter image description here

然后,我决定使用RFE对最重要的功能进行排名,假设&#39;性别&#39;是期望的预测。这给了我一组功能 - 我把所有的True值(1级)作为我的功能集。这给了我以下培训(和测试)图:

heat map

总体训练分数仍然很低(0.58),但是训练和交叉验证之间的相关性很好,这意味着我选择了正确的功能,但我的目标是预测&#39;性& #39;从这个数据开始,可能不是一个好的。我可能一直在玩MLP层等,但我怀疑我能够从0.5x到0.9x

我的下一个兴趣是预测“伤害严重程度”,所以我改变了Y目标并再次运行RFE,这给了我另一套可供选择的功能。具体来说,这些是Injury Severity

的Rank = 1的列

['Victim Status', 'Ejection', 'Injury Descriptor', 'Sex']

使用结果字段作为特征使我获得了更高的训练和验证分数(0.98)和图表:

enter image description here

enter image description here

我得出的一个结论是直接相关图比做RFE或PCA(正确吗?)更有用

一个悬而未决的问题:在这个特定的例子中,当我设法获得高分测试和训练分数时,我还能面对哪些其他问题?