Scikit-Learn: 机器学习的灵丹妙药

2018-10-12 18:36:02 浏览数 (1)

Scikit-Learn是python的核心机器学习包,它拥有支持基本机器学习项目所需的大部分模块。该库为从业者提供了一个统一的API(ApplicationProgramming Interface),以简化机器学习算法的使用,只需编写几行代码即可完成预测或分类任务。它是python中为数不多的库之一,它遵守了维护算法和接口层简单的承诺。该软件包是用python编写的,它包含了支持向量机的C 库(如LibSVM和LibLinearnforSupportVectorMachine)和广义线性模型实现。包依赖于Pandas(主要用于dataframe进程)、numpy(用于ndarray构造)和cip(用于稀疏矩阵)。

该软件包之所以有用,主要是因为它的项目远景。代码质量和适当的文档构成了核心愿景。包文档包括叙述性文档、类参考、教程、安装说明,以及对初学者非常有用的60多个示例。并不是所有即将出现的机器学习算法都被立即添加到包中。对于新的机器学习算法,有一个明确的包含标准设置。包含标准附带以下条件:

1. 所提出的算法应优于在某些领域中实现的方法。

2. 无缝地融入API设计(应该以numpy数组作为输入,并遵循FIT/Transform/Process流程)。

3. 新的实现必须得到研究论文的支持,或者在另一个包中实现。

是的,可以直接在numpy和cip中对算法进行编码,但这需要一个人擅长编程、数学、统计、性能调优、版本控制和测试。此外,编写的代码实现必须是可重用和可伸缩的,以防止将来发生问题。当大家都朝着同一个目标努力的时候,就没有必要重复造轮子。Scikit-Learning正在积极开发中,这样实践者就可以专注于手头的业务问题。

包中的基本要素是估计器。估计器可以是转换数据的估计器(预处理和流水线),也可以是机器学习算法的实现。所有其他模块都将支持估计器。例如,数据集、分解、度量、特征选择、模型选择、集成和使用。

大多数Scikit-Learn模块遵循相同的步骤。

1. 用参数实例化估计器(否则它将接受默认参数)

2. 通过FIT方法向估计器实例提供输入数据(输入可以是带有选定列、Numpy 2d数组或Sciy稀疏矩阵的熊猫数据)。FIT只需要一个数组或输入数组和目标的组合。

3. 如果它是一个数据操作模块,它将附带一个转换方法。检查FIT_Transform方法,以便可以使用一行代码完成步骤2和步骤3

4. 在拟合方法之后,估计器应该有一个预测方法来预测测试输入的大小或类别。

并非所有python包都是相等的。Scikit-Learn只做了一件事,而且做得很好,那就是实现基本的机器学习算法。

1. 它不是一个深入/强化的学习包,因为TensorFlow和PyTorch在这个类别中得分很高,而且Scikit-Learning不提供任何图形处理单元支持。包括GPU支持可能会使实现复杂化,因为它需要提供对多个硬件和操作系统组合的支持。

2. 它不是一个可视化的软件包,因为matplotlib,海运和巧妙地被用来创建好的探索性数据分析图和模型评估图。

3. 它不是一个结构化的学习和预测包,因为pystruct很好地处理一般的结构化学习,而seqLearning只使用hmm的推理来处理序列。

4. 它不是一个自然语言处理包,因为nltk和gensim有更好的nlp算法实现和相应的语言语料库。

5. 它不是一个基本的统计软件包,因为statsmodel包含基本统计指标实现以及时间序列预测模块。

预测问题的示例:使用内置癌症数据集

让我们在这里启动一个机器学习项目工作流。这个工作流的目的不是提高分类问题的准确性或F1评分,而是触及所有必要的模块,以有效地使用Scikit-Learning来完成分类问题。大多数分类示例都是从iris 数据集开始的,因此让我们在Scikit中选择另一个数据集来学习这个工作流。我们将主要使用威斯康星州乳腺癌数据集。目的是根据患者的临床观察参数对诊断(癌症诊断:正确或错误)进行分类。该数据集包含569个观测数据和30个连续的数字特征。212-恶性、357-良性的类别分布。

· 数据集和生成器:与无监督学习任务不同,有监督的任务(即分类)需要标记数据集,该包附带多个数据集和数据集生成器,以便开始机器学习。

大致分为两类

a.静态数据集:数据集是具有特征数据(Numpy Ndarray)、数据集描述、特征名、目标(numpy数组和多标签的ndarray)和目标名称(即FETCH_20新闻组包含文本输入,并分成20个不同的新闻组,如体育、政治、金融等)的字典。这些数据集只有有限的观测量和目标类别或预测范围,即著名的iris 数据集只有150个观测值和3个目标类别。我编写了一个函数,将字典格式的内置数据集转换为pandas数据格式,以便进行可视化和探索。

使用seaborn的癌症数据集配对图使用seaborn的癌症数据集配对图

b.示例生成器:与静态数据集相比,大多数机器学习算法将需要更多的标记观察,并且该包具有内置的示例生成器例程来生成具有所需数量的观察值的标记数据集。例如,示例生成器make_moons接受两个关键参数n_sames和noisis。从业者可以向例程提供一些要生成的样本,并在输入特征中添加噪声。

Make_BLOB示例生成器生成的输出数据集Make_BLOB示例生成器生成的输出数据集

· 训练与测试:加载数据集后,它必须拆分为训练和测试集,以便从算法训练开始。这个程序包有一个例行程序,可以将pandas的数据序列或数字数组分解成训练和测试装置。该方法采用输入特征、目标数组、测试集的大小(观察次数作为整个数据集的百分比)和分层数组。分层是一种方便的选择,因为目标类的比例在训练和测试集合中是相同的,也就是说,目标分布在训练和测试数据集中是相同的。

X_train, X_test, y_train, y_test =   

 train_test_split(cancer_data_pd[cancer_data_dict.feature_names],    cancer_data_dict['target'],    test_size=0.20,    stratify=cancer_data_dict['target'],    random_state=111,    shuffle=True);

INFO - X_train.shape : (455, 30) INFO - X_test.shape  : (114, 30) INFO - Y_train.shape : (455,) INFO - Y_test.shape  : (114,)

· DummyRegresors和分类器:在探索性数据分析和特征选择之前,我建议建立一个虚拟回归器或分类器。Dummy分类器将为模型提供偏倚场景,即在癌症数据集中,大多数类是良性的(569个中有357个),因此将未来的任何测试观察(病人)分配给良性类将是一个虚拟分类器。虚拟估计器在目标变量中查找模式,而不是从输入特性中学习模式。为什么我们需要一个虚拟估计器来获得模型性能度量的基线。任何其他机器学习算法至少应该优于虚拟估计器。

dummy_classifier = DummyClassifier(strategy="most_frequent");

· 模型性能指标:必须在训练集上训练算法,并在测试集上进行测试。模型性能度量应用于访问模型的性能,即精度是介于0到1之间的分类度量(精度越高,精度越好)。 准确性=正确的类预测/总预测。 该包提供了各种各样的度量来访问模型性能。你还可以编写自定义度量,并将其包装在make_scorer方法中,以便它与PackageAPI很好地集成。

def cost_accuracy(actual, prediction):     """ Custom accuracy cost function to be used in the scorer """;     # accuracy = correct predictions / total predictions

    assert len(actual) == len(prediction);     return round((np.sum(actual == prediction) / len(actual)) , 4);

accuracy_scorer = make_scorer(cost_accuracy, greater_is_better=True);

· KFold和CrossVal评分/预测:为了避免算法对训练集的过度拟合,需要在一定程度上加以推广。不是在整个训练集中运行训练算法,而是将训练集分割成多个块(即10个等量块),在少数几个块(用于训练的9个块)上进行训练,在其余部分上进行测试(1块用于测试)。为了避免过度适应,这一过程将被重复。过度匹配的模型只在训练集模式/场景中表现良好,并且无法用测试集进行正确的类预测。该包提供了KFOLD和CrossVal例程,以避免过度安装。在下面的代码中,k折叠被设置为10个拆分(10个不同的组)。每个组都有训练输入特征、训练目标、测试输入特征、测试目标),交叉Val_Score将在10组k折叠数据集上匹配10个虚拟分类器。准确的分数将列在一张清单上。

kfold = model_selection.KFold(n_splits=10, random_state=111); results = model_selection.cross_val_score(dummy_classifier, X_train, y_train, cv=kfold, scoring=accuracy_scorer);

· 标准化:必须对所有连续的数字输入特征进行缩放,这样就不会有一个单一的特征影响模型的性能。例如,输入特征A可能以数百万为单位,如果不缩放到标准刻度,该模型将不会了解特征B的方差。该软件包带有最小最大值(0到1之间)和标准标量器(刻度输出将包括负值)。

std_scaler = preprocessing.MinMaxScaler(); std_scaler = std_scaler.fit(X_train); scaled_X_train = pd.DataFrame(std_scaler.transform(X_train), columns=X_train.columns);

· SelectKest:输入特征选择在任何建模过程中都是非常关键的一步。该包提供了一个例程,用于根据给定的准则选择n个最佳特征。在下面的代码中,根据f_class f准则(分类模型性能度量之一)选择特征。

selectKbest_est = SelectKBest(f_classif, k=8); selectKbest_X_train = selectKbest_est.fit_transform(X_train, y_train);

· 多项式特征生成:将输入特征结合起来生成多项式和交互项。包的预处理模块与多项式特征例程一起在给定的程度上生成新的特征。

poly = preprocessing.PolynomialFeatures(degree=2, include_bias=False, interaction_only=False); X_train_poly = poly.fit_transform(X_train); X_train_p2 = pd.DataFrame(X_train_poly,

columns=poly.get_feature_names(X_train.columns));

· 分解-PCA(核主成分分析):这是输入特性数量巨大的地方,它需要分解成几个,但需要保留各特性之间的差异。该包附带KernelPCA例程,将功能压缩到一个较小的集合中。该方法可以用不同的核进行主成分分析。数据必须按比例进行PCA。

kernel_param = ('rbf', 1); kpca = KernelPCA(n_components=4,                  kernel=kernel_param[0],                  gamma=kernel_param[1],                  fit_inverse_transform=True,                  random_state=111)      kpca.fit(scaled_X_train);   # The data has to be scaled; kpca_X_train = kpca.transform(scaled_X_train);

· 网格搜索(GridSearchCV):模型参数调优是一项艰巨的任务,必须使用其性能指标登录多个迭代,直到达到最佳参数集为止。参数调整主要是简化在Scikit-学习GridSearchCV例程。给定一个模型参数组合列表,该方法运行所有可能的组合,并返回最佳模型参数和最佳估计器。该方法还进行交叉验证,因此最佳估计器不超过训练数据。在下面的代码中,有8个(2x2x1)参数组合,由于交叉验证为5,例程将适合40个模型。

tuning_parameters = [{'n_estimators' : [1, 10],                       'max_depth' : [10, 20],                       'max_features' : [0.80, 0.40],                       'random_state' : [111]                      }];

clf = GridSearchCV(RandomForestClassifier(),                    tuning_parameters,                    cv=5,                    scoring=accuracy_scorer);

clf.fit(X_train, y_train);

· 自定义估计器和管道:你可以对他们的自定义估值器进行编码。自定义估计器可以是管道的一部分。一个管道接受多个估值器并按顺序执行它们。它将把前一个估计器的输出作为输入传递给列表中的下一个估计器。整个模型过程(标准标量器、输入器、多项式特征生成和分类模型拟合)都可以用流水线来设计,并且可以直接适合于数据集。这个例程在简化模型生产部署方面有很大的帮助。在下面的代码中,ColumnTypeFilter将只返回类型为numpy的熊猫列。该管道从ColumnTypeFilter获取输出,并使用标准标量器和最小-最大定标器对它们进行缩放。输出将有两倍的数字特性作为输入。

class ColumnTypeFilter(BaseEstimator, TransformerMixin):     """ Custom transformer to select all columns of a particular type in a pandas dataframes """;

    def __init__(self, dtype):         self.dtype = dtype;

    def fit(self, X, y=None):         return self;

    def transform(self, X):         assert isinstance(X, pd.DataFrame);         return X.select_dtypes(include=[self.dtype]);

ctf = ColumnTypeFilter(np.number); ctf.fit_transform(X_train).head();

custom_pipeline = make_pipeline(             FeatureUnion(transformer_list=[                 ('StdScl', make_pipeline(                     ColumnTypeFilter(np.number),                     preprocessing.StandardScaler()                 )),                 ('MMScl', make_pipeline(                     ColumnTypeFilter(np.number),                     preprocessing.MinMaxScaler()                 ))             ])     );

· 集合模型-Voting分类器:将许多分类器估计器(估计器应该有一个预测概率方法)添加到Voting分类器中。对于新的测试记录,例程将记录发送给所有估计器,并获得类预测,然后根据多数票分配一个类。

ensemble_clf = VotingClassifier(estimators=[                             ('dummy', dummy_classifier),                             ('logistic', lr),                             ('rf', RandomForestClassifier())],                             voting='soft');

ensemble_clf.fit(X_train, y_train); ensemble_clf_accuracy_ = cost_accuracy(y_test,    ensemble_clf.predict(X_test));

· 处理分类和文本输入功能:任何机器学习模型都需要数字输入特性(连续的或分类的)。使用标签编码器或单热编码器,下面的婴儿名被转换成数字向量,一旦转换,这些向量将作为模型训练的输入特性。

baby_names = ['Ava', 'Lily', 'Noah', 'Jacob', 'Mia', 'Sophia']; X_train_list = [ np.random.choice(baby_names) for i in range(40) ]; X_test_list = [ np.random.choice(baby_names) for i in range(6) ];

bb_labelencoder = preprocessing.LabelEncoder(); bb_labelencoder.fit(X_train_list); bb_encoded = bb_labelencoder.transform(X_test_list);

bb_onehotencoder = preprocessing.OneHotEncoder(sparse=False); bb_encoded = bb_encoded.reshape(len(bb_encoded), 1); bb_onehot = bb_onehotencoder.fit_transform(bb_encoded);

Actual : Ava   | LabelEncoded : 0   | OneHot : [ 1.  0.  0.  0.] Actual : Ava   | LabelEncoded : 0   | OneHot : [ 1.  0.  0.  0.] Actual : Noah  | LabelEncoded : 4   | OneHot : [ 0.  0.  0.  1.] Actual : Mia   | LabelEncoded : 3   | OneHot : [ 0.  0.  1.  0.] Actual : Lily  | LabelEncoded : 2   | OneHot : [ 0.  1.  0.  0.] Actual : Lily  | LabelEncoded : 2   | OneHot : [ 0.  1.  0.  0.]

· 特征提取(从图像和文本):使用这些例程可以直接将文本文档列表转换为输入特性,而不需要太多代码。

corpus = ['This is the first document.',           'This document is the second document.',           'And this is the third one.',           'Is this the first document?', ]

vectorizer = CountVectorizer(); X = vectorizer.fit_transform(corpus);

cntvector_out = pd.DataFrame(X.toarray(),        columns=vectorizer.get_feature_names());

Input text : This is the first document. Output counter vector : This is the first document. and         0 document    1 first       1 is          1 one         0 second      0 the         1 third       0 this        1

原文标题《Scikit-Learn: A silver bullet for basic machine learning》

作者:Manikandan Jeeva

译者:lemon

不代表云加社区观点,更多详情请查看原文链接

0 人点赞