程式結構&&程式設計

Inside_Zhang發表於2015-11-24

程式結構&&程式設計

程式結構&&程式設計(二)

程式結構&&程式設計(三) ——遞迴

程式結構&&程式設計(三)

程式結構&&程式設計(四)

mask

設定掩碼(0/1構成的陣列或者矩陣)的目的是為了實現對原始資料的遮蔽(0)與選擇(1)。

掩碼生成的方式之一可以是:使用二項分佈binomial distribution,

def get_corrupted_input(self, input, corruption_level):
    mask = self.theano_rng.binomial(
            n=1,
            p=1-corruption_level,
            size=input.shape,
            dtype=theano.config.floatX
            )
    return mask*input

workhorse的執行時間

import timeit 
start_time = timeit.default_timer()
for j in xrange(epochs):
    for i in xrange(n_train_batches):
        ...
end_time = timeit.default_timer()

print('Elapsed time %.2fm'%(end_time-start_time)/60.)

封裝

if sys.platform == "win32":
    # On Windows, the best timer is time.clock()
    default_timer = time.clock
else:
    # On most other platforms the best timer is time.time()
    defalut_time = time.time

我們在更外層呼叫timeit.default_timer()函式時,是不必關心具體的作業系統細節的。所以,封裝的目的是為了遮蔽更底層的細節。

找尋序列中的最值

一般流程為:

best_validation_loss = np.inf
for j in range(epochs):
    this_validation_loss = calc()
    if this_validation_loss < best_validation_loss:
        best_validation_loss = this_validation_loss
                # 以最小為最好

更為完整的程式碼如下:

best_validation_loss = np.inf
for j in range(epochs):
    for i in range(n_train_batches):
        iter = j*n_train_batches+i
        if iter % validation_freq == 0:
            validation_losses = 
                    [valid_model(i) for i in range(n_valid_batches)]
            this_validation_loss = np.mean(validation_losses)
            if this_validation_loss < best_validation_loss:
                best_validation_loss = this_validation_loss

我們對上述問題進一步細分,也即再多加一個判斷:

improvment_thresh = 0.95
if this_validation_loss < best_validation_loss:
    if this_validation_loss < best_validation_loss*improvment_thresh:
        # 也即當前迭代改進幅度足夠大,

patience 耐心值

也即是該值以下不予追究,姑妄聽之。該值以上,則要採取另外的動作,也即「我的忍耐是有限度的」。判斷是否到達耐心值,可以使用if判斷,也可採用取模運算。如下程式碼所示:

patience = 10000
validation_freq = min(n_train_batches, patience/2)
for j in range(epochs):
    for minibatch_idx in n_train_batches:
        iter = j*n_train_batches + minibatch_idx
        if iter%100 == 0:
            print 'training @ iter = ', iter
        cost_ij = train_model(minibatch_idx)
        if (iter+1)%validation_freq == 0:
            ...

以兩值中的較小值作為判斷的基準


validation_freq = min(n_train_batches, patience/2)

for j in range(epochs):
    for i in n_train_batches:
        iter = j*n_train_batches+i
        if iter % validation_freq == 0:
            ...

迴圈

考慮如下的雙條件(and的關係)迴圈:

epoch = 0
done_looping = False

while epoch < epochs and (not done_looping):
    epoch += 1
    。。。

兩層迴圈

外層表示epoch,一次epoch,表示對全體樣本進行一次學習或者叫訓練。內層對全體樣本進行分塊mini_batch,內層迴圈表示的對樣本塊的遍歷。

for j in epochs:
    for mini_batch_idx in n_train_index:
        iter = j*n_train_index + mini_batch_idx
                    # iter 以mini_batch為單位
        if iter%100 == 0:
            print 'training @ iter = ', iter

在迭代的不同階段輸出不同的資訊

for j in xrange(epochs):    
    for i in xrange(n_train_batches):
        iter = j*n_train_batches+i

        if iter % 100 == 0:
            print 'training @ iter = ', iter
        if (iter+1) % validation_freq == 0:
            print 'epoch {}, minibatch {}/{}'.format(j, i+1, n_train_batches)

python 中的for與while

當表達雙條件限制時,可能while會比for更方便點:

# 單條件限制
for j in range(epochs):

epoch = 0
while j < epochs:
    j += 1


# 雙條件限制時
j = 0
done_looping = False
while j < epochs and not done_looping:

python程式的測試

def main():
    pass
if __name__ == '__main__':
    main()

epochs

在進行每次的epoch時,我們需要記錄執行完當前epoch時的一些中間結果(如使用list容器,training\_cost, training\_accuracy=[], []),便於最後的過程視覺化,如全域性代價函式隨epoch次數的變化情況,以及分類精確率隨epochs次數的變化情況,順便地此時也需要定義相關的calc_cost以及calc_accuracy,在程式執行的過程中,我們也可以在控制檯列印相關的資訊,print('Epoch {}: cost: {}, accuracy: {}'.format(j, cost, accuracy))

training_cost, training_accuracy = [], []
for j in range(epochs):
    cost = calc_cost()
    accuracy = calc_accuracy()
    training_cost.append(cost)
    training_accuracy.append(accuracy)
    print('Epoch {}: cost: {}, accuracy: {}'.format(j, cost, accuracy))

統計分類正確出現的次數

sum(int(y_pred == y_test) for y_pred, y_test in zip(predications, test_label))

實現資料集的分塊

n = X.shape[0]
batches = [X[k:k+batch_size, :] for k in range(0, n, batch_size)]

在SGD(stochastic gradient descent)的學習演算法中,常常在分塊之前需要將資料集shuffle的過程:

n = X.shape[0]

記錄某單詞,某元素出現的次數,天然的使用字典或者map作為容器

// C++, map
std::map<std::string, size_t> words;
std::ifstream ifs(filename);
std::string word;
while(ifs >> word)
{
    ++words[word];
}
# python, defaultdict
from collections import defaultdict
densities = defaultdict(float)
digit_counts = defaultdict(int)
for image, digit in zip(training_data[0], training_data[1]):
    digit_counts[digit] += 1
    densities[digit] = sum(image)

實現一種自更新

a=σ(wa+b)
a=\sigma(w\cdot a+b)

這裡w

w
是二維矩陣,而a
a
b
b
是向量,σ()
\sigma(\cdot)
處理一個向量,得到的向量a
a
,又反過來作為程式的輸入,可通過幾乎所有程式設計語言的賦值運算進行實現:

for w, b in zip(weights, biases):
    a = sigma(np.dot(w, a)+b)

設計函式介面時,尤其注意引數是向量還是矩陣

這種對引數向量還是矩陣的考慮,在進行機器學習相關演算法的程式設計實踐中,是需要注意的一個問題。這本身又跟python(numpy)對陣列(一維還是二維)的處理方式不太一致有關。

相關文章