Python3機器學習—Tensorflow數字識別實踐


[本文出自天外歸雲的博客園]

Windows下Anaconda+Tensorflow環境部署

1. 安裝Anaconda。

2. 開始菜單 > 所有程序 > Anaconda 3 (64-bit) > Anaconda Prompt > 執行命令:

conda create -n tensorflow python=3.5

至此創建了一個名字叫做tensorflow的虛擬環境,並指定了這個虛擬環境的python為3.5版本。

3. 激活虛擬環境,執行命令:

activate tensorflow

4. 安裝CPU版本的tensorflow,執行命令:

pip install --ignore-installed --upgrade https://storage.googleapis.com/tensorflow/windows/cpu/tensorflow-1.2.1-cp35-cp35m-win_amd64.whl

必須用這個whl結尾的https地址,用其他地址安裝一會兒在python環境中import tensorflow都會報錯。

至此環境部署完成。

使用方法

要運行一個tensorflow機器學習腳本,首先創建一個test.py文件,包含以下內容:

import numpy as np
import tensorflow as tf

# Model parameters
W = tf.Variable([.3], dtype=tf.float32)
b = tf.Variable([-.3], dtype=tf.float32)
# Model input and output
x = tf.placeholder(tf.float32)
linear_model = W * x + b
y = tf.placeholder(tf.float32)
# loss
loss = tf.reduce_sum(tf.square(linear_model - y))  # sum of the squares
# optimizer
optimizer = tf.train.GradientDescentOptimizer(0.01)
train = optimizer.minimize(loss)
# training data
x_train = [1, 2, 3, 4]
y_train = [0, -1, -2, -3]
# training loop
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)  # reset values to wrong
for i in range(1000):
    sess.run(train, {x: x_train, y: y_train})

# evaluate training accuracy
curr_W, curr_b, curr_loss = sess.run([W, b, loss], {x: x_train, y: y_train})
print("W: %s b: %s loss: %s" % (curr_W, curr_b, curr_loss))

然后打開Anaconda Prompt,激活在我們剛才創建的tensorflow虛擬環境,並在其中執行上面的test.py文件,得到下面的運行結果:

這就是tensorflow機器學習腳本在Anaconda Prompt中的使用方法。

數字識別實踐

接下來詳細解釋下官方的HelloWord用例:

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

# 加載數據集,Label(標簽)在one-hot編碼后變成向量,所以在此讀取數據集中的數據時指定了one_hot參數為true
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
# 創建一個tensorflow的交互環境
sess = tf.InteractiveSession()
# [None, 784]是shape,None代表不限條數的輸入,784代表每條輸入都是一個784維的向量
x = tf.placeholder(tf.float32, [None, 784])
# W的shape是[784, 10],784是特征的維數,10是類別數,每個特征都對應有10個類別
W = tf.Variable(tf.zeros([784, 10]))
# b的shape是[10],是個10維向量
b = tf.Variable(tf.zeros([10]))
# 計算公式,其中matmul是tf.nn下面的矩陣乘法函數
y = tf.nn.softmax(tf.matmul(x, W) + b)
# y_是真實的概率分布,即Label的one-hot編碼,shape為[None, 10],None代表樣本數不限,10代表每個樣本對應的概率分布是一個10維向量
y_ = tf.placeholder(tf.float32, [None, 10])
# 損失函數(loss function)coss_entropy,reduce_sum求和,reduce_mean對每個batch數據結果求均值
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
# 優化目標設定為cross_entropy,學習速率為0.5
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
# 運行全局參數初始化器
tf.global_variables_initializer().run()
# 迭代
for i in range(1000):
    # 每次從訓練集中隨機抽取100條樣本構成一個mini-batch,他們的特征和標簽分別存到batch_xs和batch_ys里
    batch_xs, batch_ys = mnist.train.next_batch(100)
    # 調用train_step對mini-batch中的樣本進行訓練
    train_step.run({x: batch_xs, y_: batch_ys})
# tf.equal對預測類別tf.argmax(y, 1)和實際類別tf.argmax(y_, 1)進行比較判斷是否相等,tf.argmax函數從一個tensor中尋找最大值序號
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
# tf.cast()函數的作用是執行tensorflow 中張量數據類型轉換
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
# 調用此方法將執行所有前面的操作,這些操作會生成產生此張量的操作所需的輸入,這里是x和y_,分別是讀取的圖像特征和標簽
print(accuracy.eval({x: mnist.test.images, y_: mnist.test.labels}))

運行結果如下:

至此完成了訓練,並求出了精准度。如果要用我們這次訓練的模型來對數字進行識別,首先要保存本次訓練的模型,然后再在本地讀取數字圖片數據並轉化為模型可以接收的ndarray類型數據,用模型進行訓練。那就要對上面的代碼稍加改動。第一步,訓練並保存模型,修改上面代碼(number_recognition_train.py)如下,添加保存模型的過程:

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
import os

# 加載數據集,Label(標簽)在one-hot編碼后變成向量,所以在此讀取數據集中的數據時指定了one_hot參數為true
mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
# 創建一個tensorflow的交互環境
sess = tf.InteractiveSession()
# [None, 784]是shape,None代表不限條數的輸入,784代表每條輸入都是一個784維的向量
x = tf.placeholder(tf.float32, [None, 784])
# W的shape是[784, 10],784是特征的維數,10是類別數,每個特征都對應有10個類別
W = tf.Variable(tf.zeros([784, 10]))
# b的shape是[10],是個10維向量
b = tf.Variable(tf.zeros([10]))
# 計算公式,其中matmul是tf.nn下面的矩陣乘法函數
y = tf.nn.softmax(tf.matmul(x, W) + b)
# y_是真實的概率分布,即Label的one-hot編碼,shape為[None, 10],None代表樣本數不限,10代表每個樣本對應的概率分布是一個10維向量
y_ = tf.placeholder(tf.float32, [None, 10])
# 損失函數(loss function)coss_entropy,reduce_sum求和,reduce_mean對每個batch數據結果求均值
cross_entropy = tf.reduce_mean(-tf.reduce_sum(y_ * tf.log(y), reduction_indices=[1]))
# 優化目標設定為cross_entropy,學習速率為0.5
train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)
# 運行全局參數初始化器
tf.global_variables_initializer().run()
# 迭代
for i in range(1000):
    # 每次從訓練集中隨機抽取100條樣本構成一個mini-batch,他們的特征和標簽分別存到batch_xs和batch_ys里
    batch_xs, batch_ys = mnist.train.next_batch(100)
    # 調用train_step對mini-batch中的樣本進行訓練
    train_step.run({x: batch_xs, y_: batch_ys})
print("訓練完成!")
# 創建模型保存目錄
model_dir = "models"
model_name = "number_recognition"
if not os.path.exists(model_dir):
    os.mkdir(model_dir)
# 定義模型保存對象
saver = tf.train.Saver()
# 保存模型
saver.save(sess, os.path.join(model_dir, model_name))
print("保存模型成功!")
# tf.equal對預測類別tf.argmax(y, 1)和實際類別tf.argmax(y_, 1)進行比較判斷是否相等,tf.argmax函數從一個tensor中尋找最大值序號
correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
# tf.cast()函數的作用是執行tensorflow 中張量數據類型轉換
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
# 調用此方法將執行所有前面的操作,這些操作會生成產生此張量的操作所需的輸入,這里是x和y_,分別是讀取的圖像特征和標簽
print("精准度:{}".format(accuracy.eval({x: mnist.test.images, y_: mnist.test.labels})))

運行之后,在當前目錄下就會出現一個叫models的文件夾,其下會生成我們的模型文件:

之后再寫一個number_recognition_test.py文件,用我們已經保存到本地的模型對其他圖片內容進行數字識別,內容如下:

#!/usr/bin/env python
# 導入mnist數據庫
from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets("MNIST_data", one_hot=True)
import tensorflow as tf

from PIL import Image
import numpy as np


# 讀取mnist中的數據進行測試
def img_recognition_from_mnist(sess, y):
    # 從mnist中讀取出一個測試圖片
    idx = 0
    img = mnist.test.images[idx]
    print("type:{}".format(type(img)))
    print("img:{}".format(img))
    print(list(img))
    print(len(list(img)))
    # 根據模型計算結果
    ret = sess.run(y, feed_dict={x: img.reshape(1, 784)})
    # 顯示測試結果
    print("預測結果:{} 實際結果:{}".format((ret.argmax()), (mnist.test.labels[idx].argmax())))


# 讀取本地圖片轉化為數據進行測試
def img_recognition_from_custom(image_path, sess, y):
    # 讀取圖片轉成灰度格式
    img = Image.open(image_path).convert('L')
    # resize的過程
    img = img.resize((28, 28))
    # 像素存入一維數組
    arr = [1.0 - float(img.getpixel((j, i))) / 255.0 for i in range(28) for j in range(28)]
    # 轉為ndarray類型並reshape
    np_arr = np.array(arr).reshape(1, 784)
    # 根據模型計算結果
    ret = sess.run(y, feed_dict={x: np_arr})
    # 顯示預測結果
    print("預測結果:{}".format((ret.argmax())))


if __name__ == '__main__':
    # 創建會話
    sess = tf.Session()
    # 定義輸入變量
    x = tf.placeholder(tf.float32, [None, 784])
    # 定義參數
    W = tf.Variable(tf.zeros([784, 10]))
    b = tf.Variable(tf.zeros([10]))
    # 定義模型和激勵函數
    y = tf.nn.softmax(tf.matmul(x, W) + b)
    # 定義模型保存對象
    saver = tf.train.Saver([W, b])
    # 恢復模型
    saver.restore(sess, "models/number_recognition")
    print("恢復模型成功!")

    # img_recognition_from_mnist(sess, y)

    img_path = '7.jpg'
    img_recognition_from_custom(img_path, sess, y)

運行后發現預測結果是3,而實際圖片中的數字是7:

看來這個訓練集並不適合我的圖片,需要自己來搞訓練數據,再做一個訓練集進行專門的訓練。這個之后再說。


免責聲明!

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



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