regresión lineal
Los conjuntos de datos y los archivos fuente se pueden obtener en el proyecto Github.
Dirección: https://github.com/Raymond-Yang-2001/AndrewNg-Machine-Learing-Homework
1. Regresión lineal univariada
La regresión lineal univariada encuentra una ecuación unidimensional y se ajusta a una línea recta.
Fórmula de regresión lineal univariante
hw , b ( x ) = b + wx h_{w,b}(x)=b+wxhw , b( X )=b+w x
www ybbb es un parámetro. Para facilitar el cálculo, puede darxxx más unx 0 = 1 x_0=1X0=1
hw , b ( x ) = bx 0 + wx 1 h_{w,b}(x)=bx_{0}+wx_{1}hw , b( X )=b x0+ancho x1
función de pérdida
J ( w , b ) = 1 2 m ∑ i = 1 m ( hw , b ( x ( i ) ) − y ( i ) ) 2 J(w,b)=\frac{1}{2m}\sum_{ i=1}^{m}(h_{w,b}(x^{(i)})-y^{(i)})^{2}J ( w ,b )=2m_ _1yo = 1∑m( hw , b( X( i ) )−y( i ) )2
Para evitar pérdidas excesivas o pequeñas causadas por rangos de datos inadecuados (por ejemplo, si el valor de los datos es demasiado grande, la pérdida puede ser1 0 5 10^51 05 o1 0 6 10^61 06 , este orden de magnitud no es adecuado para un análisis intuitivo) Al evaluar la pérdida, puede hw, b (x (i)) h_{w,b}(x^{(i)})hw , b( X( yo ) )sumy( yo ) y^{(i)}y( i ) Primero estandarizar para que el valor de la pérdida esté dentro de un rango evaluable. Pero esto no se hace cuando se hace un descenso de gradiente.
Algoritmo de optimización: descenso de gradiente por lotes (BGD)
wj = wj − α ∂ ∂ wj J ( w , b ) = wj − α 1 m ∑ i = 1 m ( hw , b ( x ( i ) ) − y ( i ) ) x ( i ) w_j=w_{j }-\alpha\frac{\partial}{\partial{w_j}}{J(w,b)}=w_{j}-\alpha \frac{1}{m}\sum_{i=1}^{ m}{(h_{w,b}(x^{(i)})-y^{(i)})x^{(i)}}wj=wj−a∂ wj∂J ( w ,b )=wj−ametro1yo = 1∑m( hw , b( X( i ) )−y( yo ) )x( i )
bj = bj − α ∂ ∂ bj J ( w , b ) = wj − α 1 m ∑ i = 1 m ( hw , b ( x ( i ) ) − y ( i ) ) b_j=b_{j} -\alpha\frac{\partial}{\partial{b_j}}{J(w,b)}=w_{j}-\alpha \frac{1}{m}\sum_{i=1}^{m }{(h_{w,b}(x^{(i)})-y^{(i)})}bj=bj−a∂ segundoj∂J ( w ,b )=wj−ametro1yo = 1∑m( hw , b( X( i ) )−y( i ) )
Aquí, podemos usarθ \thetaθ parámetros de identificación unificados, incluidowww ybbb .
Es decir, jjthj parámetrosθ j \theta_jijDetermine lo siguiente:
θ j = θ j − α ∂ ∂ wj J ( θ ; x ) = wj − α 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x ( i ) \theta_{j}=\theta_{j}-\alpha\frac{\partial}{\partial{w_j}}{J(\theta;\mathbf{x})}=w_{j}-\alpha \frac {1}{m}\sum_{i=1^{m}{(h_{\theta}(x^{(i)})-y^{(i)})x^{(i) }}ij=ij−a∂ wj∂J ( θ ;X )=wj−ametro1yo = 1∑m( hi( X( i ) )−y( yo ) )x( i )
dondeα \alphaα es la tasa de aprendizaje.
2. Regresión lineal multivariable
La regresión lineal multivariable intenta encontrar la relación entre múltiples variables y los valores predichos. Por ejemplo, la relación entre el tamaño de la casa, el número de dormitorios de una casa y los precios de la vivienda.
Escalado de características (normalización)
Cuando las diferencias numéricas entre las diferentes características de la muestra son demasiado grandes, los métodos de optimización basados en gradientes tendrán algunos problemas. Por ejemplo, existe la siguiente ecuación de regresión:
h θ ( x ) = θ 0 + θ 1 x 1 + θ 2 x 2 h_{\theta}(x)=\theta_{0}+\theta_{1}x_{ 1}+\ theta_{2}x_{2}hi( X )=i0+i1X1+i2X2
Supongamos x 2 x_ {2}X2El rango es 0 ∼ 1 0\sim10∼1 ,x 1 x_1X1El rango es 1 0 3 ∼ 1 0 4 10^3\sim10^41 03∼1 04 . Optimizamos simultáneamenteθ 0 ∼ θ 2 \theta_0\sim\theta_2i0∼i2, de modo que todas cambien en el mismo tamaño, entonces obviamente cuando las muestras de entrada son iguales, θ 1 \theta_1i1El cambio será mayor que θ 2 \theta_2i2cambios que conduzcan a una mayor producción. Esto también puede entenderse como el par de modelos θ 1 \theta_1i1Más sensible. Como se muestra en el siguiente diagrama de isolíneas de pérdida, θ 1 \theta_1i1Pequeños cambios pueden traer cambios drásticos en las pérdidas. En este caso, la optimización de los parámetros será más difícil.
Una forma de resolver este problema es el escalado de funciones, que escala dos funciones al mismo rango. Por ejemplo, se puede realizar la normalización del puntaje z:
xnew = x − μ σ x_{new} = \frac{x-\mu}{\sigma}Xnuevo _ _=pagX−metro
Entre ellos, μ \muμ es la media del conjunto de datos,σ \sigmaσ es la desviación estándar y la distribución de datos nuevos es una distribución con media 0 y desviación estándar 1.
El diagrama de pérdida de parámetros después de la normalización de datos es el siguiente:
Escalado inverso de parámetros.
Dado que los datos están escalados, los parámetros finales también se escalarán en consecuencia. La relación específica es la siguiente:
θ 0 + θ 1 ∼ d + 1 x 1 ∼ d + 1 − μ x σ x = y − μ y σ y \theta_{0}+\theta_{1\sim d+1} \frac {x_{1\sim d+1}-\mu_{x}}{\sigma_{x}}=\frac{y-\mu_{y}}{\sigma_{y}}i0+i1 ∼ d + 1pagxX1 ∼ d + 1−metrox=pagyy−metroy
Aquí estamos hablando de yyy también se ha estandarizado,de hecho, no es necesario hacer esto y no habrá ningún impacto en el rendimiento. Pero la normalización de y hace que los parámetros sean más pequeños y la convergencia se puede lograr más rápido para los parámetros inicializados en 0.
En estandarizaciónEn este caso, la fórmula de escala inversa de los parámetros es:
θ 1 ∼ d + 1 new = θ 1 ∼ d + 1 σ x σ y \theta_{1\sim d+1}^{new}=\frac{\ theta_{1\sim d+1}}{\sigma_{x}}\sigma_{y}i1 ∼ re + 1nuevo _ _=pagxi1 ∼ d + 1pagy
Fórmula:
θ 0 σ y + θ 1 ∼ d + 1 nuevo ( x 1 ∼ d + 1 − μ x ) = y − μ y \theta_{0}\sigma_{y}+\theta_{1\sim d+1 }^{nuevo}(x_{1\sim d+1}-\mu_{x})=y-\mu_{y}i0pagy+i1 ∼ re + 1nuevo _ _( X1 ∼ d + 1−metrox)=y−metroy
θ 0 nuevo = θ 0 σ y + μ y − θ 1 ∼ d + 1 nuevo μ x \theta_{0}^{new}=\theta_{0}\sigma_{y}+\mu_{y}-\theta_ {1\sim+1}^{nuevo}\mu_{x}i0nuevo _ _=i0pagy+metroy−i1 ∼ re + 1nuevo _ _metrox
Entre ellos, durante la operación de vectorización, θ 1 ∼ d + 1 new \theta_{1\sim d+1}^{new}i1 ∼ re + 1nuevo _ _和μ x \mu_{x}metroxTodos son vectores de (1,d), y la multiplicación debe utilizar el producto interno del vector.
3. Implementación del código del algoritmo de regresión lineal
implementación de vectores
Sea el dato x \boldsymbol{x}Las dimensiones de x son(n,d) (n,d)( norte ,d ) , donde n es el número de muestras y d es la dimensión de las características de la muestra. Para facilitar el cálculo, agregamos una dimensión de característica adicional con todos los valores 1 a la muestra, de modo que su dimensión se convierta en( n , d + 1 ) (n, d+1)( norte ,d+1 )
- Predicción
Sea el parámetro θ \boldsymbol{\theta}La dimensión de θ es (1, d+1), entoncesx θ ⊤ \boldsymbol{x\theta^{\top}}xθ _⊤或( θ x ⊤ ) ⊤ \boldsymbol{(\theta x^{\top})^{\top}}( θ x⊤ )⊤La dimensión se puede obtener como(n, 1) (n,1)( norte ,1 ) Resultado de la predicciónh θ ( x ) h_{\boldsymbol{\theta}}(\boldsymbol{x})hi( X ) . - Dividamos la
cantidad j entre la cantidad:
θ j = θ j − α ∂ ∂ wj J ( θ ; x ) = wj − α 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x ( i ) \theta_{j}=\theta_{j}-\alpha\frac{\partial}{\partial{w_j}}{J(\theta;\mathbf{x})}=w_ {j }-\alpha\frac{1}{m}\sum_{i=1}^{m}{(h_{\theta}(x^{(i)})-y^{(i)}) x^ {(i)}}ij=ij−a∂ wj∂J ( θ ;X )=wj−ametro1yo = 1∑m( hi( X( i ) )−y( yo ) )x( i )
De hecho, aquí ponemosθ 0 \theta_{0}i0Como sesgo, su gradiente debería ser:
∂ ∂ w 0 J ( θ ; x ) = w 0 − α 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) \frac{\ parcial}{\partial{w_0}}{J(\theta;\mathbf{x})}=w_{0}-\alpha \frac{1}{m}\sum_{i=1}^{m}{ (h_{\theta}(x^{(i)})-y^{(i)})}∂ w0∂J ( θ ;X )=w0−ametro1yo = 1∑m( hi( X( i ) )−y( i ) ), ya que complementamos los datos con dimensiones de característicasx 0 x_0X0, por lo que se puede calcular utilizando la fórmula anterior al igual que otros parámetros.
dejar error errormatriz de error β \boldsymbol{\beta}β为h θ ( x ) − x h_{\boldsymbol{\theta}}(\boldsymbol{x})-\boldsymbol{x}hi( X )−x , con dimensiones( n , 1 ) (n,1)( norte ,1 ) , entoncesx ⊤ β / n \boldsymbol{x^{\top}\beta} /nX⊤ β/nes la dimensión(d + 1, 1) (d+1,1)( d+1 ,1 )的梯度矩阵。
x ⊤ β = [ x ( 1 ) x ( 2 ) ⋯ ] × [ h ( x ( 1 ) ) − y ( 1 ) h ( x ( 2 ) ) − y ( 2 ) ⋮ ] = [ ∑ i = 1 norte ( h ( x ( i ) ) − y ( i ) ) x 0 ( 1 ) ∑ i = 1 norte ( h ( x ( i ) ) − y ( i ) ) x 1 ( 1 ) ⋮ ] \boldsymbol{x^{\top}\beta}= \left[ \begin{matrix} x^{(1)}& x^{(2)} &\cdots \end{matrix} \right] \times \left[ \begin{matrix} h(x^{(1)})-y^{(1)}\\ h(x^{(2)})-y^{(2)}\\ \vdots \end{matrix} \right] =\left[ \begin{matrix} \sum_{i=1}^{n}{(h(x^{(i)})-y^{(i)})x_ {0}^{(1)}}\\ \sum_{i=1}^{n}{(h(x^{(i)})-y^{(i)})x_{1}^{ (1)}}\\ \vdots \end{matrix} \right]X⊤β _=[X( 1 )X( 2 )⋯]× h ( x( 1 ) )−y( 1 )h ( x( 2 ) )−y( 2 )⋮ = ∑yo = 1norte( h ( x( i ) )−y( yo ) )x0( 1 )∑yo = 1norte( h ( x( i ) )−y( yo ) )x1( 1 )⋮
x ⊤ β / n \boldsymbol{x^{\top}\beta} /nXCada elemento en ⊤ β/n
código pitón
import numpy as np
def square_loss(pred, target):
"""
计算平方误差
:param pred: 预测
:param target: ground truth
:return: 损失序列
"""
return np.sum(np.power((pred - target), 2))
def compute_loss(pred, target):
"""
计算归一化平均损失
:param pred: 预测
:param target: ground truth
:return: 损失
"""
pred = (pred - pred.mean(axis=0)) / pred.std(axis=0)
target = (pred - target.mean(axis=0)) / target.std(axis=0)
loss = square_loss(pred, target)
return np.sum(loss) / (2 * pred.shape[0])
class LinearRegression:
"""
线性回归类
"""
def __init__(self, x, y, val_x, val_y, epoch=100, lr=0.1):
"""
初始化
:param x: 样本, (sample_number, dimension)
:param y: 标签, (sample_numer, 1)
:param epoch: 训练迭代次数
:param lr: 学习率
"""
self.theta = None
self.loss = []
self.val_loss = []
self.n = x.shape[0]
self.d = x.shape[1]
self.epoch = epoch
self.lr = lr
t = np.ones(shape=(self.n, 1))
self.x_std = x.std(axis=0)
self.x_mean = x.mean(axis=0)
self.y_mean = y.mean(axis=0)
self.y_std = y.std(axis=0)
x_norm = (x - self.x_mean) / self.x_std
y_norm = (y - self.y_mean) / self.y_std
self.y = y_norm
self.x = np.concatenate((t, x_norm), axis=1)
self.val_x = val_x
self.val_y = val_y
def init_theta(self):
"""
初始化参数
:return: theta (1, d+1)
"""
self.theta = np.zeros(shape=(1, self.d + 1))
def validation(self, x, y):
x = (x - x.mean(axis=0)) / x.std(axis=0)
y = (y - y.mean(axis=0)) / y.std(axis=0)
outputs = self.predict(x)
curr_loss = square_loss(outputs, y) / (2 * y.shape[0])
return curr_loss
def gradient_decent(self, pred):
"""
实现梯度下降求解
"""
# error (n,1)
error = pred - self.y
# gradient (d+1, 1)
gradient = np.matmul(self.x.T, error)
# gradient (1,d+1)
gradient = gradient.T / pred.shape[0]
# update parameters
self.theta = self.theta - (self.lr / self.n) * gradient
def train(self):
"""
训练线性回归
:return: 参数矩阵theta (1,d+1); 损失序列 loss
"""
self.init_theta()
for i in range(self.epoch):
# pred (1,n); theta (1,d+1); self.x.T (d+1, n)
pred = np.matmul(self.theta, self.x.T)
# pred (n,1)
pred = pred.T
curr_loss = square_loss(pred, self.y) / (2 * self.n)
val_loss = self.validation(self.val_x, self.val_y)
self.gradient_decent(pred)
self.val_loss.append(val_loss)
self.loss.append(curr_loss)
print("Epoch: {}/{}\tTrain Loss: {:.4f}\tVal loss: {:.4f}".format(i + 1, self.epoch, curr_loss, val_loss))
# un_scaling parameters
self.theta[0, 1:] = self.theta[0, 1:] / self.x_std.T * self.y_std[0]
self.theta[0, 0] = self.theta[0, 0] * self.y_std[0] + self.y_mean[0] - np.dot(self.theta[0, 1:], self.x_mean)
return self.theta, self.loss, self.val_loss
def predict(self, x):
"""
回归预测
:param x: 输入样本 (n,d)
:return: 预测结果 (n,1)
"""
# (d,1)
t = np.ones(shape=(x.shape[0], 1))
x = np.concatenate((t, x), axis=1)
pred = np.matmul(self.theta, x.T)
return pred.T
4. Resultados experimentales
Regresión univariada
Conjunto de entrenamiento de visualización de conjuntos de datos
y división del conjunto de pruebas
from LinearRegression import LinearRegression
epochs = 200
alpha = 1
linear_reg = LinearRegression(x=train_x_ex,y=train_y_ex,val_x=val_x_ex, val_y=val_y_ex, lr=alpha,epoch=epochs)
start_time = time.time()
theta,loss, val_loss = linear_reg.train()
end_time = time.time()
Train Time: 0.0309s
Val Loss: 6.7951
Visualización del proceso de entrenamiento
y curva de predicción de comparación de sk-learn.
regresión multivariable
Conjunto de visualización y entrenamiento de datos y conjunto de validación.
from LinearRegression import LinearRegression
alpha = 0.1
epochs = 1000
multi_lr = LinearRegression(train_x,train_y_ex,val_x=val_x,val_y=val_y_ex, epoch=epochs,lr=alpha)
start_time = time.time()
theta, loss, val_loss = multi_lr.train()
end_time = time.time()
Train Time: 0.1209s
Val Loss: 4.187(采用归一化后数据计算损失)
Visualización del proceso de formación.
Plano de predicción (en comparación con sk-learn),
donde el azul es el plano de predicción de este algoritmo y el gris es el plano de predicción de sk-learn.
Resumen del experimento
Para que la implementación del algoritmo de regresión lineal logre un mejor rendimiento, puede intentar ajustar la tasa de aprendizaje o el número de iteraciones para obtener un mejor rendimiento. Dado que se utilizan operaciones matriciales en lugar de bucles, el tiempo de entrenamiento se reduce considerablemente, pero aún no ha alcanzado el nivel de la función de la biblioteca sk-learn.