Andrew Ngs „Machine Learning“ – Implementierung des linearen Regressionscodes


Datensätze und Quelldateien können im Github-Projekt bezogen werden

Adresse: https://github.com/Raymond-Yang-2001/AndrewNg-Machine-Learing-Homework

1. Univariate lineare Regression

Die univariate lineare Regression findet eine eindimensionale Gleichung und passt eine gerade Linie an.

Univariate lineare Regressionsformel

hw , b ( x ) = b + wx h_{w,b}(x)=b+wxHw , b( X )=B+B x
Www undbbb ist ein Parameter. Um die Berechnung zu erleichtern, können Siexxx plus einx ​​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+B x1

verlustfunktion

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 _1ich = 1m( Hw , b( X( ich ) )j( ich ) )2
Um übermäßige oder kleine Verluste zu vermeiden, die durch ungeeignete Datenbereiche verursacht werden (z. B. wenn der Datenwert zu groß ist, kann der Verlust1 0 5 10^51 05 oder1 0 6 10^61 06 , diese Größenordnung ist für eine intuitive Analyse nicht geeignet) Bei der Bewertung des Verlusts können Sie hw, b (x (i)) h_{w,b}(x^{(i)})Hw , b( X( i ) )sumy( i ) y^{(i)}j( i ) Standardisieren Sie zunächst so, dass der Verlustwert innerhalb eines auswertbaren Bereichs liegt. Beim Gradientenabstieg ist dies jedoch nicht der Fall

Optimierungsalgorithmus – Batch Gradient Descent (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=wjAwjJ ( w ,B )=wjAM1ich = 1m( Hw , b( X( ich ) )j( i ) )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=BjAbjJ ( w ,B )=wjAM1ich = 1m( Hw , b( X( ich ) )j( i ) )
Hier können wirθ \thetaθ einheitliche Identifikationsparameter, einschließlichWWw undbbB .

Das heißt, jjthj Parameterθ j \theta_jichjBestimmen Sie Folgendes:
θ 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) }}ichj=ichjAwjJ ( θ ;X )=wjAM1ich = 1m( Hich( X( ich ) )j( i ) )x( i )
wobeiα \alphaα ist die Lernrate.

2. Multivariable lineare Regression

Bei der multivariablen linearen Regression wird versucht, die Beziehung zwischen mehreren Variablen und vorhergesagten Werten zu ermitteln. Zum Beispiel die Beziehung zwischen Hausgröße, Anzahl der Schlafzimmer in einem Haus und Hauspreisen.

Feature-Skalierung (Normalisierung)

Wenn die numerischen Unterschiede zwischen verschiedenen Merkmalen der Stichprobe zu groß sind, treten bei der Optimierung auf Gradientenbasis einige Probleme auf. Beispielsweise gibt es die folgende Regressionsgleichung:
h θ ( x ) = θ 0 + θ 1 x 1 + θ 2 x 2 h_{\theta}(x)=\theta_{0}+\theta_{1}x_{ 1}+\theta_{2}x_{2}Hich( X )=ich0+ich1X1+ich2X2
Angenommen x 2 x_{2}X2Der Bereich ist 0 ∼ 1 0\sim101x 1 x_1X1Der Bereich ist 1 0 3 ∼ 1 0 4 10^3\sim10^41 031 04 . Wir optimieren gleichzeitigθ 0 ∼ θ 2 \theta_0\sim\theta_2ich0ich2, so dass sie sich alle um die gleiche Größe ändern, dann ist es offensichtlich, dass θ 1 \theta_1 , wenn die Eingabeproben gleich sindich1Die Änderung wird größer sein als θ 2 \theta_2ich2Änderungen, die zu einer höheren Leistung führen. Dies kann auch als Modellpaar θ 1 \theta_1 verstanden werdenich1Empfindlichere. Wie im folgenden Verlustisoliniendiagramm gezeigt, ist θ 1 \theta_1ich1Kleine Änderungen können drastische Veränderungen bei den Verlusten mit sich bringen. In diesem Fall wird die Parameteroptimierung schwieriger.
Fügen Sie hier eine Bildbeschreibung ein
Eine Möglichkeit, dieses Problem zu lösen, ist die Feature-Skalierung, die zwei Features auf den gleichen Bereich skaliert. Beispielsweise kann eine Z-Score-Normalisierung durchgeführt werden:
xnew = x − μ σ x_{new} = \frac{x-\mu}{\sigma}Xneu _ _=PXM
Darunter μ \muμ ist der Mittelwert des Datensatzes,σ \sigmaσ ist die Standardabweichung und die Verteilung neuer Daten ist eine Verteilung mit Mittelwert 0 und Standardabweichung 1.
Das Parameterverlustdiagramm nach der Datennormalisierung sieht wie folgt aus:
Fügen Sie hier eine Bildbeschreibung ein

Inverse Skalierung von Parametern

Da die Daten skaliert sind, werden auch die endgültigen Parameter entsprechend skaliert. Die spezifische Beziehung ist wie folgt:
θ 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}}ich0+ich1 d + 1PxX1 d + 1Mx=PyjMy
Hier reden wir über jjy wurde ebenfalls standardisiert.Tatsächlich ist dies nicht erforderlich und es wird keine Auswirkungen auf die Leistung haben. Durch die Normalisierung von y werden die Parameter jedoch kleiner und die Konvergenz kann für auf 0 initialisierte Parameter schneller erreicht werden.

In der StandardisierungyyIn diesem Fall lautet die inverse Skalierungsformel der Parameter:
θ 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}ich1 d + 1neu _ _=Pxich1 d + 1Py
Formel:
θ 0 σ y + θ 1 ∼ d + 1 new ( x 1 ∼ d + 1 − μ x ) = y − μ y \theta_{0}\sigma_{y}+\theta_{1\sim d+1 }^{new}(x_{1\sim d+1}-\mu_{x})=y-\mu_{y}ich0Py+ich1 d + 1neu _ _( X1 d + 1Mx)=jMy

θ 0 neu = θ 0 σ y + μ y − θ 1 ∼ d + 1 neu μ x \theta_{0}^{neu}=\theta_{0}\sigma_{y}+\mu_{y}-\theta_ {1\sim+1}^{neu}\mu_{x}ich0neu _ _=ich0Py+Myich1 d + 1neu _ _Mx
Darunter gilt während des Vektorisierungsvorgangs θ 1 ∼ d + 1 new \theta_{1\sim d+1}^{new}ich1 d + 1neu _ _μ x \mu_{x}MxSie sind alle Vektoren von (1,d), und die Multiplikation sollte das innere Vektorprodukt verwenden.

3. Implementierung des Codes für den linearen Regressionsalgorithmus

Vektorimplementierung

Seien die Daten x \boldsymbol{x}Die Dimensionen von x sind(n, d) (n,d)( N ,d ) , wobei n die Anzahl der Stichproben und d die Dimension der Stichprobenmerkmale ist. Zur Vereinfachung der Berechnung fügen wir der Stichprobe eine zusätzliche Merkmalsdimension mit allen Werten 1 hinzu, sodass ihre Dimension( n , d + 1 ) (n, d+1)( N ,D+1 )

  1. Vorhersage
    Sei der Parameter θ \boldsymbol{\theta}Die Dimension von θ ist (1, d+1), dann istx θ ⊤ \boldsymbol{x\theta^{\top}}x θ( θ x ⊤ ) ⊤ \boldsymbol{(\theta x^{\top})^{\top}}( θ x )⊤Die Dimension kann erhalten werden als(n, 1) (n,1)( N ,1 ) Vorhersageergebnish θ ( x ) h_{\boldsymbol{\theta}}(\boldsymbol{x})Hich( X ) .
  2. Teilen wir die
    Größe j durch die Größe:
    θ 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^ {(ich)}}ichj=ichjAwjJ ( θ ;X )=wjAM1ich = 1m( Hich( X( ich ) )j( i ) )x( i )
    Tatsächlich setzen wir hierθ 0 \theta_{0}ich0Als Voreingenommenheit sollte sein Gradient sein:
    ∂ ∂ w 0 J ( θ ; x ) = w 0 − α 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) \frac{\ partiell}{\partial{w_0}}{J(\theta;\mathbf{x})}=w_{0}-\alpha \frac{1}{m}\sum_{i=1}^{m}{ (h_{\theta}(x^{(i)})-y^{(i)})}w0J ( θ ;X )=w0AM1ich = 1m( Hich( X( ich ) )j( i ) ), da wir die Daten mit Merkmalsdimensionenx 0 x_0X0, sodass er wie andere Parameter mit der obigen Formel berechnet werden kann.
    Lassen Sie Fehler FehlerFehlermatrix β\boldsymbol{\beta}βh θ ( x ) − x h_{\boldsymbol{\theta}}(\boldsymbol{x})-\boldsymbol{x}Hich( X )x , mit Abmessungen( n , 1 ) (n,1)( N ,1 ) , dannx ⊤ β / n \boldsymbol{x^{\top}\beta} /nX β/nist die Dimension(d + 1, 1) (d+1,1)( D+1 ,x ⊤ β = [ x ( 1 ) x ( 2 ) ⋯ ] × [ h ( x ( 1 ) ) − y ( 1 ) h ( x (
    2 ) ) − y ( 2 ) ⋮ ] = [ ∑ i = 1 n ( h ( x ( i ) ) − y ( i ) ) x 0 ( 1 ) ∑ i = 1 n ( 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 ) )j( 1 )h ( x( 2 ) )j( 2 ) = ich = 1n( h ( x( ich ) )j( i ) )x0( 1 )ich = 1n( h ( x( ich ) )j( i ) )x1( 1 )
    x ⊤ β / n \boldsymbol{x^{\top}\beta} /nXJedes Element in β/n

Python-Code

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. Experimentelle Ergebnisse

Univariate Regression

Aufteilung des Trainingssatzes zur Datensatzvisualisierung und des Testsatzes
Fügen Sie hier eine Bildbeschreibung ein

blog.csdnimg.cn/c92b41d0e88f4afab794315c992525a0.png)

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

Visualisierung des Trainingsprozesses
Fügen Sie hier eine Bildbeschreibung ein
und Prognosekurve für den Sk-Learn-Vergleich
Fügen Sie hier eine Bildbeschreibung ein

multivariable Regression

Datenvisualisierungs- und Trainingsset und Validierungsset
Fügen Sie hier eine Bildbeschreibung ein

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(采用归一化后数据计算损失)

Visualisierung des Trainingsprozesses
Fügen Sie hier eine Bildbeschreibung ein

Vorhersageebene (im Vergleich zu sk-learn),
wobei Blau die Vorhersageebene dieses Algorithmus und Grau die Vorhersageebene von sk-learn ist
Fügen Sie hier eine Bildbeschreibung ein

Zusammenfassung des Experiments

Um bei der Implementierung des linearen Regressionsalgorithmus eine bessere Leistung zu erzielen, können Sie versuchen, die Lernrate oder die Anzahl der Iterationen anzupassen, um eine bessere Leistung zu erzielen. Da Matrixoperationen anstelle von Schleifen verwendet werden, wird die Trainingszeit erheblich verkürzt, sie hat jedoch noch nicht das Niveau der Sk-Learn-Bibliotheksfunktion erreicht.

Ich denke du magst

Origin blog.csdn.net/d33332/article/details/128455218
Empfohlen
Rangfolge