05 fusión modelo

Objetivo de fusión de modelos: fusión de modelos para una variedad de modelos que se han ajustado

La fusión de modelos es una parte importante en la etapa posterior del juego. En términos generales, existen los siguientes tipos.

1. Fusión ponderada simple:

  • Regresión (probabilidad de clasificación): media aritmética, media geométrica;
#简单加权平均,结果直接融合
## 生成一些简单的样本数据,test_prei 代表第i个模型的预测值
test_pre1 = [1.2, 3.2, 2.1, 6.2]
test_pre2 = [0.9, 3.1, 2.0, 5.9]
test_pre3 = [1.1, 2.9, 2.2, 6.0]

# y_test_true 代表第模型的真实值
y_test_true = [1, 3, 2, 6] 

import numpy as np
import pandas as pd

## 定义结果的加权平均函数
def Weighted_method(test_pre1,test_pre2,test_pre3,w=[1/3,1/3,1/3]):
    Weighted_result = w[0]*pd.Series(test_pre1)+w[1]*pd.Series(test_pre2)+w[2]*pd.Series(test_pre3)
    return Weighted_result



from sklearn import metrics
# 各模型的预测结果计算MAE
print('Pred1 MAE:',metrics.mean_absolute_error(y_test_true, test_pre1))
print('Pred2 MAE:',metrics.mean_absolute_error(y_test_true, test_pre2))
print('Pred3 MAE:',metrics.mean_absolute_error(y_test_true, test_pre3))



## 根据加权计算MAE
w = [0.3,0.4,0.3] # 定义比重权值
Weighted_pre = Weighted_method(test_pre1,test_pre2,test_pre3,w)
print('Weighted_pre MAE:',metrics.mean_absolute_error(y_test_true, Weighted_pre))

## 定义结果的加权平均函数
def Mean_method(test_pre1,test_pre2,test_pre3):
    Mean_result = pd.concat([pd.Series(test_pre1),pd.Series(test_pre2),pd.Series(test_pre3)],axis=1).mean(axis=1)
    return Mean_result


Mean_pre = Mean_method(test_pre1,test_pre2,test_pre3)
print('Mean_pre MAE:',metrics.mean_absolute_error(y_test_true, Mean_pre))

 

  • Categoría: Votación
#分类模型融合

from sklearn.datasets import make_blobs
from sklearn import datasets
from sklearn.tree import DecisionTreeClassifier
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import VotingClassifier
from xgboost import XGBClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_moons
from sklearn.metrics import accuracy_score,roc_auc_score
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import StratifiedKFold

#Voting投票机制
#Voting即投票机制,分为软投票和硬投票两种,其原理采用少数服从多数的思想。

'''
硬投票:对多个模型直接进行投票,不区分模型结果的相对重要度,最终投票数最多的类为最终被预测的类。
'''
iris = datasets.load_iris()

x=iris.data
y=iris.target
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3)

clf1 = XGBClassifier(learning_rate=0.1, n_estimators=150, max_depth=3, min_child_weight=2, subsample=0.7,
                     colsample_bytree=0.6, objective='binary:logistic')
clf2 = RandomForestClassifier(n_estimators=50, max_depth=1, min_samples_split=4,
                              min_samples_leaf=63,oob_score=True)
clf3 = SVC(C=0.1)

# 硬投票
eclf = VotingClassifier(estimators=[('xgb', clf1), ('rf', clf2), ('svc', clf3)], voting='hard')
for clf, label in zip([clf1, clf2, clf3, eclf], ['XGBBoosting', 'Random Forest', 'SVM', 'Ensemble']):
    scores = cross_val_score(clf, x, y, cv=5, scoring='accuracy')
    print("Accuracy: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label))


'''
软投票:和硬投票原理相同,增加了设置权重的功能,可以为不同模型设置不同权重,进而区别模型不同的重要度。
'''
x=iris.data
y=iris.target
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3)

clf1 = XGBClassifier(learning_rate=0.1, n_estimators=150, max_depth=3, min_child_weight=2, subsample=0.8,
                     colsample_bytree=0.8, objective='binary:logistic')
clf2 = RandomForestClassifier(n_estimators=50, max_depth=1, min_samples_split=4,
                              min_samples_leaf=63,oob_score=True)
clf3 = SVC(C=0.1, probability=True)

# 软投票
eclf = VotingClassifier(estimators=[('xgb', clf1), ('rf', clf2), ('svc', clf3)], voting='soft', weights=[2, 1, 1])
clf1.fit(x_train, y_train)

for clf, label in zip([clf1, clf2, clf3, eclf], ['XGBBoosting', 'Random Forest', 'SVM', 'Ensemble']):
    scores = cross_val_score(clf, x, y, cv=5, scoring='accuracy')
    print("Accuracy: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label))



 

  • Síntesis: promedio de rango, fusión de registro

 

2.apilamiento / mezcla:

  • Construya un modelo de múltiples capas y use los resultados de predicción para ajustar las predicciones.

¿Qué es apilar?

En términos simples, apilar es usar los datos de entrenamiento inicial para aprender varios estudiantes básicos, y usar los resultados de predicción de estos estudiantes como un nuevo conjunto de entrenamiento para aprender un nuevo estudiante.

El método utilizado cuando se combinan alumnos individuales se denomina estrategia combinada. Para problemas de clasificación, podemos usar el método de votación para seleccionar la clase de mayor producción. Para problemas de regresión, podemos promediar los resultados obtenidos por el clasificador.

El método de votación y el método de promedio mencionado anteriormente son estrategias de combinación muy efectivas. Otra estrategia de combinación es utilizar otro algoritmo de aprendizaje automático para combinar los resultados de los aprendices de máquinas individuales. Este método es el Apilamiento.

En el método de apilamiento, llamamos al alumno individual el alumno primario, el alumno utilizado para combinar se denomina alumno secundario o meta-alumno, y los datos utilizados por el alumno secundario para el entrenamiento se denominan conjunto de entrenamiento secundario. El conjunto de entrenamiento secundario se obtiene con el alumno primario en el conjunto de entrenamiento.

 

Cómo apilar

El diagrama esquemático del algoritmo es el siguiente:

  • El proceso 1-3 consiste en capacitar al alumno individual, que es el alumno primario.
  • El proceso 5-9 consiste en utilizar al alumno individual capacitado para obtener el resultado previsto, que se utiliza como conjunto de capacitación del alumno secundario.
  • El proceso 11 consiste en capacitar al alumno secundario con los resultados pronosticados por el alumno primario y obtener el modelo que finalmente capacitamos.

Método de apilamiento

Primero, comencemos con un método de apilamiento "no tan correcto" pero fácil de entender.

El modelo de apilamiento es esencialmente una estructura jerárquica. En aras de la simplicidad, solo se analiza el apilamiento de segundo nivel. Supongamos que tenemos dos modelos base Modelo1_1, Modelo1_2 y un modelo secundario Modelo2

Paso 1. Modelo base Modelo1_1, entrene el conjunto de entrenamiento y luego se usa para predecir las columnas etiquetadas de tren y prueba, respectivamente P1, T1

Modelo1_1 entrenamiento modelo:

El modelo entrenado Model1_1 se predice en el tren y la prueba, respectivamente, y las etiquetas predichas son P1 y T1, respectivamente.

 

Paso 2. Modelo base Modelo1_2, entrene el conjunto de entrenamiento y luego se usa para predecir las columnas etiquetadas de entrenamiento y prueba, respectivamente P2, T2

Modelo1_2 entrenamiento modelo:

El modelo entrenado Model1_2 se predice en el tren y la prueba, respectivamente, y las etiquetas predichas son P2 y T2, respectivamente.

 

Paso 3. Combina P1, P2 y T1, T2 respectivamente para obtener un nuevo conjunto de entrenamiento y conjunto de prueba train2, test2.

Luego use el modelo secundario Model2 para entrenar con la etiqueta del conjunto de entrenamiento real como etiqueta, y train2 como la característica para entrenar, predecir test2 y obtener la columna de etiqueta predicha del conjunto de prueba final

Esta es una idea original básica de nuestro apilamiento de dos capas. En función de los resultados de predicción de diferentes modelos, agregue otra capa de modelo y vuelva a entrenar para obtener la predicción final del modelo.

En esencia, el apilamiento es una idea tan directa, pero a veces es un pequeño problema si el conjunto de entrenamiento y el conjunto de prueba no se distribuyen uniformemente. El problema es que las etiquetas entrenadas con el modelo inicial se vuelven a entrenar con etiquetas reales. No hay duda de que causará que cierto modelo sobreajuste el conjunto de entrenamiento, por lo que tal vez la capacidad de generalización o el efecto del modelo en el conjunto de prueba se reducirá en cierta medida, por lo que la pregunta ahora es cómo reducir el sobreajuste del reentrenamiento Aquí, generalmente tenemos dos métodos.

    1. Intente elegir un modelo lineal simple para el modelo secundario.
    1. Validación cruzada usando K-fold

Validación cruzada K-fold: Entrenamiento:

Imagen

Pronóstico:

# Stacking融合(回归)

from sklearn import linear_model

def Stacking_method(train_reg1,train_reg2,train_reg3,y_train_true,test_pre1,test_pre2,test_pre3,model_L2= linear_model.LinearRegression()):
    model_L2.fit(pd.concat([pd.Series(train_reg1),pd.Series(train_reg2),pd.Series(train_reg3)],axis=1).values,y_train_true)
    Stacking_result = model_L2.predict(pd.concat([pd.Series(test_pre1),pd.Series(test_pre2),pd.Series(test_pre3)],axis=1).values)
    return Stacking_result



## 生成一些简单的样本数据,test_prei 代表第i个模型的预测值
train_reg1 = [3.2, 8.2, 9.1, 5.2]
train_reg2 = [2.9, 8.1, 9.0, 4.9]
train_reg3 = [3.1, 7.9, 9.2, 5.0]
# y_test_true 代表第模型的真实值
y_train_true = [3, 8, 9, 5] 

test_pre1 = [1.2, 3.2, 2.1, 6.2]
test_pre2 = [0.9, 3.1, 2.0, 5.9]
test_pre3 = [1.1, 2.9, 2.2, 6.0]

# y_test_true 代表第模型的真实值
y_test_true = [1, 3, 2, 6] 



model_L2= linear_model.LinearRegression()
Stacking_pre = Stacking_method(train_reg1,train_reg2,train_reg3,y_train_true,
                               test_pre1,test_pre2,test_pre3,model_L2)
print('Stacking_pre MAE:',metrics.mean_absolute_error(y_test_true, Stacking_pre))

Apilamiento clasificado \ Fusión de mezcla

El apilamiento es un marco de integración de modelo en capas.

Tomando dos capas como ejemplo, la primera capa está compuesta de múltiples alumnos de base, cuya entrada es el conjunto de entrenamiento original, y el modelo de la segunda capa utiliza la salida de la primera capa de alumnos de base como el conjunto de entrenamiento para el reentrenamiento, a fin de obtener una completa El modelo de apilamiento, ambos modelos de apilamiento utilizan todos los datos de entrenamiento.

'''
5-Fold Stacking
'''
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import ExtraTreesClassifier,GradientBoostingClassifier
import pandas as pd
#创建训练的数据集
data_0 = iris.data
data = data_0[:100,:]

target_0 = iris.target
target = target_0[:100]

#模型融合中使用到的各个单模型
clfs = [LogisticRegression(solver='lbfgs'),
        RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='gini'),
        ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='gini'),
        ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='entropy'),
        GradientBoostingClassifier(learning_rate=0.05, subsample=0.5, max_depth=6, n_estimators=5)]
 
#切分一部分数据作为测试集
X, X_predict, y, y_predict = train_test_split(data, target, test_size=0.3, random_state=2020)

dataset_blend_train = np.zeros((X.shape[0], len(clfs)))
dataset_blend_test = np.zeros((X_predict.shape[0], len(clfs)))

#5折stacking
n_splits = 5
skf = StratifiedKFold(n_splits)
skf = skf.split(X, y)

for j, clf in enumerate(clfs):
    #依次训练各个单模型
    dataset_blend_test_j = np.zeros((X_predict.shape[0], 5))
    for i, (train, test) in enumerate(skf):
        #5-Fold交叉训练,使用第i个部分作为预测,剩余的部分来训练模型,获得其预测的输出作为第i部分的新特征。
        X_train, y_train, X_test, y_test = X[train], y[train], X[test], y[test]
        clf.fit(X_train, y_train)
        y_submission = clf.predict_proba(X_test)[:, 1]
        dataset_blend_train[test, j] = y_submission
        dataset_blend_test_j[:, i] = clf.predict_proba(X_predict)[:, 1]
    #对于测试集,直接用这k个模型的预测值均值作为新的特征。
    dataset_blend_test[:, j] = dataset_blend_test_j.mean(1)
    print("val auc Score: %f" % roc_auc_score(y_predict, dataset_blend_test[:, j]))

clf = LogisticRegression(solver='lbfgs')
clf.fit(dataset_blend_train, y)
y_submission = clf.predict_proba(dataset_blend_test)[:, 1]

print("Val auc Score of Stacking: %f" % (roc_auc_score(y_predict, y_submission)))

 

La fusión, de hecho, es una forma similar de fusión de modelos de múltiples capas con apilamiento

La idea principal es dividir el conjunto de entrenamiento original en dos partes, por ejemplo, el 70% de los datos se usa como el nuevo conjunto de entrenamiento, y el 30% restante de los datos se usa como el conjunto de prueba.

En la primera capa, entrenamos múltiples modelos en los datos del 70%, y luego predecimos la etiqueta de los datos del 30%, y también predecimos la etiqueta del conjunto de prueba.

En la segunda capa, usamos directamente los resultados de la predicción de datos del 30% en la primera capa como nuevas características para continuar el entrenamiento, y luego usamos el conjunto de prueba para predecir la primera capa de la etiqueta como la característica, y usamos el modelo entrenado en la segunda capa para una predicción adicional.

Las ventajas son:

  • 1. Más simple que el apilamiento (porque no se necesita validación cruzada de k veces para obtener las características del apilador)
  • 2. Para evitar un problema de fuga de información: los generadores y el apilador utilizan diferentes conjuntos de datos

Las desventajas son:

  • 1. Se utilizan muy pocos datos (la licuadora en la segunda etapa solo usa el conjunto de entrenamiento 10%)
  • 2. Blender puede sobreajustar
  • 3.Apilar usando validación cruzada múltiple será más robusto ''
'''
Blending
'''
 
#创建训练的数据集
#创建训练的数据集
data_0 = iris.data
data = data_0[:100,:]

target_0 = iris.target
target = target_0[:100]
 
#模型融合中使用到的各个单模型
clfs = [LogisticRegression(solver='lbfgs'),
        RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='gini'),
        RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='entropy'),
        ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='gini'),
        #ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='entropy'),
        GradientBoostingClassifier(learning_rate=0.05, subsample=0.5, max_depth=6, n_estimators=5)]
 
#切分一部分数据作为测试集
X, X_predict, y, y_predict = train_test_split(data, target, test_size=0.3, random_state=2020)

#切分训练数据集为d1,d2两部分
X_d1, X_d2, y_d1, y_d2 = train_test_split(X, y, test_size=0.5, random_state=2020)
dataset_d1 = np.zeros((X_d2.shape[0], len(clfs)))
dataset_d2 = np.zeros((X_predict.shape[0], len(clfs)))
 
for j, clf in enumerate(clfs):
    #依次训练各个单模型
    clf.fit(X_d1, y_d1)
    y_submission = clf.predict_proba(X_d2)[:, 1]
    dataset_d1[:, j] = y_submission
    #对于测试集,直接用这k个模型的预测值作为新的特征。
    dataset_d2[:, j] = clf.predict_proba(X_predict)[:, 1]
    print("val auc Score: %f" % roc_auc_score(y_predict, dataset_d2[:, j]))

#融合使用的模型
clf = GradientBoostingClassifier(learning_rate=0.02, subsample=0.5, max_depth=6, n_estimators=30)
clf.fit(dataset_d1, y_d2)
y_submission = clf.predict_proba(dataset_d2)[:, 1]
print("Val auc Score of Blending: %f" % (roc_auc_score(y_predict, y_submission)))

Fusión de apilamiento clasificada (usando mlxtend)

!pip install mlxtend

import warnings
warnings.filterwarnings('ignore')
import itertools
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec

from sklearn import datasets
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB 
from sklearn.ensemble import RandomForestClassifier
from mlxtend.classifier import StackingClassifier

from sklearn.model_selection import cross_val_score
from mlxtend.plotting import plot_learning_curves
from mlxtend.plotting import plot_decision_regions

# 以python自带的鸢尾花数据集为例
iris = datasets.load_iris()
X, y = iris.data[:, 1:3], iris.target

clf1 = KNeighborsClassifier(n_neighbors=1)
clf2 = RandomForestClassifier(random_state=1)
clf3 = GaussianNB()
lr = LogisticRegression()
sclf = StackingClassifier(classifiers=[clf1, clf2, clf3], 
                          meta_classifier=lr)

label = ['KNN', 'Random Forest', 'Naive Bayes', 'Stacking Classifier']
clf_list = [clf1, clf2, clf3, sclf]

fig = plt.figure(figsize=(10,8))
gs = gridspec.GridSpec(2, 2)
grid = itertools.product([0,1],repeat=2)

clf_cv_mean = []
clf_cv_std = []
for clf, label, grd in zip(clf_list, label, grid):
        
    scores = cross_val_score(clf, X, y, cv=3, scoring='accuracy')
    print("Accuracy: %.2f (+/- %.2f) [%s]" %(scores.mean(), scores.std(), label))
    clf_cv_mean.append(scores.mean())
    clf_cv_std.append(scores.std())
        
    clf.fit(X, y)
    ax = plt.subplot(gs[grd[0], grd[1]])
    fig = plot_decision_regions(X=X, y=y, clf=clf)
    plt.title(label)

plt.show()

Se puede encontrar que el modelo base usa 'KNN', 'Random Forest', 'Naive Bayes' y luego, sobre la base del modelo secundario más una 'LogisticRegression', el efecto de la prueba del modelo se ha mejorado muy bien.

 

Resumen:

  • 1) Fusión en el nivel de resultado . Este es el método de fusión más común. Hay muchos métodos de fusión factibles, como la fusión ponderada basada en la puntuación del resultado y el procesamiento de registro y exp. Cuando se realiza la fusión de resultados, una condición importante es que los puntajes de los resultados del modelo deben ser relativamente similares y, a continuación, la diferencia en los resultados debe ser relativamente grande. Dicha fusión de resultados a menudo tiene un mejor efecto.

  • 2) Fusión de nivel de característica . Este nivel en realidad no se conoce como fusión. Se puede llamar segmentación con precisión. En muchos casos, si usamos el mismo entrenamiento de modelo, podemos dividir las características en diferentes modelos y luego realizar la fusión de modelo o resultado más tarde A veces puede producir mejores resultados.

  • 3) Fusión a nivel de modelo: la fusión a nivel de modelo puede incluir el apilamiento y el diseño de modelos, como agregar una capa de replanteo, y los resultados de algunos modelos como entradas de características. Estos requieren más experimentos y pensamiento, y la fusión basada en el nivel de modelo es mejor Los diferentes tipos de modelos tienen ciertas diferencias, y los beneficios de usar diferentes parámetros del mismo modelo son generalmente relativamente pequeños.

3. refuerzo / embolsado (ya utilizado en xgboost, Adaboost, GBDT):

  • Método de elevación de varios árboles

Materiales de referencia:

https://tianchi.aliyun.com/notebook-ai/detail?spm=5176.12586969.1002.15.1cd8593a4gdfJ6&postId=95535

 

21 artículos originales publicados · Me gusta1 · Visitantes 1823

Supongo que te gusta

Origin blog.csdn.net/wjsjjss/article/details/105316332
Recomendado
Clasificación