<jupyter_start><jupyter_text>Solution2：房價預測模型       Run in Google Colab        View source on GitHub    Import必要套件<jupyter_code>import os
import numpy as np
import pandas as pd
import tensorflow as tf
import matplotlib.pyplot as plt

from tensorflow import keras
from tensorflow.keras import layers<jupyter_output><empty_output><jupyter_text>數據讀取並分析<jupyter_code>data = pd.read_csv("kc_house_data.csv")
# 顯示dataset的形狀，共21613比資料，每一比資料有21種不同資訊。
data.shape
# 將顯示列數設定為25，不然會有部份資料無法顯示
pd.options.display.max_columns = 25
# head 會顯示前五行的數據
data.head()<jupyter_output><empty_output><jupyter_text>各個數據的簡寫分別代表下面意思：- date：房屋出售日期。- price：房屋價格（目標）。- bedrooms：臥室數量。- bathrooms：浴室數量。- sqft_living：居住的坪數（平方英尺）。- sqft_lot：實際的坪數（平方英尺）。- floors：房屋總共樓層。- waterfront：海景房。- view：房屋是否看過。- condition：整體條件有多好。- grade：房屋的整體等級（根據King County評分系統）。- sqft_above：除了地下室外的坪數（平方英尺）。- sqft_basement：地下室的坪數（平方英尺）。- yr_built：房屋建造時間。- yr_renovated：何時重新裝修過（一些沒重新裝修過或是裝修紀錄沒被記錄到的數值都為0）。- zipcode：郵政編碼。- lat：緯度座標。- long：經度座標。- sqft_living15：2015年紀錄的居住坪數（可能是翻新的原因導致sqft_living15與sqft_living不同）。- sqft_lot15：2015年紀錄的實際坪數（可能是翻新的原因導致sqft_lot15與sqft_lot不同）。  檢查資料的型態資料型態總共有五種：object(string),booleab, integer, float and categorical.<jupyter_code>data.dtypes<jupyter_output><empty_output><jupyter_text>數據前處理轉換資料型態：因為數據集裡的date數據是字串（string）格式，而模型的輸入只接受數值格式，所以可以透過以下程式碼將其轉為數值，並分成年、月及日三種數據。<jupyter_code># 將date日期拆為年、月和日並轉成數值
data['year'] = pd.to_numeric(data['date'].str.slice(0, 4))
data['month'] = pd.to_numeric(data['date'].str.slice(4, 6))
data['day'] = pd.to_numeric(data['date'].str.slice(6, 8))

# 刪除沒有用的數據，inplace則是將更新後的資料存回原本的地方
data.drop(['id'], axis="columns", inplace=True)
data.drop(['date'], axis="columns", inplace=True)

data.head()<jupyter_output><empty_output><jupyter_text>分割數據集（Dataset）：將數據集切割成三個部份，訓練數據（Training data）、驗證數據（Validation data）和測試數據（Testing data）。<jupyter_code>data_num = data.shape[0]
# 取得一筆與data數量相同的亂數索引，主要目的是用於打散資料
indexes = np.random.permutation(data_num)
# 並將亂數索引值分為Train、validation和test分為，這裡的劃分比例為6:2:2
train_indexes = indexes[:int(data_num *0.6)]
val_indexes = indexes[int(data_num *0.6):int(data_num *0.8)]
test_indexes = indexes[int(data_num *0.8):]
# 透過索引值從data取出訓練資料、驗證資料和測試資料
train_data = data.loc[train_indexes]
val_data = data.loc[val_indexes]
test_data = data.loc[test_indexes]<jupyter_output><empty_output><jupyter_text>Normalization 正規化 使用標準分數(Standard Score, 又稱z-score)將數據正規化，經過z-score正規化後數據的都會聚集在0附近， 標準差為1。 (x - 平均值) / 標準差<jupyter_code>train_validation_data = pd.concat([train_data, val_data])
mean = train_validation_data.mean()
std = train_validation_data.std()

train_data = (train_data - mean) / std
val_data = (val_data - mean) / std<jupyter_output><empty_output><jupyter_text>建立Numpy array格式的訓練數據<jupyter_code>x_train = np.array(train_data.drop('price', axis='columns'))
y_train = np.array(train_data['price'])
x_val = np.array(val_data.drop('price', axis='columns'))
y_val = np.array(val_data['price'])<jupyter_output><empty_output><jupyter_text>整理過後的資料共12967筆，且一筆資料有21種資訊(所以網路輸入必須為21)。<jupyter_code>x_train.shape<jupyter_output><empty_output><jupyter_text>建立並訓練網路模型這裡建構三層全連接層的網路架構，並且使用ReLU作為隱藏層的激活函數，而由於需得到線性輸出，故輸出層不使用任何激活函數。提示: https://www.tensorflow.org/api_docs/python/tf/keras/layers?hl=zh-cn<jupyter_code># 建立一個Sequential型態的model
model = keras.Sequential(name='model-1')
# 第1層全連接層設為128個unit，kernel_regularizer=l1，將輸入形狀設定為(21, )
model.add(layers.Dense(128, 
                       kernel_regularizer=keras.regularizers.l1(0.001), 
                       input_shape=(21,)))
# 第3層激活層(activation layer)為LeakyReLU
model.add(layers.LeakyReLU())
# 第4層Dropout層，捨棄比率設定為20%
model.add(layers.Dropout(0.2))
# 第5層全連接層設為128個unit，kernel_regularizer=l1
model.add(layers.Dense(128, 
                       kernel_regularizer=keras.regularizers.l1(0.001)))
# 第6層激活層(activation layer)為LeakyReLU
model.add(layers.LeakyReLU())
# 第7層Dropout層，捨棄比率設定為20%
model.add(layers.Dropout(0.2))
# 最後一層全連接層設為1個unit
model.add(layers.Dense(1))
# 顯示網路模型架構
model.summary()<jupyter_output>Model: "model-1"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 128)               2816      
_________________________________________________________________
leaky_re_lu (LeakyReLU)      (None, 128)               0         
_________________________________________________________________
dropout (Dropout)            (None, 128)               0         
_________________________________________________________________
dense_1 (Dense)              (None, 128)               16512     
_________________________________________________________________
leaky_re_lu_1 (LeakyReLU)    (None, 128)               0         
_________________________________________________________________
dropout_1 (Dropout)          (None, 128)               0         
___________________________________________________________[...]<jupyter_text>設定訓練使用的優化器、損失函數和指標函數：<jupyter_code>model.compile(
    # optimizers使用Adam(0.002)
    optimizer=keras.optimizers.Adam(0.002),
    # loss使用MAE Loss
    loss=keras.losses.MeanSquaredError()
)<jupyter_output><empty_output><jupyter_text>創建模型儲存目錄：<jupyter_code>model_dir = 'lab2-logs/models/'
if not os.path.isdir(model_dir):
    os.makedirs(model_dir)<jupyter_output><empty_output><jupyter_text>設定回調函數：<jupyter_code># TensorBoard回調函數會幫忙紀錄訓練資訊，並存成TensorBoard的紀錄檔
log_dir = os.path.join('lab2-logs', 'model-1')
model_cbk = keras.callbacks.TensorBoard(log_dir=log_dir)
# ModelCheckpoint回調函數幫忙儲存網路模型，可以設定只儲存最好的模型，「monitor」表示被監測的數據，「mode」min則代表監測數據越小越好。
model_mckp = keras.callbacks.ModelCheckpoint(model_dir + '/Best-model-1.h5', 
                                        monitor='val_mean_absolute_error', 
                                        save_best_only=True, 
                                        mode='min')<jupyter_output><empty_output><jupyter_text>訓練網路模型：<jupyter_code>history = model.fit(x_train, y_train,  # 傳入訓練數據
               batch_size=64,  # 批次大小設為64
               epochs=100,  # 整個dataset訓練50遍
               validation_data=(x_val, y_val),  # 驗證數據
               callbacks=[model_cbk, model_mckp])  # Tensorboard回調函數紀錄訓練過程，ModelCheckpoint回調函數儲存最好的模型<jupyter_output>Epoch 1/100
201/203 [============================>.] - ETA: 0s - loss: 1.4957WARNING:tensorflow:Can save best model only with val_mean_absolute_error available, skipping.
203/203 [==============================] - 1s 4ms/step - loss: 1.4956 - val_loss: 1.0154
Epoch 2/100
202/203 [============================>.] - ETA: 0s - loss: 0.8643WARNING:tensorflow:Can save best model only with val_mean_absolute_error available, skipping.
203/203 [==============================] - 0s 2ms/step - loss: 0.8638 - val_loss: 0.6618
Epoch 3/100
164/203 [=======================>......] - ETA: 0s - loss: 0.5936WARNING:tensorflow:Can save best model only with val_mean_absolute_error available, skipping.
203/203 [==============================] - 0s 2ms/step - loss: 0.5800 - val_loss: 0.4798
Epoch 4/100
165/203 [=======================>......] - ETA: 0s - loss: 0.4376WARNING:tensorflow:Can save best model only with val_mean_absolute_error available, skipping.
203/203 [==============================] - 0s 2ms[...]<jupyter_text>訓練結果<jupyter_code>history.history.keys()  # 查看history儲存的資訊有哪些
plt.plot(history.history['loss'], label='train')
plt.plot(history.history['val_loss'], label='validation')
plt.title('Mean square error')
plt.ylabel('loss')
plt.xlabel('epochs')
plt.legend(loc='upper right')<jupyter_output><empty_output><jupyter_text>測試數據的誤差百分比：用測試數據預測房屋價格並與答案計算誤差百分比。<jupyter_code># 載入模型
model = keras.models.load_model('lab2-logs/models/Best-model-1.h5')
# 先將房屋價格取出
y_test = np.array(test_data['price'])
# 標準化數據
test_data = (test_data - mean) / std
# 將輸入數據存成Numpy 格式
x_test = np.array(test_data.drop('price', axis='columns'))
# 預測測試數據
y_pred = model.predict(x_test)
# 將預測結果轉換回來(因為訓練時的訓練目標也有經過標準化)
y_pred = np.reshape(y_pred * std['price'] + mean['price'], y_test.shape)
# 計算平均的誤差百分比
percentage_error = np.mean(np.abs(y_test - y_pred)) / np.mean(y_test) * 100
# 顯示誤差百分比
print("Model Percentage Error: {:.2f}%".format(percentage_error))<jupyter_output>Model Percentage Error: 15.74%
{'fraction_non_alphanumeric': 0.15726931005214018, 'fraction_numerical': 0.03601309567115315, 'mean_word_length': 5.608974358974359, 'pattern_counts': {'":': 0, '<': 58, '<?xml version=': 0, '>': 62, 'https://': 1, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '15', 'dir': 'jupyter-structured-clean-dedup', 'id': '598670', 'license': 'MIT', 'n_tokens_mistral': 3990, 'n_tokens_neox': 4053, 'n_words': 378, 'path': 'Exercise/Solution2.ipynb', 'repo_name': 'yychuang/MMSLAB-TF2', 'size': '8247'}