python ocr(光學文字識別)學習筆記 (二)

來源:互聯網
上載者:User

標籤:網路   init   python   還需要   調用   erro   使用   文字識別   數列   

參考資料:500 lines or less ocr 其中包括神經網路演算法的簡單介紹,如果看不懂您需要使用Google翻譯呢

在這一節內容中,我們將對實現這個系統的演算法進行分析

設計feedforward ANN(前饋神經網路,也稱bp神經網路)時,我們需要考慮以下因素:

1.啟用函數的選用

啟用函數是結點輸出的決策者。我們這個系統將為每個數字輸出一個介於0到1的值,值越接近1意味著ann預測的是繪製的數字,越接近0意味著它被預測不是繪製的數字。因此我們將輸出接近0或者1的啟用函數。我們還需要一個可微分的函數。這是由於我們的bp神經網路基於萬能逼近定理:對於一個任意閉區間的連續函數,都可以用隱含層的bp網路來逼近。所以一個3層的bp網路可以完成任意m維到n維的映射。在反向傳播計算的時候需要求導所以要求函數是可微的

所以我們可以參看 常用啟用函數列表

最終選擇了Logistic,也就是s型啟用函數了

2. biases(位移因子,又譯成閥值)

使用起到加快收斂的作用。收斂次數可以相當於神經網路進行正確的判斷的訓練次數,用數學方法使得神經網路更“聰明”

3.神經網路隱藏層的數量和隱藏層節點的數量

在多數的情況下,單個隱藏層是足夠的,這裡使用neural_network_design.pyl來對隱藏層節點數量進行測試

這裡匯入的ocr.py的類

"""In order to decide how many hidden nodes the hidden layer should have,split up the data set into training and testing data and create networkswith various hidden node counts (5, 10, 15, ... 45), testing the performancefor each.The best-performing node count is used in the actual system. If multiple countsperform similarly, choose the smallest count for a smaller network with fewer computations."""import numpy as npfrom ocr import OCRNeuralNetworkfrom sklearn.cross_validation import train_test_splitdef test(data_matrix, data_labels, test_indices, nn):    avg_sum = 0    for j in xrange(100):        correct_guess_count = 0        for i in test_indices:            test = data_matrix[i]            prediction = nn.predict(test)            if data_labels[i] == prediction:                correct_guess_count += 1        avg_sum += (correct_guess_count / float(len(test_indices)))    return avg_sum / 100# Load data samples and labels into matrixdata_matrix = np.loadtxt(open(‘data.csv‘, ‘rb‘), delimiter = ‘,‘).tolist()data_labels = np.loadtxt(open(‘dataLabels.csv‘, ‘rb‘)).tolist()# Create training and testing sets.train_indices, test_indices = train_test_split(list(range(5000)))print "PERFORMANCE"print "-----------"# Try various number of hidden nodes and see what performs bestfor i in xrange(5, 50, 5):    nn = OCRNeuralNetwork(i, data_matrix, data_labels, train_indices, False)    performance = str(test(data_matrix, data_labels, test_indices, nn))    print "{i} Hidden Nodes: {val}".format(i=i, val=performance)

 之後是在ocr.py中構建主類,包含反向傳播訓練,網路預測等方法

我們使用反向傳播演算法訓練我們的ANN。它由訓練集中的每個樣本重複的4個主要步驟來更新ANN權重。

1.初始化資料

首先,我們將權重初始化為小(在-1和1之間)隨機值。在我們的例子中,我們將它們初始化為-0.06和0.06之間的值,並將其儲存在矩陣theta1theta2input_layer_bias,和hidden_layer_bias。由於層中的每個節點連結到下一層的每個節點,我們可以建立一個具有m行n列的矩陣,其中n是一層中的節點數,m是相鄰層中的節點數。該矩陣將表示這兩個層之間的連結的所有權重。這裡,theta1具有400列,用於我們的20x20像素輸入和num_hidden_nodes行。同樣,theta2表示隱藏層和輸出層之間的連結。它有num_hidden_nodes列和NUM_DIGITS10)行。其他兩個向量(1行),input_layer_bias和hidden_layer_bias表示位移因子。

2.forward propagation(前向傳播)

 第二步是前向傳播,其本質上是如[什麼是anns]中所描述的那樣從輸入節點開始逐層地計算的節點輸出。這裡,`y0`是我們希望用來訓練ANN的大小為400的數組輸入。我們將theta1乘以`y0`的轉置矩陣,使得我們有兩個大小為(`num_hidden_??nodes×400)*(400×1)`的矩陣,並且具有對於大小為`num_hidden_??nodes`的隱藏層的輸出的結果向量。然後,我們添加位移因子,並應用向量化S形啟用函數得到一個輸出向量`y1`。 `y1`是我們隱藏層的輸出向量。再次重複相同的過程以計算輸出節點的`y2`。 `y2`現在是我們的輸出層向量,其值表示它們的索引是繪製數位可能性。例如,如果有人繪製一個8,如果ANN做出正確的預測,則在第8個索引處的`y2`的值將是最大的。然而,6可能具有比為所繪製的數位1更高的似然性,因為其看起來更類似於8,並且和8也有著更多重疊得像素.`y2`隨著很多用於訓練的繪製的數字,ANN將會變得更準確。

3.back propagation

 第三步是反向傳播,其涉及計算輸出節點處的錯誤,然後在每個中介層返回到輸入。這裡我們首先建立一個期望的輸出向量`actual_vals`,在表示繪製數位值的數位索引為1,否則為0。輸出節點處的誤差向量`output_errors`通過從`actual_vals`中減去實際輸出向量`y2`來計算。對於每個隱藏層之後,我們計算兩個組件。首先,我們有下一層的轉置權重矩陣乘以其輸出誤差。然後我們得到應用於上一層的啟用函數的導數。然後,我們對這兩個分量執行元素級乘法,得到隱藏層的誤差向量。這裡我們稱之為`hidden_??errors`。

4.基於先前計算的誤差得到的權重更新,調整ANN權重。

通過矩陣乘法在每一層更新權重。每層的誤差矩陣乘以前一層的輸出矩陣。然後將該乘積乘以稱為學習速率的標量,並將其加到權重矩陣。學習速率是在0和1之間的值,其影響ANN中的學習的速度和準確性。較大的學習速率值將產生快速學習但不太準確的ANN,而較小的值將產生學習速度較慢但是更準確的ANN。在我們的例子中,我們有一個相對較小的學習率,0.1。因為我們沒有為了使使用者進行訓練或預測請求而立即完成對ANN的訓練的需求,所以這樣的學習率很不錯。這樣我們就可以通過簡單地將學習速率乘以層的誤差向量來更新偏差。

python源碼如下,使用了python的科學計算包建立矩陣,進行矩陣運算。而啟用函數的導數手動求好直接調用

import csvimport matplotlib.pyplot as pltimport matplotlib.cm as cmimport numpy as npfrom numpy import matrixfrom math import powfrom collections import namedtupleimport mathimport randomimport osimport json"""This class does some initial training of a neural network for predicting drawndigits based on a data set in data_matrix and data_labels. It can then be used totrain the network further by calling train() with any array of data or to predictwhat a drawn digit is by calling predict().The weights that define the neural network can be saved to a file, NN_FILE_PATH,to be reloaded upon initilization."""class OCRNeuralNetwork:    LEARNING_RATE = 0.1    WIDTH_IN_PIXELS = 20    NN_FILE_PATH = ‘nn.json‘    def __init__(self, num_hidden_nodes, data_matrix, data_labels, training_indices, use_file=True):        self.sigmoid = np.vectorize(self._sigmoid_scalar)        self.sigmoid_prime = np.vectorize(self._sigmoid_prime_scalar)        self._use_file = use_file        self.data_matrix = data_matrix        self.data_labels = data_labels        if (not os.path.isfile(OCRNeuralNetwork.NN_FILE_PATH) or not use_file):            # Step 1: Initialize weights to small numbers            self.theta1 = self._rand_initialize_weights(400, num_hidden_nodes)            self.theta2 = self._rand_initialize_weights(num_hidden_nodes, 10)            self.input_layer_bias = self._rand_initialize_weights(1, num_hidden_nodes)            self.hidden_layer_bias = self._rand_initialize_weights(1, 10)            # Train using sample data            TrainData = namedtuple(‘TrainData‘, [‘y0‘, ‘label‘])            self.train([TrainData(self.data_matrix[i], int(self.data_labels[i])) for i in training_indices])            self.save()        else:            self._load()    def _rand_initialize_weights(self, size_in, size_out):        return [((x * 0.12) - 0.06) for x in np.random.rand(size_out, size_in)]    # The sigmoid activation function. Operates on scalars.    def _sigmoid_scalar(self, z):        return 1 / (1 + math.e ** -z)    def _sigmoid_prime_scalar(self, z):        return self.sigmoid(z) * (1 - self.sigmoid(z))    def _draw(self, sample):        pixelArray = [sample[j:j+self.WIDTH_IN_PIXELS] for j in xrange(0, len(sample), self.WIDTH_IN_PIXELS)]        plt.imshow(zip(*pixelArray), cmap = cm.Greys_r, interpolation="nearest")        plt.show()    def train(self, training_data_array):        for data in training_data_array:            # Step 2: Forward propagation            y1 = np.dot(np.mat(self.theta1), np.mat(data[‘y0‘]).T)            sum1 =  y1 + np.mat(self.input_layer_bias) # Add the bias            y1 = self.sigmoid(sum1)            y2 = np.dot(np.array(self.theta2), y1)            y2 = np.add(y2, self.hidden_layer_bias) # Add the bias            y2 = self.sigmoid(y2)            # Step 3: Back propagation            actual_vals = [0] * 10 # actual_vals is a python list for easy initialization and is later turned into an np matrix (2 lines down).            actual_vals[data[‘label‘]] = 1            output_errors = np.mat(actual_vals).T - np.mat(y2)            hidden_errors = np.multiply(np.dot(np.mat(self.theta2).T, output_errors), self.sigmoid_prime(sum1))            # Step 4: Update weights            self.theta1 += self.LEARNING_RATE * np.dot(np.mat(hidden_errors), np.mat(data[‘y0‘]))            self.theta2 += self.LEARNING_RATE * np.dot(np.mat(output_errors), np.mat(y1).T)            self.hidden_layer_bias += self.LEARNING_RATE * output_errors            self.input_layer_bias += self.LEARNING_RATE * hidden_errors    def predict(self, test):        y1 = np.dot(np.mat(self.theta1), np.mat(test).T)        y1 =  y1 + np.mat(self.input_layer_bias) # Add the bias        y1 = self.sigmoid(y1)        y2 = np.dot(np.array(self.theta2), y1)        y2 = np.add(y2, self.hidden_layer_bias) # Add the bias        y2 = self.sigmoid(y2)        results = y2.T.tolist()[0]        return results.index(max(results))    def save(self):        if not self._use_file:            return        json_neural_network = {            "theta1":[np_mat.tolist()[0] for np_mat in self.theta1],            "theta2":[np_mat.tolist()[0] for np_mat in self.theta2],            "b1":self.input_layer_bias[0].tolist()[0],            "b2":self.hidden_layer_bias[0].tolist()[0]        };        with open(OCRNeuralNetwork.NN_FILE_PATH,‘w‘) as nnFile:            json.dump(json_neural_network, nnFile)    def _load(self):        if not self._use_file:            return        with open(OCRNeuralNetwork.NN_FILE_PATH) as nnFile:            nn = json.load(nnFile)        self.theta1 = [np.array(li) for li in nn[‘theta1‘]]        self.theta2 = [np.array(li) for li in nn[‘theta2‘]]        self.input_layer_bias = [np.array(nn[‘b1‘][0])]        self.hidden_layer_bias = [np.array(nn[‘b2‘][0])]

之後就是神經網路的測試函數了,用神經網路來預知資料

由於我們只有一層隱藏層我們直接計算0-9每個ann的輸出抓一個最大的值出來就做完拉

(還有一些沒更完會回來挖坑:測試隱藏節點函數錯誤問題,原因是ocr.py中的test的‘y0‘沒有按格式寫的’u‘裡(錯誤原因暫時這麼稱呼吧)

              save,load細節

              矩陣乘法函數及其內部資料變化過程

              至於演算法證明這鍋不背了, orz)

 

python ocr(光學文字識別)學習筆記 (二)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.