在Anaconda环境下的jupyter进行编写的,之前一直在用pycharm编译器,改为jupyter后发现更方便运行,便于观察每一行代码的输出。在看过了吴恩达老师的machine_learning,再动手实践一下。
细节我就不说了,主要结合具体的代码,来看原理。
下图是我的前五行数据集:
import pandas as pd
df = pd.read_csv('ex1data1.txt',names=['population','profit']
df.head()
这是单变量线性回归的函数,即预测结果
通过不断更新参数theta,得到更低的cost代价函数,保证更准确的预测,
那么怎么更新theta呢?如下:α是学习率,可以理解为每次移动的步长,
线性回归主要应用到的数学基础大概就是以上了。
线性回归的步骤:
1.读入数据,处理X,Y数据为矩阵
2.编写代价函数,更新theta的函数
3.下面是按照循环更新500次得到theta,也可以是代价函数到达一定值后停止更新。
4.得到theta后就可以画图把线性回归的直线表示出来。
下面结合代码说明下具体实现中有哪些注意的问题。
ones = pd.DataFrame({'ones': np.ones(len(df))})#生成ones 97个 都为1
data = pd.concat([ones, df], axis=1) # 合并数据,根据列合并 合并ones和df
array = data.iloc[:, :-1].as_matrix() #把 dataframe类型转换为np数组-------data.iloc() 和data.loc()的区别,loc按照索引,iloc按照顺序
#逗号前表示行数,后表示列数
array_y = np.array(df.iloc[:,-1])
theta = np.zeros(array.shape[1])#theta初始化为0
得到的x数据,可以看到下图中加了一列全部为1的数据,因为预测函数中theta0没有与它相乘的数,为了使x和theta矩阵能够相乘,所以给x的第一列设为1.theta矩阵初始化的时候[0,0]
计算代价函数, ,m=97,就是个矩阵相乘的操作,((97,2)*(2,1)-(97,1))/2*m.(ps:(97,2),表示矩阵的维度,最后相乘得到的是个数)。
m = X.shape[0]#m为样本数m=97
inner = X @ theta - y
square_sum = inner.T @ inner
cost = square_sum / (2 * m)
采用梯度下降,更新theta,学习率alpha=0.01,循环次数epoch=500,for _ in range(epoch):
_theta = _theta - alpha * gradient(_theta, X, y)#更新theta
cost_data.append(lr_cost(_theta, X, y))#计算代价
gradient计算这一部分,theta0的xi为1,
返回的值(2,97)*((97,2)*(2,1)-(97,1))/m. 最后是(2,1)的数组,所以可以用来更新theta
def gradient(theta, X, y):
m = X.shape[0]
inner = X.T @ (X @ theta - y)
return inner / m
最后得到的代价函数随循环次数变化的曲线:
线性回归结果:
多变量线性回归,先标准化数据,其他步骤相同。
df.apply(lambda column: (column - column.mean()) / column.std())