机器学习之线性回归学习

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_38684419/article/details/79985733

线性回归是一种回归分析技术,回归在于分析自变量与因变量之间的关系。回归分析的自变量应是连续性变量,如果自变量是离散性变量则转化为分类问题,线性回归属于有监督学习。

我们用向量x表示训练样本的特征,向量w表示权重,T表示训练集,m表示样本数量,n表示特征数量。

简化问题的难度,假设有3个样本特征x1,x2,x3,并假设我们的输出回归函数为h(x)=w1*x1+w2*x2+w3*x3+w0,

w0为初始权重,现在令x0=1,则回归函数可写为h(x)=w0**x0+w1*x1+w2*x2+w3*x3=w^T*x。对于给定的样本xi其预测值为yi=h(xi)=w*xi。函数的损失函数我们定义为平方损失函数,则损失函数为J(w)=∑(h(xi)-yi)²(∑的下标i=0,上标是样本数量m)。现在目标是损失函数最小化,即argmin∑(h(xi)-yi

说明一下每个符号代表的意义:h(x)表示训练模型或者回归函数,J(w)表示损失函数,y代表真实值,h(x)或斜体y代表预测值。

将上面整理,即:

假设:h(x)=w0**x0+w1*x1+w2*x2+w3*x3=w^T*x

求:w0,w1,w2,w3,即权重向量w

代价函数:J(w)=∑(h(xi)-yi

优化目标:argmin∑J(w)=argmin(h(xi)-yi

特征缩放:假设有两个特征,一个特征取值1-1000,另一个取值1-5。在对其优化时会得到一个窄长得椭圆,导致在梯度下降是梯度的方向为垂直等高的方向走之字形,这样会使寻求最优解得迭代很慢。如果我们将特征进行缩放这样在对其优化时会得到一个近似圆形,梯度的方向直指圆心,这样迭代的速度就会很快,可以减少寻求最优解的时间。在特征缩放时我们可以设置到一个小范围例如-1<=xi<=1或者-3<=xi<=3。可以采用一种叫标准化的特征缩放方法:

xj = (xj - μj) / σj

μ:平均值,σ:标准差(最大值减去最小值)

特征组合:假设预测一间房子的价钱,我们有这件房子的长度x1和宽度x2两个特征,现在我们可以将两个特征进行组合得到一个新的特征:房子的面积x=x1*x2。这样我们可以的到一个新的预测函数h(x)=w0+w1*x。有时候为了加快训练速度我们可以去掉一些不是特别重要的特征。

多项式回归:假设我们给定房子的面积x现在需要预测房子的价钱,下面给一个图

在这个图中直线明显不能很好的拟合数据,我们可以用w0+w1*x+w2*x²来拟合数据,但是随着房子面积的增长价钱不可能下降,现在我们可以换为用w0+w1*x+w2*x²+w3*x³来拟合数据。现在定义:

h(x)=w0+w1*x1+w2*x2+w3*x3=w0+w1*x+w2*x²+w3*x³

x1=x, x2=x², x3=x³

在这里,如果x³非常大的话,我们就可以使用特征缩放。或者我们也可以使用h(x)=w0+w1*x1+w2*x2^½。


现在我们用线性回归进行分类

鸢尾花数据集是机器学习的一个经典示例,它包含Setosa,Versicolor,Virginica三个品种,现在我们用鸢尾花的前两个品种并选取两个特征做分类。我们用做一个感知器,预设一个阈值θ=0,如果预测值大于0将其归到1类,如果预测值小于0将其归到-1类。

我们先拿出数据并进行数据预处理:

import pandas as pd
df = pd.read_csv('iris.data', header=None)
df.tail()
y = df.iloc[0:100, 4].values
y = np.where(y == 'Iris-setosa', -1, 1)
X = df.iloc[0:100, [0,2]].values

下面实现感知器算法:

import numpy as np

class Perceptron():
    #eta是学习速率,n_iter是迭代次数
    def __init__(self,eta=0.01, n_iter=10):
        self.eta = eta
        self.n_iter = n_iter
    
    #fit方法是进行学习
    def fit(self,X,y):
        #W_:权重并初始化为一个零向量,errors_:收集迭代中错误的分类样本
        #W_数组元素个数是特征数目n+1是因为增加了一个初始权重W0,并增加一个特征x0=1.
        self.w_ = np.zeros(1 + X.shape[1])
        self.errors_ = []
        
        for i in range(self.n_iter):
            errors = 0
            for xi, target in zip(X,y):
                update = self.eta * (target - self.predict(xi))
                #更新权重
                self.w_[1:] += update * xi
                #初始权重W0,因为x0=1所以单独更新
                self.w_[0] += update
                #预测结果正确,预测值与真实秩之差为零所以update=0,权重将不再更新
                errors += int(update != 0.0)
            self.errors_.append(errors)
        return self
    
    #进行计算,获得预测值
    def net_input(self,X):
        return np.dot(X, self.w_[1:]) + self.w_[0]
    
    #将预测值与阈值比较,并进行分类
    def predict(self, X):
        return np.where(self.net_input(X) >= 0.0, 1, -1)

用感知器进行训练:

绘制每次迭代的错误分类数量的折线图,以检验算法是否收敛并可以找到可以分开两张类型鸢尾花的决策边界

import matplotlib.pylab as plt

ppn = Perceptron(eta=0.1, n_iter=10)
ppn.fit(X,y)
plt.plot(range(1, len(ppn.errors_)+1), ppn.errors_, marker='o')
plt.xlabel('Epochs')
plt.ylabel('Number of misclassifications')
plt.show()

得到如下图:


可以观察到,分类器在第六次迭代就已经收敛,并具备对训练样本进行正确分类的能力。

下面实现对二维数据的集决策边界的可视化:

from matplotlib.colors import ListedColormap

def plot_decision_regions(X, y, classifier, resolution=0.02):
    #setup marker generator and color map
    markers = ('s', 'x', 'o', '^', 'v')
    colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
    cmap = ListedColormap(colors[:len(np.unique(y))])
    
    #plot the decision surface
    x1_min, x1_max = X[:, 0].min() -1, X[:, 0].max() + 1
    x2_min, x2_max = X[:, 1].min() -1, X[:, 1].max() + 1
    xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution),
                          np.arange(x2_min, x2_max, resolution))
    Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
    Z = Z.reshape(xx1.shape)
    plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap)
    plt.xlim(xx1.min(), xx1.max())
    plt.ylim(xx2.min(), xx2.max())
    
    #plot class samples
    for idx, cl in enumerate(np.unique(y)):
        plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1],
                   alpha=0.8, c=cmap(idx),
                   marker=markers[idx], label=cl)

plot_decision_regions(X, y, classifier=ppn)
plt.xlabel('sepal length(cm)')
plt.ylabel('petal length(cm)')
plt.legend(loc='upper left')
plt.show()

得到决策区域的图像:



如上图,通过感知器学习我们得到的分类曲面可以对训练子集中的所有样本进行分类。


感知器虽然可以完美划分两个类别的花,但是感知器面临的最大问题是算法的收敛。如果两个类别可以通过线性超平面进行划分,则感知器一定会收敛。但是,如果两个类别无法通过线性判定边界完全正确划分,则权重会不断更新。为防止此类事件,可以事先设置权重更新的最大迭代次数。

例如:

更改下训练数据并将二维散点图进行可视化:

import matplotlib.pylab as plt

y = df.iloc[0:100, 4].values
y = np.where(y == 'Iris-setosa', -1, 1)
X = df.iloc[0:100, 0:2].values
plt.scatter(X[:50, 0], X[:50, 1], color='red', marker='o', label='setosa')
plt.scatter(X[50:100, 0], X[50:100, 1], color='blue', marker='x', label='versicolor')
plt.xlabel('petal length')
plt.ylabel('sepal length')
plt.legend(loc='upper left')
plt.show()

得到图:


判断算法的收敛性,并将迭代次数改为30次:


可以看到算法将无法收敛,同时也无法的到正确的决策边界:






猜你喜欢

转载自blog.csdn.net/qq_38684419/article/details/79985733