吴恩达机器学习ex1
简单写一下自己的总结
part1:
概念部分:
监督学习:提供了数据X与Y,有回归任务和分类任务
非监督学习:仅提供了数据X,有聚类任务
如本题的“预测房屋价格”即属于监督学习中回归任务
part2:
代码部分:
本人对python中numpy、pandas和matplotlib等库使用很不熟悉,在尝试编写此题目代码时,学习用到了许多函数,记录一下,以某一行或某一部分代码进行学习。
- 1
path = "ex1data1.txt"
data = pd.read_csv(path,header=None,names=['population','profit'])
data.head()
(1)这样处理得到的data是DataFrame格式的数据,需要有表头,但原数据ex1data1.txt并没有表头,所以需要在函数中说明header=None,并给出自己想要的表头names=[‘population’,‘profit’])
DataFrame是Pandas库中的核心数据结构,以表格形式存储二维数据(类似Excel或SQL表)。特点包括:
每列可以是不同的数据类型(数值、字符串、布尔值等)。
支持行索引和列标签,方便数据定位和操作。
提供丰富的内置方法(如合并、分组、过滤、统计等)。
(2)ex1data1.txt的数据之间是用逗号分隔的,所以可以当作.csv文件使用。
(3)data.head()展示前5行数据,便于查看数据是否有误。
- 2
data.plot(kind='scatter',x='population',y='profit',figsize=(12,8))
刚刚得到的data包含画图plot这一方法,实则内部还是在调用matplotlib。
- 3
# X:population中的数据+给其增添一列数据1,便于与theta进行矩阵运算; y:profit中的数据; theta:要确定的两个参数,shape为(2,1)
def ComputeCost(X,y,theta):
h=np.power((X @ theta - y),2)
return np.sum(h) / (2*X.shape[0])
创建成本函数,其公式为:
J(θ)=12m∑i=1m(hθ(x(i))−y(i))2
J(\theta)=\frac{1}{2m}\sum_{i=1}^{m}(h_\theta(x^{(i)})-y^{(i)})^2
J(θ)=2m1i=1∑m(hθ(x(i))−y(i))2
其中,假设hθ(x)h_\theta(x)hθ(x)是一个线性模型:
hθ(x)=θ0+θ1x
h_\theta(x)=\theta_0+\theta_1x
hθ(x)=θ0+θ1x
该函数方法延伸到多变量的回归任务时,仍可使用。
这里说明一下X,y,theta的shape:
| variable | shape |
|---|---|
| X | (97,2) |
| y | (97,1) |
| theta | (2,1) |
X.shape[0]即公式里的m
上述函数使用矩阵运算,优于使用for循环进行计算。
以后写的代码中多尝试使用矩阵运算
- 4
处理数据,得到所需的X,y,theta
X=(data['population']).to_numpy()
y=(data['profit']).to_numpy()
X=X.reshape(-1,1)
y=y.reshape(-1,1)
m=X.shape[0]
one_columun=np.ones((m,1))
X=np.concatenate((one_columun,X),axis=1)
这样得到的X,y是np类型的数据,并给X插入了一列1,否则X只是一维的数据,无法进行ComputeCost中的矩阵运算。
data[‘列名’],可以得到该列的数据
X.reshape(-1,1),可以得到shape为(97,1)的二维数据,第一个参数为-1表示处理全部的数据。在进行这一步之前,X的shape为(97,)的一维数据。可以看出这样处理X,y较麻烦。可以使用下面的代码,更简单。
col=data.shape[1]
X=(data.iloc[:,:col-1]).to_numpy()
y=(data.iloc[:,col-1:col]).to_numpy()
data.iloc的用法,行列之间用逗号隔开。
例如data.iloc[1:4]表示第2到4行(左闭右开)
data.iloc[:,:2]表示所有行,从头到第2列
one_columun=np.ones((m,1))创造了一个全为1的数组。
X=np.concatenate((one_columun,X),axis=1)合并两个数组,其中axis=1表示合并列。
- 5
batch gredient descent(批量梯度下降)公式
θj:=θj−α∂∂θjJ(θi)
{\theta}_{j}:={\theta}_{j}-\alpha \frac{\partial}{\partial{\theta}_{j}}J\left(\theta_i \right)
θj:=θj−α∂θj∂J(θi)
其中∂∂θjJ(θi)\frac{\partial}{\partial{\theta}_{j}}J\left(\theta_i \right)∂θj∂J(θi)通过求导公式可以得到:
∂∂θ0J(θ0)=1m∑i=1m(h(xi)−yi)
\frac{\partial}{\partial{\theta}_{0}}J\left(\theta_0 \right)=\frac{1}{m} \sum_{i=1}^{m} (h(x^{i})-y^{i})
∂θ0∂J(θ0)=m1i=1∑m(h(xi)−yi)
∂∂θ1J(θ1)=1m∑i=1m(h(xi)−yi)xi
\frac{\partial}{\partial{\theta}_{1}}J\left(\theta_1 \right)=\frac{1}{m} \sum_{i=1}^{m} (h(x^{i})-y^{i})x^{i}
∂θ1∂J(θ1)=m1i=1∑m(h(xi)−yi)xi
在批量梯度下降(Batch Gradient Descent, BGD)中,“批量”指的是每次迭代时使用整个训练数据集的所有样本计算损失函数的梯度。与随机梯度下降(SGD)或小批量梯度下降(Mini-batch Gradient Descent)不同,BGD的“批量”规模始终等于数据集的总样本数。
#alpha:学习率;inters:迭代次数
def GradientDescent(alpha,inters,X,y,theta):
# 创建一个临时变量temp储存更新后的theta
temp=np.zeros(theta.shape)
# cost表示每次迭代的成本
cost=np.zeros(inters)
for i in range(inters):
error=X @ theta - y
temp=theta - (alpha / m) * (X.T @ error)
theta=temp
cost[i]=ComputeCost(X,y,theta)
return theta,cost
无需定义temp临时储存theta,因为使用了矩阵运算直接就得到了新的theta。
alpha=0.01
inters=1000
theta,cost=GradientDescent(alpha,inters,X,y,theta)
plt.figure(figsize=(12,8))
plt.plot(np.arange(0,inters,1),cost,color='blue')
plt.title('cost in each inter')
plt.xlabel('inters')
plt.ylabel('cost')
plt.show()
绘图,直观的去看成本的下降程度以及函数的拟合程度!
上为成本的下降图代码,下为函数的拟合程度代码。
plt.figure(figsize=(12,8))
plt.scatter(data['population'],data['profit'],color='blue',label='training data')
f=X @ theta
plt.plot(X[:,1],f,color='red',label='prediction')
plt.xlabel('population')
plt.ylabel('profit')
plt.legend()
plt.show()
绘图函数的使用,常规三步:
plt.figure(figsize=(12,8)),plt.plot(x,y),plt.show()。
- 6
试一下scikit-learn的线性回归函数,与自己写的结果进行比较,看有无较大差异。
from sklearn import linear_model
model=linear_model.LinearRegression()
X_df=X[:,1].reshape(-1,1)
model.fit(X_df,y)
model.fit(X_df,y)中,第一个参数填入n个指标的数据X,第二个参数填入1一个变量y。
print(f'截距theta0={theta[0,0]},斜率theta1={theta[1,0]}')
print(f'截距theta0={model.intercept_},斜率theta1={model.coef_}')
可以打印看一下结果差异,是不大的。
model.intercept_可以得到截距;model.coef_可以得到多个斜率,这里只有一个指标,所以它的shape为(1,1),n个指标则为(1,n)
同样可以将这个新的结果按上面的代码进行绘图。
part3
最后还尝试了多变量线性回归,原理一样,上面的两个函数ComputeCost和GradientDescent函数可以直接用。
多变量时需要考虑各个指标之间大小范围的问题,可能需要进行归一化处理。
为何要进行归一化处理呢?
个人理解:例如有两个指标x1,x2x_1,x_2x1,x2,其中x1x_1x1的数据范围为(0,1000),x2x_2x2的数据范围为(0,10),我们要拟合的方程为:y=w1x1+w2x2+by=w_1x_1+w_2x_2+by=w1x1+w2x2+b由于x1x_1x1的数据远大于x2x_2x2,在每次更新参数值时,w1w_1w1的微小变化可能会导致成本函数值的巨大变化,可能会降低收敛速度。
常见的归一化方法有很多,比如Z-Score标准化,我觉得最重要的是提前了解数据,至于使用哪种方法,只要最后的模型结果还不错,就可以。
没有尝试normal equation(正规方程),因为还不太明白公式怎么来的。只知道它类似于数学中我们计算解析值一样。但在计算机处理这类任务时,重要的是掌握数值解。
part4
学习率和迭代次数的确定。
学习率过小:每一次迭代的变化太小,速度太慢。
学习率过大:每一次迭代的变化太大,容易超调。
学习率α\alphaα可以从0.001,0.003,0.01,0.03,0.1。从小到大,每次约3倍,同时输出成本函数值随着每一次迭代的变化(此时先设置一个较小的迭代次数)。从而确定一个不小不大的学习率。此外,这一步骤还可以帮助我们检查代码是否有误。
迭代次数同样可以通过绘制成本函数值随着每一次迭代的变化来确定。可以手动确定,也可以通过代码确定。前者通过观察曲线的变化,在曲线开始平坦时,就是一个合适的迭代次数;后者可以通过程序判断每一次迭代的变化量,当其小于某一给定值,例如10−310^{-3}10−3时,即可退出迭代。
part5
代码已上传资源中心。
最后,欢迎探讨、交流和学习!共同进步!
吴恩达ML ex1 Python实现
530

被折叠的 条评论
为什么被折叠?



