多元線性回歸—波士頓房價預測(版本一)


 

背景:波士頓房價數據集包括506個樣本,每個樣本包括12個特征變量和該地區的平均房價。房價(單價)顯然和多個特征變量相關,不是單變量線性回歸(一元線性回歸)問題;選擇多個特征變量來建立線性方程,這就是多變量線性回歸(多元線性回歸)問題。

房價和多個特征變量相關,本案例嘗試使用多元線性回歸建模  Y=X1*W1+X2*W2+..+X12*W12+b

結果可以由不同特征的輸入值和對應的權重相乘求和,加上偏置項計算求解,多變量線性方程可用矩陣運算表示。

一、數據讀取

CRIM:城鎮人均犯罪率                                                  AGE:1940年之前建成的自用房屋比例

ZN:住宅用地超過25000sq.ft.的比例                             DIS:到波士頓5個中心區域的加權距離

INDUS:城鎮非零售商用土地的比例                              RAD:輻射性公路的靠近指數
CHAS:邊界是河流為1,否則0                                      TAX:每10000美元的全值財產稅率
NOX:一氧化氮濃度                                                        PTRATIO:城鎮師生比例
RM:住宅平均房間數                                                       LSTAT:人口中地位低下者的比例
                            標簽數據       MEDV:自住房的平均房價,單位:干美元

 1.1通過pandas讀取數據文件,列出統計概述(分析用)

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.utils import shuffle     #打亂樣本
df = pd.read_csv("data/boston.csv", header=0)
print(df.describe())   #線束數據摘要描述信息
View Code1

 

pandas是python提供的非常好用的數據分析模塊,但是在使用pandas進行數據分析時,有時候需要查看打印的結果,當dataframe行數或者列數比較多的時候,打印結果總是有一些省略號,不能完整的看到數據的大致分布,比如最大值,最小值,等等,了解數據分布的區間有助於進行可視化和進一步分析。查看pandas的文檔,這個問題可以通過pandas內置的set_option()方法解決,從文檔的屬性設置中可以看到,與顯示的行數列數有關的選項主要是【display】中的【max_columns,max_rows,max_colwidth,line_width】等這幾項,只需要將這幾項屬性值設置得大一些就可以解決。

修改后的程序為:

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.utils import shuffle     #打亂樣本

pd.set_option('display.max_columns',1000)
pd.set_option('display.width',1000)
pd.set_option('display.max_colwidth',1000)

df = pd.read_csv("data/boston.csv", header=0)
print(df.describe())   #線束數據摘要描述信息(數量、平均值、標准值、最大最小值等)
View Code2

 從上到下分別為,每一列的數目、平均值、標准值、最小值、25%位置的值、50%位置的值、75%位置的值、最大值。

1.2載入本例所需數據

df = df.values #獲取df的值
df = np.array(df) #把df轉換為np的數組格式
# print(df)
x_data = df[:,:12] #x_data為前12列特征數據
y_data = df[:,12] #y_data為第12列標簽數據
# print(x_data,'\n shape=',x_data.shape)
# print(y_data,'\n shape=',y_data.shape)

二、模型定義

2.1定義特征數據和標簽數據的占位符

x = tf.placeholder(tf.float32,[None,12],name ="X") #12個特征數據(12列)
y = tf.placeholder(tf.float32,[None,1],name ="Y") #1個標簽數據(1列)

Note:shape中None表示行的數量未知,在實際訓練時決定一次代入多少行樣本,從一個樣本的隨機SDG到批量SDG都可以.

2.2定義模型結構

#定義了一個命名空間,對以下語句的節點打包在一起,使計算圖看上去更簡潔
with tf.name_scope("Model"):
    # w 初始化值為shape=(12,1)的隨機數,標准差為0.01
    w = tf.Variable(tf.random_normal([12,1],stddev=0.01),name="W")
    b = tf.Variable(1.0, name="b")      # b 初始化值為1.0

    def model(x, w, b):    # w 和 b 四矩陣相乘,用matmul,不能用mutiply或者*
        return tf.matmul(x,w) + b
    pred = model(x, w, b)  #預測計算操作,前向計算節點

三、訓練模型

3.1設置訓練參數(超參數)

train_epochs = 50     #迭代次數(訓練輪數)
learning_rate = 0.01   #學習率,設置為經驗值。

3.2定義均方差損失函數

with tf.name_scope("LossFunction"):
loss_function = tf.reduce_mean(tf.pow(y-pred, 2)) #均方誤差

3.3選擇優化器

optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss_function) #創建優化器

Note:常用優化器包括

tf.train.MomentumOptimizer                                      tf.train.AdamOptimizer

tf.train.GradientDescentOptimizer                             tf.train.FtrlOptimizer

tf.train.AdadeltaOptimizer                                         tf.train.ProximalGradientDescentOptimizer

tf.train.AdagradOptimizer                                          tf.train.ProximalAdagradOptimizer

tf.train.AdagradDAOptimizer                                     tf.train.RMSPropOptimizer

3.4聲明並啟動會話

sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)

3.5迭代訓練

 1 for epoch in range (train_epochs):
 2     loss_sum = 0.0
 3     for xs, ys in zip(x_data,y_data): # 每次各取一行數據(一維)
 4         xs = xs.reshape(1,12)         # feed數據必須和placeholder的shape一致
 5         ys = ys.reshape(1,1)
 6         _, loss = sess.run([optimizer,loss_function],feed_dict={x: xs, y: ys})
 7         loss_sum= loss_sum+ loss
 8     xvalues,yvalues = shuffle(x_data,y_data)  #打亂數據順序
 9     bOtemp=b.eval(session=sess)
10     wOtemp=w.eval(session=sess)
11     loss_average =loss_sum/len(y_data)
12     print("epoch=",epoch+1,"loss=",loss_average,"b=",betemp,"w=",wOtemp)

Note:第四行和第五行的解釋,一維變為二維,如把[x1,x2,...x12]變成[[x1,x2,...x12]] 進而滿足之前定義的[None,12]  ; 18 變為[[18]]進而滿足之前定義的[None,1]

以上完整程序,運行后結果為:

 

 可以發現,訓練結果出現了異常!

四、探究訓練結果異常的原因

要考慮不同特征值取值范圍大小的影響,機器學習過程中需要避免特征的絕對值取值范圍大小,造成權值過大的影響,需要進行歸一化

                                                    歸一化[0~1]:特征值 /(特征值max - 特征值min

4.1特征數據歸一化

對1.2節代碼進行修改,其余代碼不變

#對特證數據【0-11】列歸一化
for i in range(12):
    df[:,i]=df[:,i]/(df[:,i].max() - df[:,i].min())

x_data = df[:,:12]  #xdata為歸一化后的前12列特征數據
y_data = df[:,12]  #ydata 為最后1列標簽數據

運行后,取最后一輪訓練結果顯示為:

 

 Note:權重絕對值越大說明該特征值影響越大。

 五、模型應用

模型一般應該用來預測新的樣本的值,本例506條數據都用來訓練了,暫時沒有新的數據。

n=348  #指定一條來看看效果
# n=np.random.randint(506) #隨機確定一條來看看效果
# print(n)
x_test = x_data[n]
x_test = x_test.reshape(1,12)
predict = sess.run(pred, feed_dict={x:x_test})
print("預測值:%f" % predict)
target = y_data[n]
print("標簽值:%f" % target)

 

 完整代碼為:

#Created by:Huang
#Time:2019/10/8 0007.
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.utils import shuffle     #打亂樣本

# pd.set_option('display.max_columns',1000)
# pd.set_option('display.width',1000)
# pd.set_option('display.max_colwidth',1000)

df = pd.read_csv("data/boston.csv", header=0)
# print(df.describe())   #線束數據摘要描述信息(數量、平均值、標准值、最大最小值等)

df = df.values    #獲取df的值
df = np.array(df)   #把df轉換為np的數組格式
# print(df)

#對特證數據【0-11】列歸一化
for i in range(12):
    df[:,i]=df[:,i]/(df[:,i].max() - df[:,i].min())

x_data = df[:,:12]  #xdata為歸一化后的前12列特征數據
y_data = df[:,12]  #ydata 為最后1列標簽數據

# print(x_data,'\n shape=',x_data.shape)
# print(y_data,'\n shape=',y_data.shape)

x = tf.placeholder(tf.float32,[None,12],name ="X")    #12個特征數據(12列)
y = tf.placeholder(tf.float32,[None,1],name ="Y")   #1個標簽數據(1列)

#定義了一個命名空間,對以下語句的節點打包在一起,使計算圖看上去更簡潔
with tf.name_scope("Model"):
    # w 初始化值為shape=(12,1)的隨機數,標准差為0.01
    w = tf.Variable(tf.random_normal([12,1],stddev=0.01),name="W")
    b = tf.Variable(1.0, name="b")      # b 初始化值為1.0

    def model(x, w, b):    # w 和 b 四矩陣相乘,用matmul,不能用mutiply或者*
        return tf.matmul(x,w) + b
    pred = model(x, w, b)  #預測計算操作,前向計算節點

train_epochs = 50    #迭代次數(訓練輪數)
learning_rate = 0.01  #學習率,設置為經驗值。

with tf.name_scope("LossFunction"):
    loss_function = tf.reduce_mean(tf.pow(y-pred,2))  #均方誤差
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss_function) #創建優化器

sess = tf.Session()
init = tf.global_variables_initializer()
sess.run(init)


for epoch in range (train_epochs):
    loss_sum = 0.0
    for xs, ys in zip(x_data,y_data): # 每次各取一行數據(一維)
        xs = xs.reshape(1,12)         # feed數據必須和placeholder的shape一致
        ys = ys.reshape(1,1)
        _, loss = sess.run([optimizer,loss_function],feed_dict={x: xs, y: ys}) #下划線表示只接收但之后並不會去用,返回值對我們沒有用
        loss_sum= loss_sum+ loss
    xvalues,yvalues = shuffle(x_data,y_data)  #每訓練一輪(506個數據),打亂數據順序
    b0temp = b.eval(session=sess)
    wOtemp = w.eval(session=sess)
    loss_average =loss_sum/len(y_data)
    print("epoch=",epoch+1,"loss=",loss_average,"b=",b0temp,"w=",wOtemp)

# n=348  #指定一條來看看效果
n=np.random.randint(506) #隨機確定一條來看看效果
print(n)
x_test = x_data[n]
x_test = x_test.reshape(1,12)
predict = sess.run(pred, feed_dict={x:x_test})
print("預測值:%f" % predict)
target = y_data[n]
print("標簽值:%f" % target)
MLR6.1 Code

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM