1.单变量线性回归
数据介绍:在本练习的这一部分中,您将使用一个变量实现线性回归,以预测餐厅的利润。假设你是一家连锁餐厅的首席执行官,正在考虑在不同的城市开设一家新餐厅,你可以得到城市的利润和人口数据。
1.1 画出原始数据图
import matplotlib.pyplot as plt
import pandas as pd
data = pd.read_csv('ex1data1.txt', names=['population', 'profit']) # 读取数据并赋予列名
展示前5行数据
data.head()
画出原始数据图
data.plot(kind='scatter', x='population', y='profit', figsize=(12,8))
plt.show()
1.2 数据处理
插入一列特征,其值均为1,目的为了在矩阵运算时匹配偏置。
# 插入全1列x0
data.insert(0, 'Ones', 1)
将特征值和目标值从数据中提取出来
# set X (training data) and y (target variable)
cols = data.shape[1] # 特征值的数量n
X = data.iloc[:,0:cols-1] # X是所有行,去掉最后一列
y = data.iloc[:,cols-1:cols] # y是所有行,最后一列
将dataframe类型转换为np.matrix
# 构造矩阵和向量
X = np.matrix(X.values)
y = np.matrix(y.values)
# 初始化权重为0,1*2向量
theta = np.matrix(np.array([0,0]))
1.3 创建损失函数
损失函数数学模型(MSE)
创建损失函数# 构建损失函数
def computeCost(X, y, theta):
inner = np.power(((X * theta.T) - y), 2) # J(θ)内部函数
return np.sum(inner) / (2 * X.shape[0]) # X.shape[0]是样本数m
1.4 创建梯度下降函数
数学模型(批量梯度下降)
# 构造梯度下降函数
def gradientDescent(X, y, final_theta, alpha, iters):
temp = np.matrix(np.zeros(theta.shape))
# 特征数n
featrue_num = int(theta.shape[1])
# 用来保存损失值
cost = np.zeros(iters)
# 用来保存θ的值
theta0_list = []
theta1_list = []
for i in range(iters):
# 梯度下降模型内部函数
inner = (X * final_theta.T) - y
# 分别迭代不同特征
for j in range(featrue_num):
term = np.multiply(inner, X[:,j])
temp[0,j] = final_theta[0,j] - ((alpha / X.shape[0]) * np.sum(term))
# 保存变量
theta0_list.append(temp[0,0])
theta1_list.append(temp[0,1])
final_theta = temp
cost[i] = computeCost(X, y, final_theta)
return final_theta, cost,theta0_list,theta1_list
1.5 进行训练并绘图
真实值和预测值的对比
# 进行梯度下降运算
g, cost, theta0, theta1 = gradientDescent(X, y, theta, alpha, iters)
# 绘制拟合图
x = np.linspace(df.population.min(), df.population.max(), 100) # 返回在指定范围内的100个等间隔数
f = g[0, 0] + (g[0, 1] * x) # 预测值
# 设置子画布
fig, ax = plt.subplots(figsize=(12,8))
ax.plot(x, f, 'r', label='Prediction')
ax.scatter(df.population, df.profit, label='Traning Data')
ax.legend(loc=2) # 设置标签
ax.set_xlabel('Population')
ax.set_ylabel('Profit')
ax.set_title('Predicted Profit vs. Population Size')
plt.show()
迭代次数和损失值的对比
# 绘制损失函数变化
fig, ax = plt.subplots(figsize=(12,8))
ax.plot(np.arange(iters), cost, 'r') # np.arange():生成自然数组
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title('Error vs. Training Epoch')
plt.show()
1.6 θ值和损失值的对比,3D图
python中3d图的绘制值得探讨,先贴代码
# 绘制3D图
from mpl_toolkits.mplot3d import Axes3D
# 创建对象
fig = plt.figure()
ax = Axes3D(fig)
# 指定值选取范围
axis=[min(theta0)-0.5, max(theta0)+0.5,min(theta1)-0.5, max(theta1)+0.5]
X0, X1 = np.meshgrid(
# 随机两组数,起始值和密度由坐标轴的起始值决定
np.linspace(axis[0], axis[1], int((axis[1] - axis[0]) * 200)).reshape(-1, 1),
np.linspace(axis[2], axis[3], int((axis[3] - axis[2]) * 200)).reshape(-1, 1),
)
# ravel()方法将高维数组降为一维数组,c_[]将两个数组以列的形式拼接起来,形成矩阵
X_grid_matrix = np.c_[X0.ravel(), X1.ravel()]
# 这一部分是计算cost损失值
inner = np.power(((X * X_grid_matrix.T) - y), 2)
inner = inner.sum(axis=0) / (2 * X.shape[0])
Z = inner.reshape(X0.shape)
# 设置标签
ax.set_xlabel("theta0")
ax.set_ylabel("theta1")
ax.set_zlabel("cost")
# 绘制3D曲面图
ax.plot_surface(X0, X1, Z, rstride=10, cstride=10, cmap='rainbow')
ax.view_init(30, 70) # 改变视角
plt.show()
由此图可以直观的看出梯度下降的大致方向,其中:
引自:程序员说
- np.meshgrid():该函数将随机出的两组数以坐标点的形式组合起来,其中X0为横坐标的组合,X1为纵坐标的组合
- np.c_[]:将两个一维数组拼接起来,最终形成一个n * 2的矩阵,即每个点坐标的组合
另外,在计算损失值时用np.mat().sum(axis=0)
的目的是将矩阵的每列求和,返回一个1 * n的矩阵。
2.用TensorFlow实现线性回归
数据介绍:在这一部分中,你将使用多元线性回归来预测房价。假设你要卖房子,你想知道一个好的市场价格是多少。一种方法是首先收集最近售出房屋的信息,并制作一个房价模型。 文件ex1data2.txt包含俄勒冈州波特兰市的房价培训集。第一栏是房子的大小(以平方英尺为单位),第二栏是卧室的数量,第三栏是房子的价格。
2.1 读取数据,特征归一化
因为数据的量纲相差较大,故需要进行特征归一化
# 读取数据
data = pd.read_csv('ex1data2.txt', header=None, names=['Size', 'Bedrooms', 'Price'])
# 特征归一化
data = (data - data.mean()) / data.std()
data.head()
2.2 提取数据
因为需要在tf设置float32类型的占位符,并且feed数据的时候不支持dataframe类型,所以将dataframe --> ndarray。
# add ones column
data.insert(0, 'Ones', 1)
# set X (training data) and y (target variable)
cols = data.shape[1]
X = data.iloc[:,0:cols-1]
y = data.iloc[:,cols-1:cols]
# 数据类型转换 dataframe --> ndarray
X = X.values.astype(np.float32)
y = y.values.astype(np.float32)
2.3 创建tf函数
函数返回损失值列表和最后的权重值
def linear_regression(X_data, y_data, alpha, epoch):
# 设置占位符
X = tf.placeholder(tf.float32, shape=X_data.shape)
y = tf.placeholder(tf.float32, shape=y_data.shape)
# 构造线性回归算法
with tf.variable_scope('linear-regression'):
W = tf.get_variable("weights",
(X_data.shape[1], 1),
initializer=tf.constant_initializer()) # 创建权重
y_pred = tf.matmul(X, W) # m*n @ n*1 -> m*1
# 损失函数
loss = 1 / (2 * X_data.shape[0]) * tf.matmul((y_pred - y), (y_pred - y), transpose_a=True) # (m*1).T @ m*1 = 1*1
# 梯度下降优化
train_op = tf.train.GradientDescentOptimizer(alpha).minimize(loss)
# run the session
with tf.Session() as sess:
# 变量初始化
sess.run(tf.global_variables_initializer())
loss_data = []
for i in range(epoch):
_, loss_val, W_val = sess.run([train_op, loss, W], feed_dict={X: X_data, y: y_data})
# print(loss_val)
loss_data.append(loss_val[0, 0]) # because every loss_val is 1*1 ndarray
if len(loss_data) > 1 and np.abs(loss_data[-1] - loss_data[-2]) < 10 ** -9: # early break when it's converged
print('Converged at epoch {}'.format(i))
break
# clear the graph
tf.reset_default_graph()
return {'loss': loss_data, 'parameters': W_val} # just want to return in row vector format
2.4 绘制迭代图
迭代次数和损失值的对比
result = linear_regression(X,y,0.1,1000)
# 绘制损失函数变化
fig, ax = plt.subplots(figsize=(12,8))
ax.plot(np.arange(152), result['loss'], 'r') # np.arange():生成自然数组
ax.set_xlabel('Iterations')
ax.set_ylabel('Cost')
ax.set_title('Error vs. Training Epoch')
plt.show()