Regresión¶
Los objetivos de esta clase son:
Comprender/recordar regresión lineal.
Estimar el error al aplicar modelos matemáticos a los datos.
Introducir la librería scikit-learn.
Otros tipos de regresión.
Motivación¶
La regresión lineal es una técnica universalmente utilizada y a pesar de su simpletaza, la derivación de este método entrega importantes consideraciones sobre su implementación, sus hipótesis y sus posibles extensiones.
Para motivar el estudio utilizaremos datos de diabetes disponibles en la biblioteca scikit learn.
import numpy as np
import pandas as pd
import altair as alt
from sklearn import datasets
alt.themes.enable('opaque') # Para quienes utilizan temas oscuros en Jupyter Lab
ThemeRegistry.enable('opaque')
diabetes_X, diabetes_y = datasets.load_diabetes(return_X_y=True, as_frame=True)
diabetes = pd.concat([diabetes_X, diabetes_y], axis=1)
diabetes.head()
age | sex | bmi | bp | s1 | s2 | s3 | s4 | s5 | s6 | target | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | 0.038076 | 0.050680 | 0.061696 | 0.021872 | -0.044223 | -0.034821 | -0.043401 | -0.002592 | 0.019908 | -0.017646 | 151.0 |
1 | -0.001882 | -0.044642 | -0.051474 | -0.026328 | -0.008449 | -0.019163 | 0.074412 | -0.039493 | -0.068330 | -0.092204 | 75.0 |
2 | 0.085299 | 0.050680 | 0.044451 | -0.005671 | -0.045599 | -0.034194 | -0.032356 | -0.002592 | 0.002864 | -0.025930 | 141.0 |
3 | -0.089063 | -0.044642 | -0.011595 | -0.036656 | 0.012191 | 0.024991 | -0.036038 | 0.034309 | 0.022692 | -0.009362 | 206.0 |
4 | 0.005383 | -0.044642 | -0.036385 | 0.021872 | 0.003935 | 0.015596 | 0.008142 | -0.002592 | -0.031991 | -0.046641 | 135.0 |
En este conjunto la variable a predecir (target) es una medida cuantitativa de la progresión de la enfermedad un año después de la línea base. Contiene 10 características (features) numéricas, definidas en la siguienta tabla. Cada una de estas ha sido centrada y escalada por su desviación estandar multiplicada por la cantidad de muestras, i.e. la suma de cuadrados de cada columna es 1, que en la prácitca es que tengan norma unitaria.
Feature |
Descripción |
---|---|
age |
age in years |
sex |
sex |
bmi |
body mass index |
bp |
average blood pressure |
s1 |
tc, T-Cells (a type of white blood cells) |
s2 |
ldl, low-density lipoproteins |
s3 |
hdl, high-density lipoproteins |
s4 |
tch, thyroid stimulating hormone |
s5 |
ltg, lamotrigine |
s6 |
glu, blood sugar level |
A continuación exploremos los datos
diabetes.describe().T
count | mean | std | min | 25% | 50% | 75% | max | |
---|---|---|---|---|---|---|---|---|
age | 442.0 | -3.639623e-16 | 0.047619 | -0.107226 | -0.037299 | 0.005383 | 0.038076 | 0.110727 |
sex | 442.0 | 1.309912e-16 | 0.047619 | -0.044642 | -0.044642 | -0.044642 | 0.050680 | 0.050680 |
bmi | 442.0 | -8.013951e-16 | 0.047619 | -0.090275 | -0.034229 | -0.007284 | 0.031248 | 0.170555 |
bp | 442.0 | 1.289818e-16 | 0.047619 | -0.112400 | -0.036656 | -0.005671 | 0.035644 | 0.132044 |
s1 | 442.0 | -9.042540e-17 | 0.047619 | -0.126781 | -0.034248 | -0.004321 | 0.028358 | 0.153914 |
s2 | 442.0 | 1.301121e-16 | 0.047619 | -0.115613 | -0.030358 | -0.003819 | 0.029844 | 0.198788 |
s3 | 442.0 | -4.563971e-16 | 0.047619 | -0.102307 | -0.035117 | -0.006584 | 0.029312 | 0.181179 |
s4 | 442.0 | 3.863174e-16 | 0.047619 | -0.076395 | -0.039493 | -0.002592 | 0.034309 | 0.185234 |
s5 | 442.0 | -3.848103e-16 | 0.047619 | -0.126097 | -0.033249 | -0.001948 | 0.032433 | 0.133599 |
s6 | 442.0 | -3.398488e-16 | 0.047619 | -0.137767 | -0.033179 | -0.001078 | 0.027917 | 0.135612 |
target | 442.0 | 1.521335e+02 | 77.093005 | 25.000000 | 87.000000 | 140.500000 | 211.500000 | 346.000000 |
diabetes.apply(np.linalg.norm)
age 1.000000
sex 1.000000
bmi 1.000000
bp 1.000000
s1 1.000000
s2 1.000000
s3 1.000000
s4 1.000000
s5 1.000000
s6 1.000000
target 3584.818126
dtype: float64
También es interesante ver como se relaciona cada feature con el target.
base = alt.Chart(diabetes).mark_circle().encode(
x=alt.X(alt.repeat("row"), type='quantitative'),
y="target"
).properties(
width=300,
height=300
)
base.repeat(row=diabetes_X.columns.tolist()[:4]) | base.repeat(row=diabetes_X.columns.tolist()[4:7]) | base.repeat(row=diabetes_X.columns.tolist()[7:])
Modelo¶
Supondremos que tenemos \(m\) datos.
Cada dato \(x^{(i)}\), \(i=1,\dots,\) \(m\) tiene \(n\) componentes, \(x^{(i)} = (x^{(i)}_1, ..., x^{(i)}_n)\).
Conocemos además el valor (etiqueta) asociado a \(x^{(i)}\) que llamaremos \(y^{(i)}\), \(i=1,\dots, m\) .
Nuestra hipótesis de modelo lineal puede escribirse como
Definiremos \(x^{(i)}_0 =1\), de modo que \(h_{\theta}(x^{(i)}) = (x^{(i)})^T \theta \) y buscamos el vector de parámetros $\(\theta = \begin{bmatrix}\theta_0 \\ \theta_1 \\ \theta_2 \\ \vdots \\ \theta_n\end{bmatrix}\)$
Definamos las matrices
y
Luego la evaluación de todos los datos puede escribirse matricialmente como
Nuestro problema es encontrar un “buen” conjunto de valores \(\theta\) de modo que
es decir, que $\(X \theta \approx Y\)$
Para encontrar el mejor vector \(\theta\) podríamos definir una función de costo \(J(\theta)\) de la siguiente manera:
Implementaciones¶
Aproximación Ingenieril¶
¿Cómo podemos resolver el problema en el menor número de pasos?
Deseamos resolver el sistema $\(A \theta = b\)\( con \)A \in \mathbb{R}^{m \times n}\( y \)m > n\( (La matrix \)A$ es skinny).
¿Cómo resolvemos?
Bueno, si \(A \in \mathbb{R}^{m \times n}\), entonces \(A^T \in \mathbb{R}^{n \times m}\) y la multiplicación está bien definida y obtengo el siguiente sistema lineal, conocido como Ecuación Normal: \(n \times n\). $\((A^T A) \ \theta = A^T b\)$
Si la matriz \(A^T A\) es invertible, el sistema se puede solucionar “sin mayor reparo”. $\(\theta = (A^T A)^{-1} A^T b\)$
En nuestro caso, obtendríamos $\(\theta = (X^T X)^{-1} X^T Y\)$ Esta respuesta, aunque correcta, no admite interpretaciones y no permite generalizar a otros casos más generales.
En particular…
¿Qué relación tiene con la función de costo (no) utilizada?
¿Qué pasa si \(A^T A\) no es invertible?
Aproximación Machine Learning¶
¿Cómo podemos obtener una buena aproximación para \(\theta\)?
Queremos encontrar \(\theta^*\) que minimice \(J(\theta)\).
Basta con utilizar una buena rutina de optimización para cumplir con dicho objetivo.
En particular, una elección natural es tomar la dirección de mayor descenso, es decir, el método del máximo descenso (gradient descent).
donde \(\alpha >0\) es la tasa de aprendizaje.
En nuestro caso, puesto que tenemos $\(J(\theta) = \frac{1}{2} \sum_{i=1}^{m} \left( h_{\theta}(x^{(i)}) - y^{(i)}\right)^2\)$ se tiene que
Luego, el algoritmo queda como sigue: $\(\begin{aligned} \theta^{(n+1)} & = \theta^{(n)} - \alpha \nabla_{\theta} J(\theta^{(n)}) \\\\ \frac{\partial J(\theta)}{\partial \theta_k} &= \sum_{i=1}^{m} \left( h_{\theta}(x^{(i)}) - y^{(i)}\right) x^{(i)}_k\end{aligned}\)$
Observación: La elección de \(\alpha\) es crucial para la convergencia. En particular, una regla de trabajo es utilizar \(0.01/m\). Notar que el parámetro \(\alpha\) no es un parámetro del modelo como tal, si no que es parte del algoritmo, este tipo de parámetros se suelen llamar hyperparameters. Pudes reconocerlos porque el valor del parámetro es conocido antes de la fase de entrenamiento del modelo.
def lms_regression_slow(X, Y, theta, tol=1E-6):
m, n = X.shape
converged = False
alpha = 0.01 / len(Y)
while not converged:
gradient = 0.
for xiT, yi in zip(X, Y):
xiT = xiT.reshape(1, n)
hi = np.dot(xiT, theta)
gradient += (hi - yi) * xiT.T
new_theta = theta - alpha * gradient
converged = np.linalg.norm(theta - new_theta) < tol * np.linalg.norm(theta)
theta = new_theta
return theta
m = 1000
t = np.linspace(0, 1, m)
x = 2 + 2 * t
y = 300 + 100 * t
X = np.array([np.ones(m), x]).T
Y = y.reshape(m, 1)
theta_0 = np.array([[0.0], [0.0]])
theta_slow = lms_regression_slow(X, Y, theta_0)
print(theta_slow)
Validamos si nuestro resultado es el indicado con una tolerancia dada.
np.allclose(X @ theta_slow, Y, atol=0.5)
True
np.allclose(X @ theta_slow, Y, atol=1e-3)
False
Implementación Vectorial¶
¿Cómo podemos obtener una justificación para la ecuación normal?
Necesitamos los siguientes ingredientes:
Se tiene
Aplicando a cada uno de los términos, obtenemos:
también se tiene
y por último
Por lo tanto se tiene que
Esto significa que el problema $\(\min_\theta J(\theta)\)\( se resuelve al hacer todas las derivadas parciales iguales a cero (ie, gradiente igual a cero) \)\(\nabla_\theta J(\theta) = 0\)\( lo cual en nuestro caso se convierte convenientemente a la ecuación normal \)\(X^T X \theta = X^T Y\)\( y se tiene \)\(\hat{\theta} = (X^T X)^{-1} X^T Y\)\( Aquí \)\hat{\theta}\( es una estimación de \)\theta$.
def lms_regression_fast(X, Y, theta, tol=1E-6):
converged = False
alpha = 0.01 / len(Y)
theta = theta.reshape(X.shape[1], 1)
A = np.dot(X.T, X)
b = np.dot(X.T, Y)
while not converged:
gradient = np.dot(A, theta) - b
new_theta = theta - alpha * gradient
converged = np.linalg.norm(theta - new_theta) < tol * np.linalg.norm(theta)
theta = new_theta
return theta
theta_fast = lms_regression_fast(X, Y, theta_0)
print(theta_fast)
[[199.39672176]
[ 50.19457286]]
Validación
np.allclose(X @ theta_fast, Y, atol=0.5)
True
np.allclose(X @ theta_fast, Y, atol=1e-3)
False
También es posible usar la implementación de resolución de sistemas lineales dispoinible en numpy.
def matrix_regression(X, Y, theta, tol=1E-6):
A = np.dot(X.T,X)
b = np.dot(X.T,Y)
sol = np.linalg.solve(A,b)
return sol
theta_npsolve = matrix_regression(X, Y, theta_0)
print(theta_npsolve)
[[200.]
[ 50.]]
Interpretación Probabilística¶
Consideremos el modelo lineal
donde \(\varepsilon\) es un vector de errores aleatorios de media cero y matriz de dispersión \(\sigma^2 I\), donde \(I\) es la matriz identidad. Es usual añadir el supuesto de normalidad al vector de errores, por lo que se asume que
Cabe destacar que:
\(\theta\) no es una variable aleatoria, es un parámetro (desconocido).
\(Y \ | \ X; \theta \sim \mathcal{N}(X \theta, \sigma^2 I)\)
La función de verosimilitud \(L(\theta)\) nos permite entender que tan probable es encontrar los datos observados, para una elección del parámetro \(\theta\).
Sea \(l(\theta) = \log L(\theta)\) la log-verosimilitud. Luego, ignorando los términos constantes se tiene
Luego, derivando respecto a \(\theta\):
Luego podemos usar toda nuestra artillería de optimización despejando \(\partial l(\theta) / \partial \theta = 0\) y demostrando que es un máximo. Nuevamente llegamos a
Scikit-learn¶
Scikit-learn Machine Learning in Python
Scikit-learn is an open source machine learning library that supports supervised and unsupervised learning. It also provides various tools for model fitting, data preprocessing, model selection and evaluation, and many other utilities.
Simple and efficient tools for predictive data analysis
Accesible to everybody, and reusable in various contexts
Built on
numpy
,scipy
andmatplotlib
Open source, commercially usable - BSD license
Scikit-learn cuenta con enorme cantidad de herramientas de regresión, siendo la regresión lineal la más simple de estas. Ajustar una es tan sencillo como:
from sklearn.linear_model import LinearRegression
reg = LinearRegression(fit_intercept=False)
reg.fit(X, Y)
theta_sklearn = reg.coef_.T
print(theta_sklearn)
[[200.]
[ 50.]]
Nota que primero se crea un objeto LinearRegression
en que se declaran algunos parámetros, por ejemplo, en nuestro caso la matriz de diseño X
ya posee una columna de intercepto, por lo que no es necesario incluirla en el modelo de scikit-learn. Luego se ajusta el modelo reg
con el método fit()
.
Benchmark¶
Implementación simple
%%timeit
lms_regression_slow(X, Y, theta_0)
1min 33s ± 1.2 s per loop (mean ± std. dev. of 7 runs, 1 loop each)
theta_slow
array([[199.39672176],
[ 50.19457286]])
Implementación vectorizada
%%timeit
lms_regression_fast(X, Y, theta_0)
241 ms ± 7.73 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
theta_fast
array([[199.39672176],
[ 50.19457286]])
Implementación numpy
%%timeit
matrix_regression(X, Y, theta_0)
17.1 µs ± 475 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
theta_npsolve
array([[200.],
[ 50.]])
Implementación scikit-learn
%%timeit
LinearRegression(fit_intercept=False).fit(X, Y).coef_.T
278 µs ± 2.58 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
theta_sklearn
array([[200.],
[ 50.]])
Algunos comentarios:
La implementación simple es miles de veces más lenta que la más rápida, que en este caso es la implementación de numpy.
La implementación de numpy es sin duda la más rápida, pero no es posible utilizarla con matrices singulares.
Las implementaciones de gradient descent implementadas from scratch no son lo sufiecientemente precisas.
scikit-learn demora más pues es más flexible, además de realizar validaciones al momento de ajustar los modelos.
Aspectos Prácticos¶
Al realizar regresión, algunos autores indican que es conveniente normalizar/estandarizar los datos, es decir transformarlos para que tengan una escala común:
Utilizando la media y la desviación estándar $\(\frac{x_i-\overline{x_i}}{\sigma_{x_i}}\)$
Utilizando mínimos y máximos $\(\frac{x_i-\min{x_i}}{\max{x_i} - \min{x_i}}\)$
¿Porqué normalizar?
Los valores numéricos poseen escalas de magnitud distintas.
Las variables tienen distintos significados físicos.
Algoritmos funcionan mejor.
Interpretación de resultados es más sencilla.
Algunos problemas potenciales
Normalizar los datos puede producir colinealidad en los datos, produciendo inestabilidad numérica en la implementación.
En particular, scikit-learn ofrece herramientas para transformar datos. Por ejemplo, para escalar la forma más fácil y directa es utilizar sklearn.preprocessing.scale
from sklearn import preprocessing
diabetes_X_scaled = preprocessing.scale(diabetes_X)
diabetes_X_scaled
array([[ 0.80050009, 1.06548848, 1.29708846, ..., -0.05449919,
0.41855058, -0.37098854],
[-0.03956713, -0.93853666, -1.08218016, ..., -0.83030083,
-1.43655059, -1.93847913],
[ 1.79330681, 1.06548848, 0.93453324, ..., -0.05449919,
0.06020733, -0.54515416],
...,
[ 0.87686984, 1.06548848, -0.33441002, ..., -0.23293356,
-0.98558469, 0.32567395],
[-0.9560041 , -0.93853666, 0.82123474, ..., 0.55838411,
0.93615545, -0.54515416],
[-0.9560041 , -0.93853666, -1.53537419, ..., -0.83030083,
-0.08871747, 0.06442552]])
Sin embargo, para parovechar todas las bondades de scikit-learn se recomienda hacer uso de los objetos Transformer
.
scaler = preprocessing.StandardScaler().fit(diabetes_X)
scaler.transform(diabetes_X)
array([[ 0.80050009, 1.06548848, 1.29708846, ..., -0.05449919,
0.41855058, -0.37098854],
[-0.03956713, -0.93853666, -1.08218016, ..., -0.83030083,
-1.43655059, -1.93847913],
[ 1.79330681, 1.06548848, 0.93453324, ..., -0.05449919,
0.06020733, -0.54515416],
...,
[ 0.87686984, 1.06548848, -0.33441002, ..., -0.23293356,
-0.98558469, 0.32567395],
[-0.9560041 , -0.93853666, 0.82123474, ..., 0.55838411,
0.93615545, -0.54515416],
[-0.9560041 , -0.93853666, -1.53537419, ..., -0.83030083,
-0.08871747, 0.06442552]])
Aplicación¶
Para aplicar a nuestros datos de diabetes es tan fácil como
reg = LinearRegression(fit_intercept=True).fit(diabetes_X, diabetes_y)
Para obtener los coeficientes de regresión y el intercepto debes acceder a los atributos de la instancia
reg.coef_
array([ -10.01219782, -239.81908937, 519.83978679, 324.39042769,
-792.18416163, 476.74583782, 101.04457032, 177.06417623,
751.27932109, 67.62538639])
reg.intercept_
152.1334841628965
También es posible predecir u obtener el score asociado a datos.
reg.predict(diabetes_X)
array([206.11706979, 68.07234761, 176.88406035, 166.91796559,
128.45984241, 106.34908972, 73.89417947, 118.85378669,
158.81033076, 213.58408893, 97.07853583, 95.1016223 ,
115.06673301, 164.67605023, 103.07517946, 177.17236996,
211.75953205, 182.84424343, 147.99987605, 124.01702527,
120.33094632, 85.80377894, 113.11286302, 252.44934852,
165.48821056, 147.72187623, 97.12824075, 179.09342974,
129.05497324, 184.78138552, 158.71515746, 69.47588393,
261.50255826, 112.81897436, 78.37194762, 87.66624129,
207.92460213, 157.87686037, 240.84370686, 136.93372685,
153.48187659, 74.15703284, 145.63105805, 77.8280105 ,
221.0786645 , 125.22224022, 142.60147066, 109.4926324 ,
73.14037106, 189.87368742, 157.93636782, 169.55816531,
134.18186217, 157.72356219, 139.1077439 , 72.73252701,
207.8289973 , 80.10834588, 104.08562488, 134.57807971,
114.23779529, 180.67760064, 61.12644508, 98.7215441 ,
113.79626149, 189.96141244, 148.98263155, 124.33457266,
114.83969622, 122.00224605, 73.91315064, 236.70948329,
142.31366526, 124.51427625, 150.84273716, 127.75408702,
191.16674356, 77.05921006, 166.82129568, 91.00741773,
174.75026808, 122.83488194, 63.27214662, 151.99895968,
53.73407848, 166.00134469, 42.65030679, 153.04135861,
80.54493791, 106.9048058 , 79.94239571, 187.1634566 ,
192.60115666, 61.07125918, 107.40466928, 125.04038427,
207.72180472, 214.21749964, 123.47505642, 139.16396617,
168.21035724, 106.9267784 , 150.64502809, 157.92231541,
152.75856279, 116.22255529, 73.03090141, 155.66898717,
230.14278537, 143.50191007, 38.0947967 , 121.860737 ,
152.79569851, 207.99651918, 291.23082717, 189.17431487,
214.02871163, 235.18090808, 165.3872774 , 151.25000032,
156.57626783, 200.44154589, 219.35211772, 174.79049427,
169.23161767, 187.8719893 , 57.49473392, 108.55110499,
92.68518048, 210.87365701, 245.47433558, 69.84529943,
113.0351432 , 68.42945176, 141.69628649, 239.46177949,
58.3802079 , 235.47268158, 254.91986281, 253.31042713,
155.50813249, 230.55904185, 170.44063216, 117.99200943,
178.55548636, 240.07155813, 190.3398776 , 228.66100769,
114.24162642, 178.36570405, 209.09273631, 144.85567253,
200.65791056, 121.34184881, 150.50918174, 199.02165018,
146.2806806 , 124.02443772, 85.26036769, 235.16536625,
82.17255475, 231.29266191, 144.36634395, 197.04778326,
146.99720377, 77.18477545, 59.3728572 , 262.67891084,
225.12578458, 220.20506312, 46.59691745, 88.1040833 ,
221.77623752, 97.24900614, 164.48869956, 119.90114263,
157.79986195, 223.08505437, 99.5885471 , 165.84341641,
179.47571002, 89.83382843, 171.82492808, 158.36337775,
201.47857482, 186.39202728, 197.47094269, 66.57241937,
154.59826802, 116.18638034, 195.92074021, 128.04740268,
91.20285628, 140.56975398, 155.23013996, 169.70207476,
98.75498537, 190.1453107 , 142.5193942 , 177.26966106,
95.31403505, 69.0645889 , 164.16669511, 198.06460718,
178.26228169, 228.58801706, 160.67275473, 212.28682319,
222.48172067, 172.85184399, 125.27697688, 174.7240982 ,
152.38282657, 98.58485669, 99.73695497, 262.29658755,
223.73784832, 221.3425256 , 133.61497308, 145.42593933,
53.04259372, 141.81807792, 153.68369915, 125.21948824,
77.25091512, 230.26311068, 78.90849563, 105.20931175,
117.99633487, 99.06361032, 166.55382825, 159.34391027,
158.27612808, 143.05658763, 231.55938678, 176.64144413,
187.23572317, 65.38504165, 190.66078824, 179.74973878,
234.91022512, 119.15540438, 85.63464409, 100.85860205,
140.4174259 , 101.83836332, 120.66138775, 83.06599161,
234.58754656, 245.16192142, 263.26766492, 274.87431887,
180.67699732, 203.05474761, 254.21769367, 118.44122343,
268.44988948, 104.83643442, 115.87172349, 140.45788952,
58.46850453, 129.83264097, 263.78452618, 45.01240356,
123.28697604, 131.08314499, 34.89018315, 138.35659686,
244.30370588, 89.95612306, 192.07094588, 164.32674962,
147.74783541, 191.89381753, 176.44296313, 158.34707354,
189.19183226, 116.58275843, 111.44622859, 117.45262547,
165.79457547, 97.80241129, 139.54389024, 84.17453643,
159.9389204 , 202.4011919 , 80.48200416, 146.64621068,
79.05274311, 191.33759392, 220.67545196, 203.75145711,
92.87093594, 179.15570241, 81.80126162, 152.82706623,
76.79700486, 97.79712384, 106.83424483, 123.83477117,
218.13375502, 126.02077447, 206.76300555, 230.57976636,
122.0628518 , 135.67694517, 126.36969016, 148.49621551,
88.07082258, 138.95595037, 203.86570118, 172.55362727,
122.95773416, 213.92445645, 174.88857841, 110.07169487,
198.36767241, 173.24601643, 162.64946177, 193.31777358,
191.53802295, 284.13478714, 279.30688474, 216.0070265 ,
210.08517801, 216.22213925, 157.01489819, 224.06561179,
189.05840605, 103.56829281, 178.70442926, 111.81492124,
290.99913121, 182.64959461, 79.33602602, 86.33287509,
249.15238929, 174.51439576, 122.10645431, 146.27099383,
170.6555544 , 183.50018707, 163.36970989, 157.03563376,
144.42617093, 125.30179325, 177.50072942, 104.57821235,
132.1746674 , 95.06145678, 249.9007786 , 86.24033937,
62.00077469, 156.81087903, 192.3231713 , 133.85292727,
93.67456315, 202.49458467, 52.53953733, 174.82926235,
196.9141296 , 118.06646574, 235.3011088 , 165.09286707,
160.41863314, 162.37831419, 254.05718804, 257.23616403,
197.50578991, 184.06609359, 58.62043851, 194.3950396 ,
110.77475548, 142.20916765, 128.82725506, 180.12844365,
211.26415225, 169.59711427, 164.34167693, 136.2363478 ,
174.50905908, 74.67649224, 246.29542114, 114.14131338,
111.54358708, 140.02313284, 109.99647408, 91.37269237,
163.01389345, 75.16389857, 254.05755095, 53.47055785,
98.48060512, 100.66268306, 258.58885744, 170.67482041,
61.91866052, 182.3042492 , 171.26913027, 189.19307553,
187.18384852, 87.12032949, 148.37816611, 251.35898288,
199.69712357, 283.63722409, 50.85577124, 172.14848891,
204.06179478, 174.16816194, 157.93027543, 150.50201654,
232.9761832 , 121.5808709 , 164.54891787, 172.67742636,
226.78005938, 149.46967223, 99.14026374, 80.43680779,
140.15557121, 191.90593837, 199.27952034, 153.63210613,
171.80130949, 112.11314588, 162.60650576, 129.8448476 ,
258.02898298, 100.70869427, 115.87611124, 122.53790409,
218.17749233, 60.94590955, 131.09513588, 119.48417359,
52.60848094, 193.01802803, 101.05169913, 121.22505534,
211.8588945 , 53.44819015])
reg.score(diabetes_X, diabetes_y)
0.5177494254132934