在线性回归中,我们想要建立一个模型,来拟合一个因变量y与一个或多个独立自变量(预测变量)x之间的关系。
给定:
线性回归模型可以理解为一个非常简单的神经网络:
线性回归模型可以使用以下方法进行训练
a)梯度下降法
线性回归模型的训练过程有不同的步骤。首先(在步骤0中),模型的参数将被初始化。在达到指定训练次数或参数收敛前,重复以下其他步骤。
第0步:
用0(或小的随机值)来初始化权重向量和偏置量,或者直接使用正态方程计算模型参数
第1步(只有在使用梯度下降法训练时需要):
第2步(只有在使用梯度下降法训练时需要):
用均方误差计算训练集上的损失:
第3步(只有在使用梯度下降法训练时需要):
对每个参数,计算其对损失函数的偏导数:
所有偏导数的梯度计算如下:
第4步(只有在使用梯度下降法训练时需要):
更新权重向量和偏置量:
In[4]:
importnumpyasnpimportmatplotlib.pyplotaspltfromsklearn.model_selectionimporttrain_test_splitnp.random.seed(123)
数据集
In[5]:
#WewilluseasimpletrainingsetX=2*np.random.rand(500,1)y=5+3*X+np.random.randn(500,1)fig=plt.figure(figsize=(8,6))plt.scatter(X,y)plt.title("Dataset")plt.xlabel("Firstfeature")plt.ylabel("Secondfeature")plt.show()
In[6]:
#SplitthedataintoatrainingandtestsetX_train,X_test,y_train,y_test=train_test_split(X,y)print(f'ShapeX_train:{X_train.shape}')print(f'Shapey_train:{y_train.shape}')print(f'ShapeX_test:{X_test.shape}')print(f'Shapey_test:{y_test.shape}')
ShapeX_train:(375,1)Shapey_train:(375,1)ShapeX_test:(125,1)Shapey_test:(125,1)
线性回归分类
In[23]:
使用梯度下降进行训练
In[24]:
regressor=LinearRegression()w_trained,b_trained,costs=regressor.train_gradient_descent(X_train,y_train,learning_rate=0.005,n_iters=600)fig=plt.figure(figsize=(8,6))plt.plot(np.arange(n_iters),costs)plt.title("Developmentofcostduringtraining")plt.xlabel("Numberofiterations")plt.ylabel("Cost")plt.show()
Costatiteration0:66.45256981003433Costatiteration100:2.2084346146095934Costatiteration200:1.2797812854182806Costatiteration300:1.2042189195356685Costatiteration400:1.1564867816573Costatiteration500:1.121391041394467
测试(梯度下降模型)
In[28]:
n_samples,_=X_train.shapen_samples_test,_=X_test.shapey_p_train=regressor.predict(X_train)y_p_test=regressor.predict(X_test)error_train=(1/n_samples)*np.sum((y_p_train-y_train)**2)error_test=(1/n_samples_test)*np.sum((y_p_test-y_test)**2)print(f"Errorontrainingset:{np.round(error_train,4)}")print(f"Errorontestset:{np.round(error_test)}")
Errorontrainingset:1.0955
Errorontestset:1.0
使用正规方程(normalequation)训练
#Tocomputetheparametersusingthenormalequation,weaddabiasvalueof1toeachinputexampleX_b_train=np.c_[np.ones((n_samples)),X_train]X_b_test=np.c_[np.ones((n_samples_test)),X_test]reg_normal=LinearRegression()w_trained=reg_normal.train_normal_equation(X_b_train,y_train)
测试(正规方程模型)
y_p_train=reg_normal.predict(X_b_train)y_p_test=reg_normal.predict(X_b_test)error_train=(1/n_samples)*np.sum((y_p_train-y_train)**2)error_test=(1/n_samples_test)*np.sum((y_p_test-y_test)**2)print(f"Errorontrainingset:{np.round(error_train,4)}")print(f"Errorontestset:{np.round(error_test,4)}")
Errorontrainingset:1.0228
Errorontestset:1.0432
可视化测试预测
#Plotthetestpredictionsfig=plt.figure(figsize=(8,6))plt.scatter(X_train,y_train)plt.scatter(X_test,y_p_test)plt.xlabel("Firstfeature")plt.ylabel("Secondfeature")plt.show()
02Logistic回归算法
Logistic回归模型可以理解为一个非常简单的神经网络:
与线性回归不同,Logistic回归没有封闭解。但由于损失函数是凸函数,因此我们可以使用梯度下降法来训练模型。事实上,在保证学习速率足够小且使用足够的训练迭代步数的前提下,梯度下降法(或任何其他优化算法)可以是能够找到全局最小值。
训练Logistic回归模型有不同的步骤。首先(在步骤0中),模型的参数将被初始化。在达到指定训练次数或参数收敛前,重复以下其他步骤。
第0步:用0(或小的随机值)来初始化权重向量和偏置值
第2步:用sigmoid函数作为激活函数,其返回值介于0到1之间:
第3步:计算整个训练集的损失值。
我们希望模型得到的目标值概率落在0到1之间。因此在训练期间,我们希望调整参数,使得模型较大的输出值对应正标签(真实标签为1),较小的输出值对应负标签(真实标签为0)。这在损失函数中表现为如下形式:
第4步:对权重向量和偏置量,计算其对损失函数的梯度。
一般形式如下:
第5步:更新权重和偏置值。
importnumpyasnpfromsklearn.model_selectionimporttrain_test_splitfromsklearn.datasetsimportmake_blobsimportmatplotlib.pyplotaspltnp.random.seed(123)%matplotlibinline
In[25]:
#WewillperformlogisticregressionusingasimpletoydatasetoftwoclassesX,y_true=make_blobs(n_samples=1000,centers=2)fig=plt.figure(figsize=(8,6))plt.scatter(X[:,0],X[:,1],c=y_true)plt.title("Dataset")plt.xlabel("Firstfeature")plt.ylabel("Secondfeature")plt.show()
In[26]:
#Reshapetargetstogetcolumnvectorwithshape(n_samples,1)y_true=y_true[:,np.newaxis]#SplitthedataintoatrainingandtestsetX_train,X_test,y_train,y_test=train_test_split(X,y_true)print(f'ShapeX_train:{X_train.shape}')print(f'Shapey_train:{y_train.shape}')print(f'ShapeX_test:{X_test.shape}')print(f'Shapey_test:{y_test.shape}')
ShapeX_train:(750,2)
Shapey_train:(750,1)
ShapeX_test:(250,2)
Shapey_test:(250,1)
Logistic回归分类
In[27]:
初始化并训练模型
In[29]:
regressor=LogisticRegression()w_trained,b_trained,costs=regressor.train(X_train,y_train,n_iters=600,learning_rate=0.009)fig=plt.figure(figsize=(8,6))plt.plot(np.arange(600),costs)plt.title("Developmentofcostovertraining")plt.xlabel("Numberofiterations")plt.ylabel("Cost")plt.show()
Costafteriteration0:0.6931471805599453
Costafteriteration100:0.046514002935609956
Costafteriteration200:0.02405337743999163
Costafteriteration300:0.016354408151412207
Costafteriteration400:0.012445770521974634
Costafteriteration500:0.010073981792906512
测试模型
In[31]:
y_p_train=regressor.predict(X_train)y_p_test=regressor.predict(X_test)print(f"trainaccuracy:{100-np.mean(np.abs(y_p_train-y_train))*100}%")print(f"testaccuracy:{100-np.mean(np.abs(y_p_test-y_test))}%")
trainaccuracy:100.0%
testaccuracy:100.0%
03感知器算法
感知器是一种简单的监督式的机器学习算法,也是最早的神经网络体系结构之一。它由Rosenblatt在20世纪50年代末提出。感知器是一种二元的线性分类器,其使用d-维超平面来将一组训练样本(d-维输入向量)映射成二进制输出值。它的原理如下:
感知器可以理解为一个非常简单的神经网络:
感知器的训练可以使用梯度下降法,训练算法有不同的步骤。首先(在步骤0中),模型的参数将被初始化。在达到指定训练次数或参数收敛前,重复以下其他步骤。
第2步:用Heavisidestep函数作为激活函数,其返回一个二进制值:
第3步:使用感知器的学习规则来计算权重向量和偏置量的更新值。
第4步:更新权重向量和偏置量。
In[1]:
importnumpyasnpimportmatplotlib.pyplotaspltfromsklearn.datasetsimportmake_blobsfromsklearn.model_selectionimporttrain_test_splitnp.random.seed(123)%matplotlibinline
In[2]:
X,y=make_blobs(n_samples=1000,centers=2)fig=plt.figure(figsize=(8,6))plt.scatter(X[:,0],X[:,1],c=y)plt.title("Dataset")plt.xlabel("Firstfeature")plt.ylabel("Secondfeature")plt.show()
In[3]:
y_true=y[:,np.newaxis]X_train,X_test,y_train,y_test=train_test_split(X,y_true)print(f'ShapeX_train:{X_train.shape}')print(f'Shapey_train:{y_train.shape})')print(f'ShapeX_test:{X_test.shape}')print(f'Shapey_test:{y_test.shape}')
Shapey_train:(750,1))
感知器分类
classPerceptron():def__init__(self):passdeftrain(self,X,y,learning_rate=0.05,n_iters=100):n_samples,n_features=X.shape#Step0:Initializetheparametersself.weights=np.zeros((n_features,1))self.bias=0foriinrange(n_iters):#Step1:Computetheactivationa=np.dot(X,self.weights)+self.bias#Step2:Computetheoutputy_predict=self.step_function(a)#Step3:Computeweightupdatesdelta_w=learning_rate*np.dot(X.T,(y-y_predict))delta_b=learning_rate*np.sum(y-y_predict)#Step4:Updatetheparametersself.weights+=delta_wself.bias+=delta_breturnself.weights,self.biasdefstep_function(self,x):returnnp.array([1ifelem>=0else0foreleminx])[:,np.newaxis]defpredict(self,X):a=np.dot(X,self.weights)+self.biasreturnself.step_function(a)
In[7]:
p=Perceptron()w_trained,b_trained=p.train(X_train,y_train,learning_rate=0.05,n_iters=500)
测试
In[10]:
y_p_train=p.predict(X_train)y_p_test=p.predict(X_test)print(f"trainingaccuracy:{100-np.mean(np.abs(y_p_train-y_train))*100}%")print(f"testaccuracy:{100-np.mean(np.abs(y_p_test-y_test))*100}%")
trainingaccuracy:100.0%
可视化决策边界
In[13]:
defplot_hyperplane(X,y,weights,bias):"""Plotsthedatasetandtheestimateddecisionhyperplane"""slope=-weights[0]/weights[1]intercept=-bias/weights[1]x_hyperplane=np.linspace(-10,10,10)y_hyperplane=slope*x_hyperplane+interceptfig=plt.figure(figsize=(8,6))plt.scatter(X[:,0],X[:,1],c=y)plt.plot(x_hyperplane,y_hyperplane,'-')plt.title("Datasetandfitteddecisionhyperplane")plt.xlabel("Firstfeature")plt.ylabel("Secondfeature")plt.show()
In[14]:
plot_hyperplane(X,y,w_trained,b_trained)
04K最近邻算法
k-nn算法是一种简单的监督式的机器学习算法,可以用于解决分类和回归问题。这是一个基于实例的算法,并不是估算模型,而是将所有训练样本存储在内存中,并使用相似性度量进行预测。
给定一个输入示例,k-nn算法将从内存中检索k个最相似的实例。相似性是根据距离来定义的,也就是说,与输入示例之间距离最小(欧几里得距离)的训练样本被认为是最相似的样本。
输入示例的目标值计算如下:
分类问题:
a)不加权:输出k个最近邻中最常见的分类
b)加权:将每个分类值的k个最近邻的权重相加,输出权重最高的分类
回归问题:
a)不加权:输出k个最近邻值的平均值
b)加权:对于所有分类值,将分类值加权求和并将结果除以所有权重的总和
加权版本的k-nn算法是改进版本,其中每个近邻的贡献值根据其与查询点之间的距离进行加权。下面,我们在sklearn用k-nn算法的原始版本实现数字数据集的分类。
importnumpyasnpimportmatplotlib.pyplotaspltfromsklearn.datasetsimportload_digitsfromsklearn.model_selectionimporttrain_test_splitnp.random.seed(123)%matplotlibinline
#Wewillusethedigitsdatasetasanexample.Itconsistsofthe1797imagesofhand-writtendigits.Eachdigitis#representedbya64-dimensionalvectorofpixelvalues.digits=load_digits()X,y=digits.data,digits.targetX_train,X_test,y_train,y_test=train_test_split(X,y)print(f'X_trainshape:{X_train.shape}')print(f'y_trainshape:{y_train.shape}')print(f'X_testshape:{X_test.shape}')print(f'y_testshape:{y_test.shape}')#Exampledigitsfig=plt.figure(figsize=(10,8))foriinrange(10):ax=fig.add_subplot(2,5,i+1)plt.imshow(X[i].reshape((8,8)),cmap='gray')
X_trainshape:(1347,64)
y_trainshape:(1347,)
X_testshape:(450,64)
y_testshape:(450,)
K最邻近类别
In[11]:
knn=kNN()knn.fit(X_train,y_train)print("Testingonedatapoint,k=1")print(f"Predictedlabel:{knn.predict(X_test[0],k=1)}")print(f"Truelabel:{y_test[0]}")print()print("Testingonedatapoint,k=5")print(f"Predictedlabel:{knn.predict(X_test[20],k=5)}")print(f"Truelabel:{y_test[20]}")print()print("Testing10datapoint,k=1")print(f"Predictedlabels:{knn.predict(X_test[5:15],k=1)}")print(f"Truelabels:{y_test[5:15]}")print()print("Testing10datapoint,k=4")print(f"Predictedlabels:{knn.predict(X_test[5:15],k=4)}")print(f"Truelabels:{y_test[5:15]}")print()
Testingonedatapoint,k=1
Predictedlabel:3
Truelabel:3
Testingonedatapoint,k=5
Predictedlabel:9
Truelabel:9
Testing10datapoint,k=1
Predictedlabels:[[3107400516]]
Truelabels:[3107400516]
Testing10datapoint,k=4
Predictedlabels:[3,1,0,7,4,0,0,5,1,6]
测试集精度
In[12]:
#Computeaccuracyontestsety_p_test1=knn.predict(X_test,k=1)test_acc1=np.sum(y_p_test1[0]==y_test)/len(y_p_test1[0])*100print(f"Testaccuracywithk=1:{format(test_acc1)}")y_p_test8=knn.predict(X_test,k=5)test_acc8=np.sum(y_p_test8==y_test)/len(y_p_test8)*100print(f"Testaccuracywithk=8:{format(test_acc8)}")
Testaccuracywithk=1:97.77777777777777
Testaccuracywithk=8:97.55555555555556
05K均值聚类算法
K-Means是一种非常简单的聚类算法(聚类算法都属于无监督学习)。给定固定数量的聚类和输入数据集,该算法试图将数据划分为聚类,使得聚类内部具有较高的相似性,聚类与聚类之间具有较低的相似性。
算法原理
1.初始化聚类中心,或者在输入数据范围内随机选择,或者使用一些现有的训练样本(推荐)
2.直到收敛
目标函数
聚类算法的目标函数试图找到聚类中心,以便数据将划分到相应的聚类中,并使得数据与其最接近的聚类中心之间的距离尽可能小。
给定一组数据X1,...,Xn和一个正数k,找到k个聚类中心C1,...,Ck并最小化目标函数:
这里:
K-Means算法的缺点:
In[21]:
importnumpyasnpimportmatplotlib.pyplotaspltimportrandomfromsklearn.datasetsimportmake_blobsnp.random.seed(123)%matplotlibinline
In[22]:
X,y=make_blobs(centers=4,n_samples=1000)print(f'Shapeofdataset:{X.shape}')fig=plt.figure(figsize=(8,6))plt.scatter(X[:,0],X[:,1],c=y)plt.title("Datasetwith4clusters")plt.xlabel("Firstfeature")plt.ylabel("Secondfeature")plt.show()
Shapeofdataset:(1000,2)
K均值分类
初始化并调整模型
kmeans=KMeans(n_clusters=4)kmeans.fit(X)
Trainingfinishedafter4iterations!
描绘初始和最终的聚类中心
kmeans.plot_clusters(X)
06简单的神经网络
在这一章节里,我们将实现一个简单的神经网络架构,将2维的输入向量映射成二进制输出值。我们的神经网络有2个输入神经元,含6个隐藏神经元隐藏层及1个输出神经元。
我们的训练集由m=750个样本组成。因此,我们的矩阵维度如下:
损失函数
我们使用与Logistic回归算法相同的损失函数:
对于多类别的分类任务,我们将使用这个函数的通用形式作为损失函数,称之为分类交叉熵函数。
训练
我们将用梯度下降法来训练我们的神经网络,并通过反向传播法来计算所需的偏导数。训练过程主要有以下几个步骤:
1.初始化参数(即权重量和偏差量)
2.重复以下过程,直到收敛:
前向传播过程
首先,我们计算网络中每个单元的激活值和输出值。为了加速这个过程的实现,我们不会单独为每个输入样本执行此操作,而是通过矢量化对所有样本一次性进行处理。其中:
隐层神经元将使用tanh函数作为其激活函数:
输出层神经元将使用sigmoid函数作为激活函数:
激活值和输出值计算如下(·表示点乘):
反向传播过程
对于输出神经元,梯度计算如下(矩阵符号):
对于输入和隐层的权重矩阵,梯度计算如下:
权重更新
importnumpyasnpimportpandasaspdimportmatplotlib.pyplotaspltfromsklearn.datasetsimportmake_circlesfromsklearn.model_selectionimporttrain_test_splitnp.random.seed(123)%matplotlibinline
X,y=make_circles(n_samples=1000,factor=0.5,noise=.1)fig=plt.figure(figsize=(8,6))plt.scatter(X[:,0],X[:,1],c=y)plt.xlim([-1.5,1.5])plt.ylim([-1.5,1.5])plt.title("Dataset")plt.xlabel("Firstfeature")plt.ylabel("Secondfeature")plt.show()
#reshapetargetstogetcolumnvectorwithshape(n_samples,1)y_true=y[:,np.newaxis]#SplitthedataintoatrainingandtestsetX_train,X_test,y_train,y_test=train_test_split(X,y_true)print(f'ShapeX_train:{X_train.shape}')print(f'Shapey_train:{y_train.shape}')print(f'ShapeX_test:{X_test.shape}')print(f'Shapey_test:{y_test.shape}')
NeuralNetworkClass
以下部分实现受益于吴恩达的课程
初始化并训练神经网络
nn=NeuralNet(n_inputs=2,n_hidden=6,n_outputs=1)print("Shapeofweightmatricesandbiasvectors:")print(f'W_hshape:{nn.W_h.shape}')print(f'b_hshape:{nn.b_h.shape}')print(f'W_oshape:{nn.W_o.shape}')print(f'b_oshape:{nn.b_o.shape}')print()print("Training:")nn.train(X_train,y_train,n_iters=2000,eta=0.7)
Shapeofweightmatricesandbiasvectors:
W_hshape:(2,6)
b_hshape:(1,6)
W_oshape:(6,1)
b_oshape:(1,1)
Training:
Costatiteration0:1.0872
Costatiteration100:0.2723
Costatiteration200:0.1712
Costatiteration300:0.1386
Costatiteration400:0.1208
Costatiteration500:0.1084
Costatiteration600:0.0986
Costatiteration700:0.0907
Costatiteration800:0.0841
Costatiteration900:0.0785
Costatiteration1000:0.0739
Costatiteration1100:0.0699
Costatiteration1200:0.0665
Costatiteration1300:0.0635
Costatiteration1400:0.061
Costatiteration1500:0.0587
Costatiteration1600:0.0566
Costatiteration1700:0.0547
Costatiteration1800:0.0531
Costatiteration1900:0.0515
测试神经网络
n_test_samples,_=X_test.shapey_predict=nn.predict(X_test)print(f"Classificationaccuracyontestset:{(np.sum(y_predict==y_test)/n_test_samples)*100}%")
Classificationaccuracyontestset:98.4%
X_temp,y_temp=make_circles(n_samples=60000,noise=.5)y_predict_temp=nn.predict(X_temp)y_predict_temp=np.ravel(y_predict_temp)
fig=plt.figure(figsize=(8,12))ax=fig.add_subplot(2,1,1)plt.scatter(X[:,0],X[:,1],c=y)plt.xlim([-1.5,1.5])plt.ylim([-1.5,1.5])plt.xlabel("Firstfeature")plt.ylabel("Secondfeature")plt.title("Trainingandtestset")ax=fig.add_subplot(2,1,2)plt.scatter(X_temp[:,0],X_temp[:,1],c=y_predict_temp)plt.xlim([-1.5,1.5])plt.ylim([-1.5,1.5])plt.xlabel("Firstfeature")plt.ylabel("Secondfeature")plt.title("Decisionboundary")
Out[11]:Text(0.5,1,'Decisionboundary')
07Softmax回归算法
Softmax回归算法,又称为多项式或多类别的Logistic回归算法。
Softmax回归模型有以下几个特点:
训练Softmax回归模型有不同步骤。首先(在步骤0中),模型的参数将被初始化。在达到指定训练次数或参数收敛前,重复以下其他步骤。
我们可以通过矢量化和矢量传播法则计算所有类别及其训练样本的得分值:
同样地,我们可以通过矢量化来对所有类别同时处理,得到其概率输出。模型预测出的表示的是该类别的最高概率。
我们希望模型预测出的高概率值是目标类别,而低概率值表示其他类别。这可以通过以下的交叉熵损失函数来实现:
第5步:对每个类别k,更新其权重和偏置值。
fromsklearn.datasetsimportload_irisimportnumpyasnpfromsklearn.model_selectionimporttrain_test_splitfromsklearn.datasetsimportmake_blobsimportmatplotlib.pyplotaspltnp.random.seed(13)
X,y_true=make_blobs(centers=4,n_samples=5000)fig=plt.figure(figsize=(8,6))plt.scatter(X[:,0],X[:,1],c=y_true)plt.title("Dataset")plt.xlabel("Firstfeature")plt.ylabel("Secondfeature")plt.show()
#reshapetargetstogetcolumnvectorwithshape(n_samples,1)y_true=y_true[:,np.newaxis]#SplitthedataintoatrainingandtestsetX_train,X_test,y_train,y_test=train_test_split(X,y_true)print(f'ShapeX_train:{X_train.shape}')print(f'Shapey_train:{y_train.shape}')print(f'ShapeX_test:{X_test.shape}')print(f'Shapey_test:{y_test.shape}')
ShapeX_train:(3750,2)
Shapey_train:(3750,1)
ShapeX_test:(1250,2)
Shapey_test:(1250,1)
Softmax回归分类
regressor=SoftmaxRegressor()w_trained,b_trained,loss=regressor.train(X_train,y_train,learning_rate=0.1,n_iters=800,n_classes=4)fig=plt.figure(figsize=(8,6))plt.plot(np.arange(800),loss)plt.title("Developmentoflossduringtraining")plt.xlabel("Numberofiterations")plt.ylabel("Loss")plt.show()Iterationnumber:0,loss:1.393
Iterationnumber:100,loss:0.2051
Iterationnumber:200,loss:0.1605
Iterationnumber:300,loss:0.1371
Iterationnumber:400,loss:0.121
Iterationnumber:500,loss:0.1087
Iterationnumber:600,loss:0.0989
Iterationnumber:700,loss:0.0909
n_test_samples,_=X_test.shapey_predict=regressor.predict(X_test)print(f"Classificationaccuracyontestset:{(np.sum(y_predict==y_test)/n_test_samples)*100}%")