数据:fetch_california_housing(加利福尼亚的房价数据)
1、解析解法
import tensorflow as tf import numpy as np from sklearn.datasets import fetch_california_housing # 立刻下载数据集 housing = fetch_california_housing(data_home="./datasets", download_if_missing=True) # 获得X数据行数和列数 m, n = housing.data.shape # 这里添加一个额外的bias输入特征(x0=1)到所有的训练数据上面,因为使用的numpy所有会立即执行 housing_data_plus_bias = np.c_[np.ones((m, 1)), housing.data] # 创建两个TensorFlow常量节点X和y,去持有数据和标签 X = tf.constant(housing_data_plus_bias, dtype=tf.float32, name='X') y = tf.constant(housing.target.reshape(-1, 1), dtype=tf.float32, name='y') # 使用一些TensorFlow框架提供的矩阵操作去求theta XT = tf.transpose(X) # 解析解一步计算出最优解 theta = tf.matmul(tf.matmul(tf.matrix_inverse(tf.matmul(XT, X)), XT), y) with tf.Session() as sess: theta_value = theta.eval() # sess.run(theta) print(theta_value)
2、梯度下降法(BSD)
import tensorflow as tf import numpy as np from sklearn.datasets import fetch_california_housing from sklearn.preprocessing import StandardScaler n_epochs = 10000 learning_rate = 0.01 housing = fetch_california_housing(data_home="./datasets", download_if_missing=False) m, n = housing.data.shape housing_data_plus_bias = np.c_[np.ones((m, 1)), housing.data] # 可以使用TensorFlow或者Numpy或者sklearn的StandardScaler去进行归一化 # StandardScaler默认就做了方差归一化,和均值归一化,这两个归一化的目的都是为了更快的进行梯度下降 # 你如何构建你的训练集,你训练除了的模型,就具备什么样的功能! scaler = StandardScaler().fit(housing_data_plus_bias) scaled_housing_data_plus_bias = scaler.transform(housing_data_plus_bias) X = tf.constant(scaled_housing_data_plus_bias, dtype=tf.float32, name='X') y = tf.constant(housing.target.reshape(-1, 1), dtype=tf.float32, name='y') # random_uniform函数创建图里一个节点包含随机数值,给定它的形状和取值范围,就像numpy里面rand()函数 theta = tf.Variable(tf.random_uniform([n + 1, 1], -1.0, 1.0), name='theta') y_pred = tf.matmul(X, theta, name="predictions") error = y_pred - y mse = tf.reduce_mean(tf.square(error), name="mse") # 梯度的公式:(y_pred - y) * xj gradients = 2/m * tf.matmul(tf.transpose(X), error) # 赋值函数对于BGD来说就是 theta_new = theta - (learning_rate * gradients) training_op = tf.assign(theta, theta - learning_rate * gradients) init = tf.global_variables_initializer() with tf.Session() as sess: sess.run(init) for epoch in range(n_epochs): if epoch % 100 == 0: print("Epoch", epoch, "MSE = ", mse.eval()) sess.run(training_op) best_theta = theta.eval() print(best_theta)
3、TensorFlow内部封装迭代
import tensorflow as tf import numpy as np from sklearn.datasets import fetch_california_housing from sklearn.preprocessing import StandardScaler # 前面的代码执行的不错,但是它需要数学上通过损失函数MSE来求导梯度 # 在线性回归的例子中,这样是可以的,看起来通过数学公式去求解不难 # 但是如果是深度学习,我们很难这样去做,会比较头疼,会很容易出错 # 幸运的是,TensorFlow提供的autodiff特性可以自动的并有效的计算梯度为我们 # reverse-mode autodiff n_epochs = 1000 learning_rate = 0.01 housing = fetch_california_housing() m, n = housing.data.shape housing_data_plus_bias = np.c_[np.ones((m, 1)), housing.data] # 可以使用TensorFlow或者Numpy或者sklearn的StandardScaler去进行归一化 scaler = StandardScaler().fit(housing_data_plus_bias) scaled_housing_data_plus_bias = scaler.transform(housing_data_plus_bias) X = tf.constant(scaled_housing_data_plus_bias, dtype=tf.float32, name='X') y = tf.constant(housing.target.reshape(-1, 1), dtype=tf.float32, name='y') # random_uniform函数创建图里一个节点包含随机数值,给定它的形状和取值范围,就像numpy里面rand()函数 theta = tf.Variable(tf.random_uniform([n + 1, 1], -1.0, 1.0), name='theta') y_pred = tf.matmul(X, theta, name="predictions") error = y_pred - y mse = tf.reduce_mean(tf.square(error), name="mse") # 梯度的公式:(y_pred - y) * xj # gradients = 2/m * tf.matmul(tf.transpose(X), error) gradients = tf.gradients(mse, [theta])[0] # 赋值函数对于BGD来说就是 theta_new = theta - (learning_rate * gradients) training_op = tf.assign(theta, theta - learning_rate * gradients) init = tf.global_variables_initializer() with tf.Session() as sess: sess.run(init) for epoch in range(n_epochs): if epoch % 100 == 0: print("Epoch", epoch, "MSE = ", mse.eval()) sess.run(training_op) best_theta = theta.eval() print(best_theta)
import tensorflow as tf import numpy as np from sklearn.datasets import fetch_california_housing from sklearn.preprocessing import StandardScaler # TensorFlow为我们去计算梯度,但是同时也给了我们更方便的求解方式 # 它提供给我们与众不同的,有创意的一些优化器,包括梯度下降优化器 # 替换前面代码相应的行,并且一切工作正常 # 设定超参数,Grid Search进行栅格搜索,其实说白了就是排列组合找到Loss Function最小的时刻 # 的那组超参数结果 n_epochs = 1000 learning_rate = 0.01 # 读取数据,这里读取数据是一下子就把所有数据交给X,Y节点,所以下面去做梯度下降的时候 # BGD = Batch Gradient Decrease ,如果面向数据集比较大的时候,我们倾向与 Mini GD housing = fetch_california_housing(data_home="./datasets", download_if_missing=False) m, n = housing.data.shape housing_data_plus_bias = np.c_[np.ones((m, 1)), housing.data] # 可以使用TensorFlow或者Numpy或者sklearn的StandardScaler去进行归一化 scaler = StandardScaler().fit(housing_data_plus_bias) scaled_housing_data_plus_bias = scaler.transform(housing_data_plus_bias) # 下面部分X,Y最后用placeholder可以改成使用Mini BGD # 构建计算的图 X = tf.constant(scaled_housing_data_plus_bias, dtype=tf.float32, name='X') y = tf.constant(housing.target.reshape(-1, 1), dtype=tf.float32, name='y') # random_uniform函数创建图里一个节点包含随机数值,给定它的形状和取值范围,就像numpy里面rand()函数 theta = tf.Variable(tf.random_uniform([n + 1, 1], -1.0, 1.0), name='theta') y_pred = tf.matmul(X, theta, name="predictions") error = y_pred - y mse = tf.reduce_mean(tf.square(error), name="mse") # 梯度的公式:(y_pred - y) * xj # gradients = 2/m * tf.matmul(tf.transpose(X), error) # gradients = tf.gradients(mse, [theta])[0] # 赋值函数对于BGD来说就是 theta_new = theta - (learning_rate * gradients) # training_op = tf.assign(theta, theta - learning_rate * gradients) optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate) # MomentumOptimizer收敛会比梯度下降更快 # optimizer = tf.train.MomentumOptimizer(learning_rate=learning_rate, momentum=0.9) training_op = optimizer.minimize(mse) init = tf.global_variables_initializer() # 下面是开始训练 with tf.Session() as sess: sess.run(init) for epoch in range(n_epochs): if epoch % 100 == 0: print("Epoch", epoch, "MSE = ", mse.eval()) sess.run(training_op) best_theta = theta.eval() print(best_theta) # 最后还要进行模型的测试,防止过拟合
import tensorflow as tf # 让我们修改前面的代码去实现Mini-Batch梯度下降 # 为了去实现这个,我们需要一种方式去取代X和y在每一次迭代中,使用一小批数据 # 最简单的方式去做到这个是去使用placeholder节点 # 这些节点特点是它们不真正的计算,它们只是在执行过程中你要它们输出数据的时候去输出数据 # 它们会传输训练数据给TensorFlow在训练的时候 # 如果在运行过程中你不给它们指定数据,你会得到一个异常 # 需要做的是使用placeholder()并且给输出的tensor指定数据类型,也可以选择指定形状 # 如果你指定None对于某一个维度,它的意思代表任意大小 A = tf.placeholder(tf.float32, shape=(None, 3)) B = A + 5 with tf.Session() as sess: B_val_1 = B.eval(feed_dict={A: [[1, 2, 3]]}) B_val_2 = B.eval(feed_dict={A: [["4", 5, 6], [7, 8, 9]]}) print(B_val_1) print(B_val_2)