Tutorial práctico de aprendizaje automático (8): regresión polinómica

regresión polinómica

concepto

La regresión lineal estudia el problema de regresión entre una variable dependiente y una variable independiente.
La regresión polinómica se refiere a un método para ajustar datos no lineales agregando características no lineales sobre la base de una regresión lineal. El modelo de regresión polinómica puede utilizar una función polinómica de enésimo grado para describir aproximadamente la relación entre la variable objetivo y la variable de entrada. Por ejemplo, para el caso en el que solo hay una variable independiente
x, la función de ajuste se puede escribir como:
Insertar descripción de la imagen aquí
donde
y representa la variable objetivo y x representa la variable independiente, que
Insertar descripción de la imagen aquíes el parámetro del modelo. El objetivo del modelo es minimizar el error entre el valor predicho y el valor real ajustando los parámetros.

La regresión polinómica se puede implementar a través de la clase PolynomialFeatures de Scikit-Learn, que puede transformar los datos de la variable independiente original en nuevos datos de la variable independiente que contienen características polinómicas. De esta manera, podemos utilizar el algoritmo de regresión lineal para procesar las características no lineales aumentadas y obtener un modelo de regresión polinómica.

Ejemplo de ajuste

Generar datos de simulación polinómica y=3 x+2 x**2

import numpy as np
import matplotlib.pyplot as plt

x = np.random.uniform(-3, 3, size=100)
X = x.reshape(-1, 1)
y =  3*x+ 2*x**2+ np.random.normal(0, 1, size=100)
plt.scatter(x, y)
plt.show()

Insertar descripción de la imagen aquí
Si usa la regresión lineal directamente, observe el efecto:

from sklearn.linear_model import LinearRegression

lin_reg = LinearRegression()
lin_reg.fit(X, y)
y_predict = lin_reg.predict(X)
plt.scatter(x, y)
plt.plot(x, y_predict, color='r')
plt.show()

Insertar descripción de la imagen aquí
Evidentemente, el efecto de adaptación no es bueno. Entonces ¿cuál es la solución?
Solución: agregue una función. x**2

X2 = np.hstack([X, X**2])
lin_reg2 = LinearRegression()
lin_reg2.fit(X2, y)
y_predict2 = lin_reg2.predict(X2)
plt.scatter(x, y)
plt.plot(np.sort(x), y_predict2[np.argsort(x)], color='r')
plt.show()

Insertar descripción de la imagen aquí
Esto es mucho mejor que un ajuste en línea recta, la pendiente y la intersección lo son.

[2.9391452  1.94366894]
0.04332751905483523

Regresión polinomial en scikit-learn

polinomioCaracterísticas

polynomialFeatures es una función en Scikit-Learn que se utiliza para convertir datos de entrada en un conjunto de características polinómicas. Su función es ajustar datos no lineales agregando características no lineales al realizar una regresión lineal en datos no lineales.

Específicamente, la función PolynomialFeatures convierte el vector de características original en un nuevo vector de características que contiene todas las combinaciones polinómicas. Por ejemplo, si el vector de características original es [a,b] y se usa grado = 2, entonces el nuevo vector de características generado por PolynomialFeatures es [1,a,b,a^2, ab,b^2]. Si el vector de características original es [x] y se usa grado = 2, entonces el nuevo vector de características generado por PolynomialFeatures es [1,x,x^2]

De esta manera, dado que el nuevo vector propio contiene todos los polinomios del vector propio original, la función no lineal se puede ajustar mejor.

Las características polinómicas tienen principalmente los siguientes parámetros:

  • Grado: representa el grado del polinomio, lo que determina cuántos términos de grado se generará el polinomio.
  • solo interacción: el valor predeterminado es Falso, lo que indica que el nuevo vector de características contiene términos cruzados y términos de orden superior, como a×b, a^2, etc.
  • include_bias: el valor predeterminado es Verdadero, lo que indica si se debe crear una columna de sesgo.

En resumen, PolynomialFeatures es una función muy útil que puede ayudarnos a manejar mejor los datos no lineales, mejorando así el poder predictivo del modelo.

from sklearn.preprocessing import PolynomialFeatures
# 这个degree表示我们使用多少次幂的多项式
poly = PolynomialFeatures(degree=2)    
poly.fit(X)
X2 = poly.transform(X)
print(X2.shape)
print(X2)

Resultado de salida (la primera columna es la constante 1, la segunda columna es la x anterior y la tercera columna es x**2):


(100, 3)
[[ 1.00000000e+00 -2.37462045e+00  5.63882230e+00]
 [ 1.00000000e+00 -7.90962247e-01  6.25621276e-01]
 [ 1.00000000e+00 -7.02888543e-01  4.94052304e-01]
 [ 1.00000000e+00 -6.54589498e-01  4.28487411e-01]]

Utilice regresión lineal para ajustar

from sklearn.linear_model import LinearRegression
reg = LinearRegression() 
reg.fit(X2, y)
y_predict = reg.predict(X2) 
plt.scatter(x, y) 
plt.plot(np.sort(x), y_predict2[np.argsort(x)], color='r')
plt.show()
print(lin_reg2.coef_)
# array([0.90802935, 1.04112467])
print(lin_reg2.intercept_)

Insertar descripción de la imagen aquí
Intercepción y pendiente de salida

[3.02468873 1.94228967]
0.41539122650325755

Anteriormente usábamos datos unidimensionales, ¿qué pasa si usamos datos bidimensionales, tridimensionales o incluso de dimensiones superiores?
Generar datos bidimensionales (1 a 10, convertidos a 5 filas y 2 columnas)

import numpy as np
x = np.arange(1, 11).reshape(5, 2)
print(x)

producción

[[ 1  2]
 [ 3  4]
 [ 5  6]
 [ 7  8]
 [ 9 10]]

Construido usando características polinómicas

from sklearn.preprocessing import PolynomialFeatures
poly = PolynomialFeatures()
poly.fit(x)
x2 = poly.transform(x)
print(x2)

producción

[[  1.   1.   2.   1.   2.   4.]
 [  1.   3.   4.   9.  12.  16.]
 [  1.   5.   6.  25.  30.  36.]
 [  1.   7.   8.  49.  56.  64.]
 [  1.   9.  10.  81.  90. 100.]]

En este momento, se puede ver que cuando la dimensión de datos es de 2 dimensiones, se generan datos de 6 dimensiones después del preprocesamiento polinomial. La primera columna es obviamente el coeficiente del término de orden 0, y la segunda y tercera columnas también son fáciles de Entiendo, respectivamente x1, x2, las columnas cuarta y sexta son x1 2 y x2 2 respectivamente, y hay otra columna, que en realidad es x1 * x2, esta es la quinta columna, un total de 6 columnas. A partir de esto, ¿puedes adivinar qué pasará si los datos son tridimensionales?

poly = PolynomialFeatures(degree=3)
poly.fit(x)
x3 = poly.transform(x)
print(x3)

producción

[[   1.    1.    2.    1.    2.    4.    1.    2.    4.    8.]
 [   1.    3.    4.    9.   12.   16.   27.   36.   48.   64.]
 [   1.    5.    6.   25.   30.   36.  125.  150.  180.  216.]
 [   1.    7.    8.   49.   56.   64.  343.  392.  448.  512.]
 [   1.    9.   10.   81.   90.  100.  729.  810.  900. 1000.]]

Insertar descripción de la imagen aquí
Entonces, ¿a qué corresponden estas 10 columnas? A través de PolynomiaFeatures, todas las combinaciones posibles aumentan exponencialmente en dimensionalidad. Esto también causará ciertos problemas. ¿Cómo afrontar este crecimiento explosivo? Si no lo controla, imagine que la diferencia entre x y x [^ 100] es demasiado grande. Este es el legendario sobreajuste.

Tubería en sklearn

Pipeline en sklearn es una herramienta que puede conectar múltiples pasos de preprocesamiento de datos (transformador) y un modelo de aprendizaje automático (estimador) para formar un proceso completo de aprendizaje automático. Cada paso en Pipeline es un objeto que contiene métodos de ajuste y transformación, donde el método de ajuste se usa para ajustar los datos de entrenamiento y el método de transformación se usa para transformar los datos.

A través de Pipeline, se pueden combinar múltiples algoritmos de preprocesamiento y algoritmos de aprendizaje automático, estandarizando y simplificando todo el proceso, y se pueden realizar fácilmente operaciones como la validación cruzada y el ajuste de parámetros. Cada paso del Pipeline se puede identificar mediante una cadena, que se puede utilizar para ajustar los hiperparámetros en el modelo.

Pipeline se utiliza generalmente para la ingeniería de características en el aprendizaje automático: construye un proceso completo de aprendizaje automático durante el preprocesamiento de datos y lo aplica al conjunto de entrenamiento y al conjunto de prueba. Al combinar varios pasos, se evitan varias combinaciones manuales de ingeniería de características y selección de modelos, al tiempo que también se mejoran la reutilización y el mantenimiento del código.

En general, para la regresión polinómica, normalizamos los datos , luego realizamos una mejora de la dimensionalidad polinómica y luego realizamos una regresión lineal. Debido a que la regresión polinómica no está encapsulada en sklearn, puedes usar Pipeline para integrar estas operaciones.

#%%

import numpy as np
import matplotlib.pyplot as plt

x = np.random.uniform(-3, 3, size=100)
X = x.reshape(-1, 1)
y =  3*x+ 2*x**2+ np.random.normal(0, 1, size=100)
plt.scatter(x, y)
plt.show()

#%%

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler

poly_reg = Pipeline([
    ('poly', PolynomialFeatures(degree=2)),   
    ('std_scale', StandardScaler()),
    ('lin_reg', LinearRegression())
])  
poly_reg.fit(X, y)
y_predict = poly_reg.predict(X)

plt.scatter(x, y)
plt.plot(np.sort(x), y_predict[np.argsort(x)], color='r')
plt.show()

Sobreajuste y desajuste

La mayor ventaja de la regresión polinómica es que puede aproximarse al punto medido sumando términos de orden superior de x hasta que sea satisfactorio. Pero esta es también su mayor deficiencia, porque generalmente si intenta ajustar los datos con dimensiones demasiado altas, obtendrá un buen rendimiento en el conjunto de entrenamiento, pero el conjunto de prueba puede no ser tan ideal, por lo que es una forma de resolver el sobreajuste.

error cuadrático medio

mean_squared_error es una función utilizada para calcular el error cuadrático medio (MSE) entre dos matrices. Es una métrica común para evaluar la precisión de los modelos de regresión.
Los parámetros de entrada de esta función incluyen:

  • y_true: matriz de valor verdadero;
  • y_pred: matriz de valores predichos;
  • sample_weight: matriz utilizada para ponderar la muestra. No es necesario pasarla. El valor predeterminado es Ninguno.

La función devuelve un valor numérico que representa el error cuadrático medio entre las dos matrices.

El error cuadrático medio es un indicador ampliamente utilizado en modelos de regresión para medir la capacidad predictiva del modelo. Cuanto menor sea el error cuadrático medio, más precisa será la predicción del modelo. Su definición es: sumar las desviaciones entre el valor predicho de cada muestra y el valor verdadero después de elevarlo al cuadrado, y luego dividirlo por el número total de muestras para obtener el valor promedio, es decir
Insertar descripción de la imagen aquí

Cuanto menor sea el error cuadrático medio, más precisa será la capacidad de predicción del modelo.

Efecto de ajuste

Después de utilizar el mismo método para generar el conjunto de datos, utilizamos diferentes métodos de ajuste y utilizamos el error cuadrático medio para comparar los efectos de varios ajustes.

ajuste lineal

from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error
lin_reg = LinearRegression()
lin_reg.fit(X, y)
y_predict = lin_reg.predict(X)
plt.scatter(x, y)
plt.plot(np.sort(x), y_predict[np.argsort(x)], color='r')
plt.show()
print("线性均方误差",mean_squared_error(y, y_predict))

Salida: 3.0750025765636577
Obviamente, si se usa directamente una regresión lineal simple, el resultado del ajuste es un ajuste insuficiente.
Insertar descripción de la imagen aquí

Ajuste polinomial cuadrático

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler

def PolynomialRegression(degree):
    return Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('std_scale', StandardScaler()),
        ('lin_reg', LinearRegression())
    ])  

poly_reg = PolynomialRegression(degree=2)
poly_reg.fit(X, y)
Pipeline(memory=None,
     steps=[('poly', PolynomialFeatures(degree=2, include_bias=True, interaction_only=False)), ('std_scale', StandardScaler(copy=True, with_mean=True, with_std=True)), ('lin_reg', LinearRegression(copy_X=True, fit_intercept=True, n_jobs=None,
         normalize=False))])
y_predict = poly_reg.predict(X)
print("2次多项式均方误差",mean_squared_error(y, y_predict))
plt.scatter(x, y)
plt.plot(np.sort(x), y_predict[np.argsort(x)], color='r')
plt.show()

Salida: 1.0987392142417856
La regresión polinómica cuadrática tiene un mejor ajuste que la regresión lineal.
Insertar descripción de la imagen aquí

Ajuste polinomial deca

poly10_reg = PolynomialRegression(degree=10)
poly10_reg.fit(X, y)

y10_predict = poly10_reg.predict(X)
print("10次多项式均方误差",mean_squared_error(y, y10_predict))
plt.scatter(x, y)
plt.plot(np.sort(x), y10_predict[np.argsort(x)], color='r')
plt.show()

Salida: 1.0508466763764202
Insertar descripción de la imagen aquí

Ajuste polinómico de cien grados

poly10_reg = PolynomialRegression(degree=100)
poly10_reg.fit(X, y)

y10_predict = poly10_reg.predict(X)
print("100次多项式均方误差",mean_squared_error(y, y10_predict))
plt.scatter(x, y)
plt.plot(np.sort(x), y10_predict[np.argsort(x)], color='r')
plt.show()

Salida: 0,6870911922673567
Insertar descripción de la imagen aquí

Prueba de conjunto de datos de generación de polinomios de cien grados

En el gráfico anterior, podemos ver que los valores de y predichos por los datos generados por uniforme están entre -1 y 10. Usamos el mismo modelo para predecir el valor de x = 3.

y_plot = poly100_reg.predict([[3]])
print(y_plot)

Salida: [-2.49133715e+06 -6.32965634e+24]
Conversión: -2.49133715e+06==-2491337.16790313

Después de encontrar> = 3, si sigues la forma de este menisco, obviamente es anormal.
Generamos una secuencia aritmética como conjunto de prueba.

from sklearn.preprocessing import PolynomialFeatures
x_plot = np.linspace(-3, 3, 100).reshape(100, 1)
y_plot = poly100_reg.predict(x_plot)
plt.scatter(x, y)
plt.plot(x_plot[:,0], y_plot, color='r')
# plt.axis([-3, 3, -1, 10])
plt.show()

Insertar descripción de la imagen aquí
De esta manera, los gráficos se estropean porque x = 3. Tomamos capturas de pantalla de los gráficos x de -3 a 3 e y de -1 a 10.

from sklearn.preprocessing import PolynomialFeatures
x_plot = np.linspace(-3, 3, 100).reshape(100, 1)
y_plot = poly100_reg.predict(x_plot)
plt.scatter(x, y)
plt.plot(x_plot[:,0], y_plot, color='r')
plt.axis([-3, 3, -1, 10])
plt.show()

Insertar descripción de la imagen aquí

Muestra que el modelo entrenado a través del conjunto de entrenamiento no tiene una buena capacidad de desempeño en el conjunto de prueba.

Resuelve el problema del sobreajuste

Por lo general, en el proceso de aprendizaje automático, el principal problema es el sobreajuste, porque implica la capacidad de generalización del modelo. La llamada capacidad de generalización significa que el modelo puede dar buenas respuestas al verificar datos fuera del conjunto de entrenamiento. No tiene sentido qué tan bien se ajusta a los datos en el conjunto de entrenamiento y qué tan buena es la capacidad de generalización del modelo que necesitamos.

¿Por qué necesitamos un conjunto de datos de entrenamiento y un conjunto de datos de prueba?

Por lo general, dividimos el conjunto de datos en un conjunto de entrenamiento y un conjunto de prueba. Tiene sentido si el modelo entrenado a través de los datos de entrenamiento puede funcionar mejor en el conjunto de prueba.

Lo siguiente usa train_test_split para dividir los datos generados en un conjunto de entrenamiento y un conjunto de prueba, regenerar el modelo y calcular el error cuadrático medio
usando regresión lineal.

from sklearn.model_selection import train_test_split
import numpy as np
import matplotlib.pyplot as plt

np.random.seed(666)
np.random.seed(666)
x = np.random.uniform(-3.0, 3.0, size=100)
X = x.reshape(-1, 1)
y = 0.5 * x**2 + x + 2 + np.random.normal(0, 1, size=100)

x_train, x_test, y_train, y_test = train_test_split(X, y, random_state=666)
lin_reg = LinearRegression()
lin_reg.fit(x_train, y_train)
y_predict = lin_reg.predict(x_test)
mean_squared_error(y_test, y_predict)

Resultado de salida: 2.2199965269396573

utilizar binomio

from sklearn.pipeline import Pipeline
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import StandardScaler

def PolynomialRegression(degree):
    return Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('std_scale', StandardScaler()),
        ('lin_reg', LinearRegression())
    ])
poly2_reg = PolynomialRegression(degree=2)
poly2_reg.fit(x_train, y_train)
y2_predict = poly2_reg.predict(x_test)
mean_squared_error(y_test, y2_predict)

Resultado de salida: 0,8035641056297901

Utilice 10 nominales

poly10_reg = PolynomialRegression(degree=10)
poly10_reg.fit(x_train, y_train)
y10_predict = poly10_reg.predict(x_test)
mean_squared_error(y_test, y10_predict)

Resultado de salida: 0,9212930722150781

En el ejemplo anterior, podemos encontrar que cuando grado = 2, el error cuadrático medio en el conjunto de prueba es mucho mejor que el del ajuste en línea recta, pero cuando grado = 10, el error cuadrático medio en el conjunto de prueba es relativamente mejor que grado = 2. El efecto es mucho peor, lo que significa que el modelo entrenado se ha sobreajustado.

100 términos

poly100_reg = PolynomialRegression(degree=100)
poly100_reg.fit(x_train, y_train)
y100_predict = poly100_reg.predict(x_test)
mean_squared_error(y_test, y100_predict)

Resultado de salida: 14440175276.314638
Insertar descripción de la imagen aquí

Resumen: encuentre el lugar con la mejor capacidad de generalización entre la complejidad y la precisión del modelo.

  1. Desajuste: desajuste, el modelo entrenado por el algoritmo no puede expresar completamente la relación de datos.
  2. Sobreajuste: sobreajuste, el modelo entrenado por el algoritmo expresa demasiado la relación de ruido entre los datos.
    Insertar descripción de la imagen aquí

curva de aprendizaje

La curva de aprendizaje del aprendizaje automático es una forma de representar gráficamente el rendimiento de un algoritmo de aprendizaje automático en datos de entrenamiento. Por lo general, toma el tamaño del conjunto de datos de entrenamiento o el número de iteraciones de entrenamiento como eje horizontal y toma los indicadores de rendimiento del modelo. (como precisión, error, etc.) como el eje vertical. Esta curva puede ayudarnos a comprender el proceso de aprendizaje del algoritmo, evaluar el efecto de aprendizaje y ajustar el modelo.

A medida que aumenta el conjunto de datos de entrenamiento, esperamos ver que el rendimiento del modelo continúe mejorando; si el rendimiento es bueno en el conjunto de entrenamiento pero no bueno en el conjunto de prueba, indica que ha ocurrido un problema de sobreajuste; por el contrario, Si el rendimiento tanto del conjunto de entrenamiento como del conjunto de prueba no es bueno, es posible que deba reconsiderar cuestiones como el preprocesamiento de datos, la ingeniería de funciones y la estructura del modelo.

Los conceptos relacionados con las curvas de aprendizaje también incluyen sesgo y varianza, que a menudo se utilizan para diagnosticar y ajustar modelos. Cuando la desviación del modelo es grande, significa que el modelo es demasiado simple y no puede ajustarse con precisión al conjunto de entrenamiento y al conjunto de pruebas, y es necesario aumentar la complejidad del modelo; cuando la varianza del modelo es grande, significa que la El modelo es demasiado complejo y hay un problema de sobreajuste, es necesario reducir la complejidad del modelo o aumentar el tamaño del conjunto de datos de entrenamiento.

Intentamos dividir todo el conjunto de datos en un conjunto de entrenamiento y una máquina de prueba. El tamaño del conjunto de entrenamiento aumenta de 1 a len (conjunto de entrenamiento) y genera un modelo correspondiente al conjunto de entrenamiento (usando regresión lineal, polinomio de segundo grado). , polinomio de 100 grados), utilice el mismo conjunto de pruebas para probar el modelo correspondiente y grábelo como x=el número de conjuntos de entrenamiento, y=error cuadrático medio para ver el subajuste (regresión lineal), el mejor ajuste (binomial) y el sobreajuste. (20 términos)

La función para dibujar la curva de aprendizaje se resume a continuación para poder llamarla fácilmente más adelante.


def plot_learning_curve(algo, x_train, x_test, y_train, y_test):

    train_score = []
    test_score = []
    for i in range(1, len(x_train)+1):
        algo.fit(x_train[:i], y_train[:i])

        y_train_predict = algo.predict(x_train[:i])
        train_score.append(mean_squared_error(y_train[:i], y_train_predict))

        y_test_predict = algo.predict(x_test)
        test_score.append(mean_squared_error(y_test, y_test_predict))

    plt.plot([i for i in range(1, len(x_train)+1)], np.sqrt(train_score), label='train')
    plt.plot([i for i in range(1, len(x_train)+1)], np.sqrt(test_score), label='test')
    plt.legend()
    plt.axis([0, len(x_train)+1, 0, 4])
    plt.show()
plot_learning_curve(LinearRegression(), x_train, x_test, y_train, y_test)

Generar conjunto de datos

np.random.seed(666)
np.random.seed(666)
x = np.random.uniform(-3.0, 3.0, size=100)
X = x.reshape(-1, 1)
y = 0.5 * x**2 + x + 2 + np.random.normal(0, 1, size=100)

x_train, x_test, y_train, y_test = train_test_split(X, y, random_state=10)

Al utilizar la regresión lineal, la imagen no está ajustada (el ajuste insuficiente significa que el modelo no puede obtener un error lo suficientemente bajo en el conjunto de entrenamiento) y el error de los datos de entrenamiento ha alcanzado 2,0. Al utilizar la revisión binomial, la imagen es la que mejor se ajusta
Insertar descripción de la imagen aquí
.

def PolynomialRegression(degree):
    return Pipeline([
        ('poly', PolynomialFeatures(degree=degree)),
        ('std_scale', StandardScaler()),
        ('lin_reg', LinearRegression())
    ])
poly2_reg = PolynomialRegression(degree=2)
plot_learning_curve(poly2_reg, x_train, x_test, y_train, y_test)

Insertar descripción de la imagen aquí
Usando 20 términos, sobreajuste (sobreajuste significa que el modelo funciona bien en el conjunto de entrenamiento, pero funciona mal en el conjunto de prueba)

poly2_reg = PolynomialRegression(degree=20)
plot_learning_curve(poly2_reg, x_train, x_test, y_train, y_test)

Insertar descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/liaomin416100569/article/details/130227742
Recomendado
Clasificación