python機器學習TensorFlow框架

TensorFlow框架

關注公衆號“輕鬆學編程”瞭解更多。

一、簡介

​ TensorFlow是谷歌基於DistBelief進行研發的第二代人工智能學習系統,其命名來源於本身的運行原理。

​ Tensor(張量)意味着N維數組,Flow(流)意味着基於數據流圖的計算,TensorFlow爲張量從流圖的一端流動到另一端的計算過程。

​ TensorFlow是將複雜的數據結構傳輸至人工智能神經網中進行分析和處理過程的系統

TensorFlow可被用於語音識別圖像識別等多項機器學習和深度學習領域,對2011年開發的深度學習基礎架構DistBelief進行了各方面的改進,它可在小到一部智能手機、大到數千臺數據中心服務器的各種設備上運行。

​ TensorFlow是開源的,任何人都可以用。

​ 網站:http://playground.tensorflow.org

​ 支持CNN(卷積神經網絡)、RNN(循環神經網絡)和LSTM(長短期記憶網絡)算法,是目前在 Image,NLP 最流行的深度神經網絡模型.

二、優點

TensorFlow優點:

  • 基於Python,寫的很快並且具有可讀性。
  • 在CPU或GPU系統上的都可運行。
  • 代碼編譯效率較高。
  • 社區發展的非常迅速並且活躍。
  • 能夠生成顯示網絡拓撲結構和性能的可視化圖。

三、原理

TensorFlow原理:
TensorFlow是用數據流圖(data flow graphs)技術來進行數值計算的。
數據流圖是描述有向圖中的數值計算過程。
有向圖中,節點通常代表數學運算,邊表示節點之間的某種聯繫,它負責傳輸多維數據(Tensors)。
這裏寫圖片描述

四、使用

###1、TensorFlow使用

​ 使用圖(graph)來表示任務
在被稱之爲會話(Session)的上下文(context)中執行圖
使用tensor表示數據
通過變量(Variable)維護狀態f(x) = w*x + b
使用feed和fetch可以爲任意操作(arbitrary operation)賦值或者從其中獲取數據。

2、下載

在管理員模式下cmd窗口中執行:

pip install tensorflow

3、第一個tf程序

導包

# 導包
import tensorflow as tf
import numpy as np
from IPython.display import display

定義常量

# 定義常量
a = tf.constant(np.random.randint(0,100,size=(3,4)))
b = tf.constant(3.14)
s = tf.constant('hello world')
display(a,b,s)
# tensor張量-------> 數據,類比ndarray

這裏寫圖片描述

定義變量

w = tf.Variable(np.random.randint(0,100,size=(2,3)),
               dtype=tf.int8,  #數據類型
               name='w'  #變量命名,可省略
               )
w

這裏寫圖片描述

創建會話

sess = tf.Session()

關閉會話

sess.close()

使用會話運行graph

一般使用with語句來創建會話,這樣就不用手動關閉會話,with語句會自動關閉會話。

with tf.Session() as sess:
    ret = sess.run(fetches=[a,b,s])
    print(ret)

這裏寫圖片描述

with tf.Session() as sess:
    # 如果要使用變量,需要進行初始化
    sess.run(tf.global_variables_initializer())
    print(sess.run(w))

這裏寫圖片描述

4、加減乘除

#加減乘除
a = tf.constant(100,dtype=tf.float16)
b = tf.constant(5,dtype=tf.float16)
#加
c = a + b
d = tf.add(a,b)
#減
e = tf.subtract(a,b)
#乘
f = tf.multiply(a,b)
#除
h = tf.div(a,b)

with tf.Session() as sess:
    print(sess.run([a,b,c,d,e,f,h]))

這裏寫圖片描述

矩陣乘法

a = tf.constant(np.random.randint(0,10,size = (2,3)))

b = tf.constant(np.random.randint(0,10,size = (3,2)))
#矩陣乘法
m = tf.matmul(a,b)
with tf.Session() as sess:
    print(sess.run([a,b]))
    print(sess.run(m))

這裏寫圖片描述

降維加法

a = tf.constant(np.random.randint(0,10,size = (4,5)))
#axis=1,列相加
#比如第一個數26 = 8+5+4+8+1
b = tf.reduce_sum(a,axis = 1)

with tf.Session() as sess:
    print(sess.run(a))
    print('-----------------------------')
    print(sess.run(b))

這裏寫圖片描述

a = tf.constant(np.random.randint(0,10,size = (4,5)))
#axis=0,行相加
#比如第一個數25 = 3+6+8+8
b = tf.reduce_sum(a,axis = 0)

with tf.Session() as sess:
    print(sess.run(a))
    print('-----------------------------')
    print(sess.run(b))

這裏寫圖片描述

5、placeholder佔位符

placeholder:可以先定義矩陣的維度,不必賦初值,在具體的運算時再賦值,定義的變量可以多次賦值。

#佔位符  placeholder
#定義一個[None,None]的矩陣和[3,None]的矩陣
#矩陣行和列可以不具體指定,裏面的元素值也可以不給
a = tf.placeholder(dtype=tf.float32,shape=[None,None])
b = tf.placeholder(dtype=tf.float32,shape=[3,None])
m = tf.matmul(a,b)
with tf.Session() as sess:
    a1 = np.random.randint(0,10,size = (2,3))
    b1 = np.random.randint(0,10,size = (3,1))
    print('a=',a1)
    print('b=',b1)
    print('a和b的矩陣乘法=',
        sess.run(
            m,
            feed_dict={       #給變量賦值
               a:a1,
               b:b1
            }
        )
    )

這裏寫圖片描述
這裏寫圖片描述

五、使用TensorFlow實現線性迴歸

普通線性迴歸

from sklearn.linear_model import LinearRegression
# 原理:最小二乘法
# (f(x) - y)**2.sum()
#導包

import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

#生成訓練數據
X = np.linspace(0,12,40)
y = np.linspace(0,5,40)
#加噪聲
y += np.random.randn(40)*0.5
plt.scatter(X,y)

這裏寫圖片描述

lrg = LinearRegression()
#訓練數據要是二維數組
lrg.fit(X.reshape(-1,1),y)
#斜率
w_ = lrg.coef_
#截距
b_ = lrg.intercept_

#繪製迴歸曲線
plt.scatter(X,y)

x1 = np.linspace(0,12,300)
y1 = w_*x1 + b_
plt.plot(x1,y1,color='green')

這裏寫圖片描述

使用TensorFlow實現

導包

#導包
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

#繪圖時可以顯示中文
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False

獲取數據

#使用tensorflow

#生成訓練數據
X_train = np.linspace(0,12,40)
y_train = np.linspace(0,5,40)
#加噪聲
y_train += np.random.randn(40)*0.5
plt.scatter(X_train,y_train)

這裏寫圖片描述

定義TensorFlow參數:X,Y,W,b

#定義TensorFlow參數:X,Y,W,b
X = tf.placeholder(dtype=tf.float32,shape=[None,1],name='data')
Y = tf.placeholder(dtype=tf.float32,shape=[None,1],name='target')
#定義兩個變量W和b,賦初值
#斜率
W = tf.Variable(np.random.randn(1,1),name='weight',
				dtype=tf.float32)
#截距
b = tf.Variable(np.random.randn(1,1),name='bias',
				dtype=tf.float32)

創建線性模型

#創建線性模型
pred = tf.matmul(X,W) + b

創建均方誤差cost (損失函數)

這裏寫圖片描述

tf.reduce_sum() 降維加法

pred = [[p1],[p2],[p3]……]

Y = [[y1],[y2],[y3],……]

(pred-Y) 相同的位置進行相減

有40個點,除以40求平均值.

cost = tf.reduce_sum(tf.pow(tf.subtract(pred,Y),2))/40

也可以寫成:

cost = tf.reduce_mean(tf.pow(tf.subtract(pred,Y),2))

創建梯度下降優化器optimizer

使用梯度下降方式去找損失函數cost的最小值.

函數的導數就是函數的梯度.

梯度下降的學習率learning_rate=0.01.

optimizer = tf.train.GradientDescentOptimizer(0.01).minimize(cost)

TensorFlow進行初始化,並進行運算

#定義訓練次數
epoches = 1000
with tf.Session() as sess:
    #變量初始化
    sess.run(tf.global_variables_initializer())
    #循環
    for i in range(epoches):
        opt,c = sess.run([optimizer,cost],
        		# 給佔位符設置數據
                        feed_dict={
                            X:X_train.reshape(-1,1),
                            Y:y_train.reshape(-1,1)
                        }
                        )
        #100次循環打印輸出一次
        if (i+1)%100 == 0:
            w_ = sess.run(W)
            b_ = sess.run(b)
            print('訓練次數:%d,損失函數是:%0.4f,斜率是:%0.2f,截距是:%0.2f'%(i,c,w_,b_))
            
    c = sess.run(cost,feed_dict={X:X_train.reshape(-1,1),Y:y_train.reshape(-1,1)})
    w_ = sess.run(W)
    b_ = sess.run(b)
    print('訓練結束,損失函數是:%0.4f,斜率是:%0.2f,截距是:%0.2f'%(c,w_,b_))            

這裏寫圖片描述

隨着訓練次數的增大,損失函數在逐漸減小,得到的斜率和截距繪製出的迴歸曲線就越準確。

繪製迴歸曲線

#繪製圖形
plt.scatter(X_train,y_train)

x1 = np.linspace(0,12,200)
#繪製迴歸線
plt.plot(x1,x1*0.42 + 0.15,color = 'green',label='斜率=%0.2f 截距=%0.2f'%(0.42,0.15))
plt.legend()

這裏寫圖片描述

六、使用TensorFlow實現類邏輯斯蒂迴歸

導包

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

import tensorflow as tf
#導入手寫數字的數據
from tensorflow.examples.tutorials.mnist import input_data

加載數據

加載當前目錄下data文件夾中的4個壓縮文件

t10k-images-idx3-ubyte.gz

t10k-labels-idx1-ubyte.gz

train-images-idx3-ubyte.gz

train-labels-idx1-ubyte.gz

mnist = input_data.read_data_sets('./data/',one_hot=True)
#mnist

這裏寫圖片描述

mnist.train.num_examples

這裏寫圖片描述
mnist中有55000個訓練數據。

#二維化的圖片數據  原始圖像大小28*28
images = mnist.train.images
images.shape

這裏寫圖片描述

images已經是處理過的二維圖片數據,意味着在訓練模型時可以直接使用。

#在其它地方的概率爲0,下標爲7的地方概率爲1
# 所以其代表數字7
mnist.train.labels[0]

這裏寫圖片描述
labels數組中的每一個元素值代表的是概率,哪個下標對應的概率大,這個數組就表示是哪個數字的概率大。

plt.figure(figsize=(1,1))

plt.imshow(images[0].reshape(28,28),cmap = 'gray')

這裏寫圖片描述

softmax()

softmax用於多分類過程中,它將多個神經元的輸出,映射到(0,1)區間內,可以看成概率來理解,從而來進行多分類

假設我們有一個數組,V,Vi表示V中的第i個元素,那麼這個元素的softmax值就是

這裏寫圖片描述

其它元素的計算如下圖:

這裏寫圖片描述

a = tf.constant([3,1,-3],dtype=tf.float32)
#nn:神經網絡的縮寫  neural network
#使用softmax函數把元素值映射成0到1的概率
b = tf.nn.softmax(a)

with tf.Session() as sess:
    print(sess.run(b))
    print(sess.run(b).sum())

這裏寫圖片描述

將原來輸出是3,1,-3通過softmax函數一作用,就映射成爲(0,1)的值,而這些值的累和爲1(滿足概率的性質),那麼我們就可以將它理解成概率,在最後選取輸出結點的時候,我們就可以選取概率最大(也就是值對應最大的)結點,作爲我們的預測目標!

【參考:https://www.cnblogs.com/alexanderkun/p/8098781.html】

定義TensorFlow參數:X,Y,W,b

這裏寫圖片描述

# None 表示任意,表示樣本數量
X = tf.placeholder(dtype=tf.float32,shape=[None,784])
# p目標值,真實分佈
#數字0到9有10個,於是輸出的數組有10列
p = tf.placeholder(dtype=tf.float32,shape=[None,10])

# W代表斜率
#一共有784個特徵,所以矩陣X與W相乘時需要784行,
#輸出的預測值pred有10列,所以W有10列
#[None,784]*[784,10]   -----> [None,10]
#給變量賦初值爲全0的矩陣
W = tf.Variable(np.zeros(shape=(784,10)),dtype=tf.float32)

# 截距 
b = tf.Variable(np.zeros(shape=10),dtype=tf.float32)

創建線性模型

#創建線性模型
pred = tf.matmul(X,W) + b

# 求解出來的pred轉換成softmax 概率了
# q是預測出來,非真實分佈
q = tf.nn.softmax(pred)

由於預測值是概率發佈,所以不能使用均方誤差來求解最小的損失函數,在這裏需要用到交叉熵作爲損失函數。

###使用交叉熵作爲損失函數

信息熵公式:

這裏寫圖片描述

交叉熵公式:

這裏寫圖片描述

交叉熵,其用來衡量在給定的真實分佈下,使用非真實分佈所指定的策略消除系統的不確定性所需要付出的努力的大小

因此,交叉熵越低,這個策略就越好,最低的交叉熵也就是使用了真實分佈所計算出來的信息熵,因爲此時 ,交叉熵 = 信息熵。這也是爲什麼在機器學習中的分類算法中,我們總是最小化交叉熵,因爲交叉熵越低,就證明由算法所產生的策略最接近最優策略,也間接證明我們算法所算出的非真實分佈越接近真實分佈。

【參考:https://www.zhihu.com/question/41252833】

求交叉熵代碼:

#根據公式求交叉熵
# p*log(1/q)
sub_key = tf.multiply(p,tf.log(1/q))

#求和 
#axis=1 把每一列對應數值取出來相加 得到一維數組A
#比如A[0] = 取出每一列的第一個數相加  
sub_sum = tf.reduce_sum(sub_key,axis=1)

#求均值  A數組是每一個樣本的交叉熵,對A求均值
cost = tf.reduce_mean(sub_sum)

# cost = tf.reduce_mean(tf.reduce_sum(tf.multiply(p,tf.log(1/q)),axis = 1))

創建梯度下降優化器optimizer

使用梯度下降方式去找損失函數cost的最小值.

函數的導數就是函數的梯度.

梯度下降的學習率learning_rate=0.01.

#創建梯度下降優化器
optimizer = tf.train.GradientDescentOptimizer(0.01).minimize(cost)

初始化TensorFlow進行運算

# 初始化TensorFlow進行運算

with tf.Session() as sess:
    # 變量初始化
    sess.run(tf.global_variables_initializer())
    
    # 訓練55000次,每次取出100個樣本
    for i in range(100):
        c_ = 0
        for j in range(550):
            # 每次取100個樣本
            X_train,y_train = mnist.train.next_batch(100)
            opt_,c = sess.run([optimizer,cost],
                               feed_dict={
                                  X:X_train,
                                  p:y_train
                               }
                              )
            #對求得損失函數值求和,然後求其均值
            c_ += c
        #求均值
        c_ = c_ / 550
        
        # 每10次循環打印一次
        if (i+1)%10 == 0:
            print('訓練次數: %d,損失函數: %0.4f'%(i,c_))
    
    # 保存模型
    saver = tf.train.Saver()
    #模型命名爲log_estimator
    saver.save(sess,'./model/like_logistic/log_estimator')

這裏寫圖片描述

可以看到隨着訓練次數的增多,損失函數值在減小。

保存模型後,在文件夾下可看到如下文件:

這裏寫圖片描述

計算準確率

with tf.Session() as sess:
    saver = tf.train.Saver()
    saver.restore(sess,'./model/like_logistic/log_estimator')
    #預測
    y_ = sess.run(q,feed_dict={X:mnist.test.images})
    print(y_.shape)
    # 獲取y_中每一行最大的概率
    y_ = tf.argmax(y_,axis=1)
    
    # 獲取真實分佈中每一行最大的概率
    y_test = tf.argmax(mnist.test.labels,axis=1)
    
    #比較預測值和真實值
    e = tf.equal(y_,y_test)
    
    # 類型轉換 True --> 1  False --> 0
    acc = tf.cast(e,dtype=np.float32)
    
    # 求均值
    accuracy = tf.reduce_mean(acc)
    
    print('對10000個測試數據,進行校驗,準確率: %0.4f'%(sess.run(accuracy)))

這裏寫圖片描述

後記

【後記】爲了讓大家能夠輕鬆學編程,我創建了一個公衆號【輕鬆學編程】,裏面有讓你快速學會編程的文章,當然也有一些乾貨提高你的編程水平,也有一些編程項目適合做一些課程設計等課題。

也可加我微信【1257309054】,拉你進羣,大家一起交流學習。
如果文章對您有幫助,請我喝杯咖啡吧!

公衆號

公衆號

讚賞碼

關注我,我們一起成長~~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章