目录
摘要
Abstract
一、吴恩达机器学习Exp1——线性回归
1、单变量线性回归
1.1数据集的读取及可视化
1.2分割训练集和验证集
1.3扩展维度
1.4线性回归模型
1.5训练过程可视化
2、多变量线性回归
2.1加载数据集并可视化
2.2划分训练集和验证集
2.3线性回归模型
2.4训练过程可视化
二、李沐动手深度学习——数据集
总结
摘要
本周复习了线性回归模型的基本概念、步骤以及应用场景,进一步延伸到代码层面。动手实践了吴恩达机器学习实验1——线性回归,单变量线性回归和多变量线性回归分别用sklearn库的LinearRegression模型和自定义线性回归模型训练数据并且进行预测,最终得出效率和准确率的对比。该实验不仅复习了模型训练的基本步骤,还进一步手动代码实现了模型的定义、损失函数的设置以及最优化的处理。为了更加熟悉pytorch框架的基本知识,本周还简单学习了torch的数据处理方式。
Abstract
This week, we reviewed the basic concepts, steps, and application scenarios of linear regression modeling, and further extended to the code level. We have practiced the Ernst & Young Wu Machine Learning Experiment 1 - Linear Regression. Univariate linear regression and multivariate linear regression were used to train the data and make predictions using the LinearRegression model and custom linear regression model of sklearn library respectively, and finally, we have the comparison of the efficiency and accuracy rate. The experiment not only reviews the basic steps of model training, but also further implements the model definition, loss function setting and optimization processing by manual code. In order to become more familiar with the basics of the pytorch framework, this week also briefly learned how to handle data in torch.
一、吴恩达机器学习Exp1——线性回归
在前面的李宏毅深度学习中,学习了线性回归的基本训练步骤:建立模型——>设置损失函数——>最优化。详见周报(二)
线性回归字面来看,就是通过历史已知数据来预测未来数据。
1、单变量线性回归
单变量线性回归就是找到一维方程,拟合一条直线。
step1 建立模型
step2 损失函数
step3 最优化
在机器学习算法中,对于很多监督学习模型,需要对原始的模型构建损失函数,接下来便是通过优化算法对损失函数进行优化,以便寻找到最优的参数。
在机器学习的参数优化算法中,梯度下降优化算法是最常见的。
采用批梯度下降法
1.1数据集的读取及可视化
data = np.loadtxt('ex1data1.txt', delimiter=',')
fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(x=data[:, 0], y=data[:, 1], s=10)
plt.show()
1.2分割训练集和验证集
from sklearn.model_selection import train_test_split
train_x, val_x, train_y, val_y = train_test_split(data[:, 0], data[:, 1], test_size=0.5)
# train_x, val_x, train_y, val_y = data[:, :-1], data[:, :-1], data[:, -1], data[:, -1]fig, ax = plt.subplots(figsize=(12,8))
ax.scatter(x=train_x, y=train_y, s=10, label="Train")
ax.scatter(x=val_x, y=val_y, s=10, color="red", label="Validation")
ax.legend()
plt.show()
1.3扩展维度
train_x_ex = np.expand_dims(train_x,axis=1)
train_y_ex = np.expand_dims(train_y,axis=1)
val_x_ex = np.expand_dims(val_x,axis=1)
val_y_ex = np.expand_dims(val_y,axis=1)
1.4线性回归模型
方法一:自己定义线性回归模型
定义回归模型
需要自定义两个:一个是线性回归类”Linear_Regression“、一个是误差函数”square_loss”
(1)误差函数
def square_loss(pred, target):return np.sum(np.power((pred - target), 2)) / (2 * pred.shape[0])
其中pred是预测值、target是真实值
(2)线性回归
传参
class LinearRegression:def __init__(self, x, y, val_x, val_y, epoch=100, lr=0.1, regularize=False, scale=0):self.theta = Noneself.loss = []self.val_loss = []self.n = x.shape[0]self.d = x.shape[1]self.epoch = epochself.lr = lrt = 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_stdself.y = yself.x = np.concatenate((t, x_norm), axis=1)self.val_x = val_xself.val_y = val_yself.regularize = regularizeself.scale = scale
其中x是样本、y是标签、epoch是训练迭代次数、lr是学习率、regularize代表是否归一化
参数初始化
def init_theta(self):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)return curr_loss
theta是记录 、validation是记录当前损失值
梯度下降
def gradient_decent(self, pred):error = pred - self.y # error (n,1)误差:预测-标签gradient = np.matmul(self.x.T, error) # gradient (d+1, 1) 矩阵乘法:计算梯度,这是损失函数相对于参数 theta 的导数gradient = gradient.T / pred.shape[0] # average gradient (1,d+1) 将梯度转置并除以样本数量,得到平均梯度。if self.regularize: #是否需要正则化reg_term = self.scale / self.n * self.theta[:, 1:] #计算正则化项reg_term[:, 0] = 0 #将正则化项的第一个元素设置为0,因为偏置项不进行正则化gradient = gradient + reg_term #将正则化项加到梯度上self.theta = self.theta - (self.lr / self.n) * gradient #更新参数
训练线性回归模型
def train(self):self.init_theta() #调用“theta的初始化函数”for i in range(self.epoch): #迭代训练pred = np.matmul(self.theta, self.x.T) #计算预测值predpred = pred.T #调整pred的形状curr_loss = square_loss(pred, self.y) #计算当前的训练损失val_loss = self.validation(self.val_x, self.val_y) #调用“validation方法”计算验证集损失self.gradient_decent(pred) #更新模型参数thetaif self.regularize: #判断是否正则化curr_loss = curr_loss + (self.scale / (2 * self.n)) * np.power(self.theta[:, 1:], 2).sum()val_loss = val_loss + (self.scale / (2 * self.n)) * np.power(self.theta[:, 1:], 2).sum()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)) #打印每个周期的训练损失和验证损失# 反归一化参数self.theta[0, 1:] = self.theta[0, 1:] / self.x_std.Tself.theta[0, 0] = self.theta[0, 0] - np.dot(self.theta[0, 1:], self.x_mean)return self.theta, self.loss, self.val_loss
模型的训练这个函数主要包含两个部分:一个是迭代训练的过程(计算损失、梯度下降、更新参数、正则化) ,另一个是反归一化的过程
回归预测
def predict(self, x):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
其中参数x是输入样本,最终返回的pred.T是预测结果
训练参数记录
linear_reg.fit(train_x_ex, train_y_ex)from Linear_Regression import LinearRegressionepochs = 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()#查看训练时间,计算在验证集上的损失
print("Train Time: {:.4f}s".format(end_time-start_time))
from Linear_Regression import square_loss
pred_val = linear_reg.predict(val_x_ex)
loss_val = square_loss(pred_val, val_y_ex)
print("Val Loss: {:.4f}".format(loss_val))
方法二:用sklearn库直接进行模型预测
用sklearn库进行验证
from sklearn.linear_model import LinearRegression
sklearn_lr = LinearRegression()
sk_start_time = time.time()
sklearn_lr.fit(train_x_ex,train_y_ex)
sk_end_time = time.time()sk_theta = [sklearn_lr.intercept_[0],sklearn_lr.coef_[0, 0]]
sk_lr_pred = sklearn_lr.predict(val_x_ex)from Linea_Regression import square_loss
sk_loss_val = square_loss(sk_lr_pred, val_y_ex)
print("Sklearn Val Loss: {:.4f}".format(sk_loss_val))
print("Sklearn Parameters: ", sklearn_lr.intercept_, sklearn_lr.coef_)
print("Sklearn Train Time: {:.4f}s".format(sk_end_time-sk_start_time))
综上所述,自定义模型无论在效率还是准确率方面都表现较好。
1.5训练过程可视化
1.5.1预测直线
1.5.2训练损失函数
2、多变量线性回归
2.1加载数据集并可视化
data2 = np.loadtxt('ex1data2.txt', delimiter=',')
plt.figure(dpi=150)
ax = plt.axes(projection='3d')
ax.scatter3D(data2[:,0],data2[:,1],data2[:,2],s=10)
plt.show()
2.2划分训练集和验证集
代码同上
下面的步骤,比如模型训练的时间及验证集的损失的记录,将自己定义的模型与sklearn中的调用模型进行对比。
2.3线性回归模型
如上图结果所示, 左边是自定义的模型训练、右边是sklearn库中的自带模型训练,总的来说,无论是效率还是准确率方面自定义都不如sklearn库中的模型。
2.4训练过程可视化
2.4.1预测
2.4.2训练损失函数
二、李沐动手深度学习——数据集
前面动手跑模型是为了完成李宏毅深度学习的课程作业,对于pytorch的理解不是很深,接下来将跟着动手逐行学习深度学习。
张量的形状和大小
import torch
x = torch.arange(12)
x,x.shape,x.numel()
把多个张量结合在一起
x = torch.arange(12, dtype=torch.float32).reshape((3,4))
y = torch.tensor([[2.0, 1, 4, 3], [1, 2, 3, 4], [4, 3, 2, 1]])
torch.cat((x, y), dim=0), torch.cat((x,y), dim=1)
torch.cat() 方法主要是拼接两个张量,其中的dim参数决定两个张量拼接的维度是哪个。比如上述,dim=0代表二者是在第一个维度进行拼接(也就是最外层括号),dim=1代表二者在第二个维度进行拼接(也就是从外数第二个括号)
通过逻辑运算符构建二元张量
x == y
输出的张量是布尔表示的。
广播机制
a = torch.arange(3).reshape((3,1))
b = torch.arange(2).reshape(1,2)
a,b,a+b
通过调用广播机制broadcasting mechanism,来执行按元素操作。它将一个进程中的张量(tensor)或数据广播到所有其他进程。
转化为numpy张量
A = x.numpy()
B = torch.tensor(A)
type(A), type(B)
总结
本周侧重于代码实践部分,一部分是pytorch的简单数据处理,另一部分是线性回归模型的代码编写,包含了模型定义、损失函数计算以及最优化的处理过程。下周继续学习机器学习的实验和深度学习的pytorch的基础代码。