线性回归
什么是线性回归就不说了,直接说线性回归的目标就是首先需要一个损失函数,使得损失函数最小化来训练得出的模型,最常用的损失函数是均方误差
例子
如果要预测房屋平均售价之前需要对数据标准化,用到StandarScalar这个类,可以计算平均值方差,输出标准化后的值
from sklearn.linear_model import LinearRegression# 初始化线性模型
linreg = LinearRegression()
# LinearRegression的方法中已经考虑了线性回归的常数项,所以无须再拼接1
linreg.fit(x_train, y_train)# coef_是训练得到的回归系数,intercept_是常数项
print('回归系数:', linreg.coef_, linreg.intercept_)
y_pred = linreg.predict(x_test)# 计算预测值和真实值之间的RMSE
rmse_loss = np.sqrt(np.square(y_test - y_pred).mean())
print('RMSE:', rmse_loss)
梯度下降 (GD)
梯度也就是寻找函数增加变化最快的方向,反方向就是减小最多的方向,如果损失函数按照梯度的反方向调整,很快就可以减小了。这个呢可能对于凸函数有用,但是非凸的时候,可能就不仅仅只有一个最小值(极小值),就可能出现局部最小的问题。
每次随机选择一个点来梯度下降寻找最小值也叫随机梯度下降(SGD),这样子也快也不复杂,但是可能不稳定,因为单个样本计算出来的可能与所有的不一致,再加上如果不是凸函数,可能下降梯度就发生偏移了,所以可以选择多个点来下降,可以使用小批量梯度下降(MBGD)也就是把样本随机分成批量来计算梯度,那么可以看出随机梯度下降是小批量的特例。MBGD的优点在于可以消除随机性,也比较稳定。
def batch_generator(x,y,batch_size,shuffle=True):batch_count=0if shuffle:idx=np.random.permutation(len(x))x=x[idx]y=y[idx]while True:start=batch_count*batch_sizeend=min(start+batch_size,len(x))if start>=end:breakbatch_count+=1yield x[start:end],y[start:end]
#%%def SGD(num_epoch,learning_rate,batch_size):#返回给定形状和数据类型的新数组X=np.concatenate([x_train,np.ones((len(x_train),1))],axis=-1)#axis=1表示对应行的数组进行拼接X_test=np.concatenate([x_test,np.ones((len(x_test),1))],axis=-1)theta=np.random.normal(size=X.shape[1]) #X大小那么大的 shape[1]是列数train_losses=[]test_losses=[]for i in range(num_epoch):batch_g=batch_generator(X,y_train,batch_size,shuffle=True)train_loss=0for x_batch,y_batch in batch_g:grad=x_batch.T@(x_batch@theta-y_batch)theta=theta-learning_rate*grad/len(x_batch)train_loss+=np.square(x_batch@theta-y_batch).sum()# 计算训练和测试误差train_loss = np.sqrt(train_loss / len(X))train_losses.append(train_loss)test_loss = np.sqrt(np.square(X_test @ theta - y_test).mean())test_losses.append(test_loss)# 输出结果,绘制训练曲线print('回归系数:', theta)return theta, train_losses, test_losses
#%%
# 设置迭代次数,学习率与批量大小
num_epoch = 20
learning_rate = 0.01
batch_size = 32
# 设置随机种子
# 设置随机种子
np.random.seed(0)
_, train_losses, test_losses = SGD(num_epoch, learning_rate, batch_size)
#%%
# 设置迭代次数,学习率与批量大小
num_epoch = 20
learning_rate = 0.01
batch_size = 32
# 设置随机种子
np.random.seed(0)_, train_losses, test_losses = SGD(num_epoch, learning_rate, batch_size)# 将损失函数关于运行次数的关系制图,可以看到损失函数先一直保持下降,之后趋于平稳
plt.plot(np.arange(num_epoch), train_losses, color='blue',label='train loss')
plt.plot(np.arange(num_epoch), test_losses, color='red',ls='--', label='test loss')
# 由于epoch是整数,这里把图中的横坐标也设置为整数
# 该步骤也可以省略
plt.gca().xaxis.set_major_locator(MaxNLocator(integer=True))
plt.xlabel('Epoch')
plt.ylabel('RMSE')
plt.legend()
plt.show()
其实还可以分析不同学习率下的结果,来调整合适的学习率,一般情况下学习率越大速度越快