1. 程式人生 > >tensorflow初級訓練

tensorflow初級訓練

本文是來自Google機器學習

資料基於加利福尼亞州 1990 年的人口普查資料。 

  • 在 TensorFlow 中使用 LinearRegressor 類並基於單個輸入特徵預測各城市街區的房屋價值中位數
  • 使用均方根誤差 (RMSE) 評估模型預測的準確率 
  • 通過調整模型的超引數提高模型準確率
from __future__ import print_function
import math
from IPython import display
from matplotlib import cm
from matplotlib import gridspec
from matplotlib import  pyplot as plt
import numpy as np
import pandas as pd
from sklearn import metrics
import  tensorflow as tf
from tensorflow.python.data import Dataset
#進行初始化
tf.logging.set_verbosity(tf.logging.ERROR)
pd.options.display.max_rows=10
pd.options.display.float_format='{:.lf}'.format
#pandas從特定網址載入資料集
california_housing_dataframe=pd.read_csv("https://download.mlcc.google.cn/mledu-datasets/california_housing_train.csv", sep=",")
#對資料集進行隨機化處理
california_housing_dataframe = california_housing_dataframe.reindex(
    np.random.permutation(california_housing_dataframe.index))
#將房價進行以千為單位的處理
california_housing_dataframe["median_house_value"] /= 1000.0
#檢視資訊
# print(california_housing_dataframe.describe())
#-------------step1:定義特徵並配置特徵-------#
#提取total_rooms這一列
my_feature=california_housing_dataframe[["total_rooms"]]
#定義一個特徵列,特徵列僅儲存對特徵資料的描述,但不包含特徵資料本身
feature_columns=[tf.feature_column.numeric_column("total_rooms")]
#-------------step2:定義目標---------------#
#定義目標:房價
targets=california_housing_dataframe["median_house_value"]
#-------------step3:配置線性模型-----------#
#GradientDescentOptimizer進行小批量隨機梯度下降法(SGD)訓練該模型
#learing_rate引數可控制梯度步長的大小
my_optimizer=tf.train.GradientDescentOptimizer(learning_rate=0.0000001)
#將梯度裁剪應用到優化器,梯度裁剪可確保梯度大小在訓練期間不會變得過大,過大會導致梯度下降失敗
my_optimizer=tf.contrib.estimator.clip_gradients_by_norm(my_optimizer,5.0)
#根據定義好的feature_columns和my_optimizer來配置線性迴歸模型
linear_regressor=tf.estimator.LinearRegressor(feature_columns=feature_columns,
                                              optimizer=my_optimizer)
#---------------step4:定義輸入函式------------#
#要將加利福尼亞州住房資料匯入 LinearRegressor,我們需要定義一個輸入函式
# 讓它告訴 TensorFlow 如何對資料進行預處理,以及在模型訓練期間如何批處理、隨機處理和重複資料。
#首先,我們將 Pandas 特徵資料轉換成 NumPy 陣列字典。
# 然後,我們可以使用 TensorFlow Dataset API 根據我們的資料構建 Dataset 物件
# 並將資料拆分成大小為 batch_size 的多批資料,以按照指定週期數 (num_epochs) 進行重複。
#注意:如果將預設值 num_epochs=None 傳遞到 repeat(),輸入資料會無限期重複。
#然後,如果 shuffle 設定為 True,則我們會對資料進行隨機處理,以便資料在訓練期間以隨機方式傳遞到模型。
# buffer_size 引數會指定 shuffle 將從中隨機抽樣的資料集的大小。
#最後,輸入函式會為該資料集構建一個迭代器,並向 LinearRegressor 返回下一批資料。
def my_input_fn(features,target,batch_size=1,shuffle=True,num_epochs=None):
    features={key:np.array(value) for key,value in dict(features).items()}
    ds=Dataset.from_tensor_slices((features,targets))
    ds=ds.batch(batch_size).repeat(num_epochs)
    if shuffle:
        ds=ds.shuffle(buffer_size=10000)
    #返回下一批資料
    #Dataset.make_one_shot_iterator()一次訪問資料集中的一個元素
    features,labels=ds.make_one_shot_iterator().get_next()
    return features,labels

#-----------------step5:訓練模型--------------#
_=linear_regressor.train(input_fn=lambda:my_input_fn(my_feature,targets),steps=100)
#-----------------step6:評估模型--------------#
prediction_input_fn=lambda:my_input_fn(my_feature,targets,num_epochs=1,shuffle=True)
predictions=linear_regressor.predict(input_fn=prediction_input_fn)
#將predictions格式化為numpy的array
predictions=np.array([item['predictions'][0] for item in predictions])
#計算均方誤差(MSE)
mean_squared_error=metrics.mean_squared_error(predictions,targets)
#由於均方誤差很難解讀,因此我們經常使用的是均方根誤差(RMSE),它與原目標同規模
root_mean_squared_error=math.sqrt(mean_squared_error)
print("Mean Squared Error (on training data): %0.3f" % mean_squared_error)
print("Root Mean Squared Error (on training data): %0.3f" % root_mean_squared_error)

#-------來比較一下 RMSE 與目標最大值和最小值的差值:
min_house_value = california_housing_dataframe["median_house_value"].min()
max_house_value = california_housing_dataframe["median_house_value"].max()
min_max_difference = max_house_value - min_house_value
print("Min. Median House Value: %0.3f" % min_house_value)
print("Max. Median House Value: %0.3f" % max_house_value)
print("Difference between Min. and Max.: %0.3f" % min_max_difference)
print("Root Mean Squared Error: %0.3f" % root_mean_squared_error)
#--------------------------------#

#下面開始繪圖,隨機挑選一些樣本
sample=california_housing_dataframe.sample(n=300)
x_0=sample["total_rooms"].min()
x_1=sample["total_rooms"].max()
##從訓練好的線性迴歸模型中得到的weights與bias
weight=linear_regressor.get_variable_value('linear/linear_model/total_rooms/weights')[0]
bias = linear_regressor.get_variable_value('linear/linear_model/bias_weights')
y_0=weight*x_0+bias
y_1=weight*x_1+bias
#繪製一條直線,這就是訓練好的線性迴歸模型
plt.plot([x_0,x_1],[y_0,y_1],c='r')
plt.ylabel("median_house_value")
plt.xlabel("total_rooms")
#繪製一些樣本中的散點作為對照
plt.scatter(sample["total_rooms"],sample["median_house_value"])
plt.show()


#將上述所有程式碼放到一個函式中
def train_model(learning_rate, steps, batch_size, input_feature="total_rooms"):
    """Trains a linear regression model of one feature.

    Args:
      learning_rate: A `float`, the learning rate.
      steps: A non-zero `int`, the total number of training steps. A training step
        consists of a forward and backward pass using a single batch.
      batch_size: A non-zero `int`, the batch size.
      input_feature: A `string` specifying a column from `california_housing_dataframe`
        to use as input feature.
    """

    periods = 10
    steps_per_period = steps / periods

    my_feature = input_feature
    my_feature_data = california_housing_dataframe[[my_feature]]
    my_label = "median_house_value"
    targets = california_housing_dataframe[my_label]

    # Create feature columns.
    feature_columns = [tf.feature_column.numeric_column(my_feature)]

    # Create input functions.
    training_input_fn = lambda: my_input_fn(my_feature_data, targets, batch_size=batch_size)
    prediction_input_fn = lambda: my_input_fn(my_feature_data, targets, num_epochs=1, shuffle=False)

    # Create a linear regressor object.
    my_optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate)
    my_optimizer = tf.contrib.estimator.clip_gradients_by_norm(my_optimizer, 5.0)
    linear_regressor = tf.estimator.LinearRegressor(
        feature_columns=feature_columns,
        optimizer=my_optimizer
    )

    # Set up to plot the state of our model's line each period.
    plt.figure(figsize=(15, 6))
    plt.subplot(1, 2, 1)
    plt.title("Learned Line by Period")
    plt.ylabel(my_label)
    plt.xlabel(my_feature)
    sample = california_housing_dataframe.sample(n=300)
    plt.scatter(sample[my_feature], sample[my_label])
    colors = [cm.coolwarm(x) for x in np.linspace(-1, 1, periods)]

    # Train the model, but do so inside a loop so that we can periodically assess
    # loss metrics.
    print("Training model...")
    print("RMSE (on training data):")
    root_mean_squared_errors = []
    for period in range(0, periods):
        # Train the model, starting from the prior state.
        linear_regressor.train(
            input_fn=training_input_fn,
            steps=steps_per_period
        )
        # Take a break and compute predictions.
        predictions = linear_regressor.predict(input_fn=prediction_input_fn)
        predictions = np.array([item['predictions'][0] for item in predictions])

        # Compute loss.
        root_mean_squared_error = math.sqrt(
            metrics.mean_squared_error(predictions, targets))
        # Occasionally print the current loss.
        print("  period %02d : %0.2f" % (period, root_mean_squared_error))
        # Add the loss metrics from this period to our list.
        root_mean_squared_errors.append(root_mean_squared_error)
        # Finally, track the weights and biases over time.
        # Apply some math to ensure that the data and line are plotted neatly.
        y_extents = np.array([0, sample[my_label].max()])

        weight = linear_regressor.get_variable_value('linear/linear_model/%s/weights' % input_feature)[0]
        bias = linear_regressor.get_variable_value('linear/linear_model/bias_weights')

        x_extents = (y_extents - bias) / weight
        x_extents = np.maximum(np.minimum(x_extents,
                                          sample[my_feature].max()),
                               sample[my_feature].min())
        y_extents = weight * x_extents + bias
        plt.plot(x_extents, y_extents, color=colors[period])
    print("Model training finished.")

    # Output a graph of loss metrics over periods.
    plt.subplot(1, 2, 2)
    plt.ylabel('RMSE')
    plt.xlabel('Periods')
    plt.title("Root Mean Squared Error vs. Periods")
    plt.tight_layout()
    plt.plot(root_mean_squared_errors)

    # Output a table with calibration data.
    calibration_data = pd.DataFrame()
    calibration_data["predictions"] = pd.Series(predictions)
    calibration_data["targets"] = pd.Series(targets)
    display.display(calibration_data.describe())
    print("Final RMSE (on training data): %0.2f" % root_mean_squared_error)
train_model(
    learning_rate=0.00002,
    steps=500,
    batch_size=5
)

#即便如此,我們仍在下面列出了幾條可為您提供指導的經驗法則:
# 訓練誤差應該穩步減小,剛開始是急劇減小,最終應隨著訓練收斂達到平穩狀態。
# 如果訓練尚未收斂,嘗試執行更長的時間。
# 如果訓練誤差減小速度過慢,則提高學習速率也許有助於加快其減小速度。
# 但有時如果學習速率過高,訓練誤差的減小速度反而會變慢。
# 如果訓練誤差變化很大,嘗試降低學習速率。
# 較低的學習速率和較大的步數/較大的批量大小通常是不錯的組合。
# 批量大小過小也會導致不穩定情況。不妨先嚐試 100 或 1000 等較大的值,然後逐漸減小值的大小,直到出現效能降低的情況。
# 重申一下,切勿嚴格遵循這些經驗法則,因為效果取決於資料。請始終進行試驗和驗證。