rt 我會第一時間回復的!
uj5u.com熱心網友回復:
minst深度學習程式不收斂
是關于tensorflow的問題。我是tensorflow的初學者。從書上抄了minst的學習程式。但是運行之后,無論學習了多少批次,成功率基本不變。
我做了許多嘗試,去掉了正則化,去掉了滑動平均,還是不行。把batch_size改成了2,觀察變數運算情況,輸入x是正確的,但神經網路的輸出y很多情況下在x不一樣的情況下y的兩個結果是完全一樣的。進而softmax的結果也是一樣的。百思不得其解,找不到造成這種情況的原因。這里把代碼和運行情況都貼出來,請大神幫我找找原因。大過年的,祝大家春節快樂萬事如意。
import struct
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button
import tensorflow as tf
import time
#把MNIST的操作封裝在一個類中,以后用起來方便。
class MyMinst():
def decode_idx3_ubyte(self,idx3_ubyte_file):
with open(idx3_ubyte_file, 'rb') as f:
print('決議檔案:', idx3_ubyte_file)
fb_data = f.read()
offset = 0
fmt_header = '>iiii' # 以大端法讀取4個 unsinged int32
magic_number, num_images, num_rows, num_cols = struct.unpack_from(fmt_header, fb_data, offset)
print('idex3 魔數:{},圖片數:{}'.format(magic_number, num_images))
offset += struct.calcsize(fmt_header)
fmt_image = '>' + str(num_rows * num_cols) + 'B'
images = np.empty((num_images, num_rows*num_cols)) #做了修改
for i in range(num_images):
im = struct.unpack_from(fmt_image, fb_data, offset)
images[i] = np.array(im)#這里用一維陣串列示圖片,np.array(im).reshape((num_rows, num_cols))
offset += struct.calcsize(fmt_image)
return images
def decode_idx1_ubyte(self,idx1_ubyte_file):
with open(idx1_ubyte_file, 'rb') as f:
print('決議檔案:', idx1_ubyte_file)
fb_data = f.read()
offset = 0
fmt_header = '>ii' # 以大端法讀取兩個 unsinged int32
magic_number, label_num = struct.unpack_from(fmt_header, fb_data, offset)
print('idex1 魔數:{},標簽數:{}'.format(magic_number, label_num))
offset += struct.calcsize(fmt_header)
labels = np.empty(shape=[0,10],dtype=float) #神經網路需要把label變成10位float的陣列
fmt_label = '>B' # 每次讀取一個 byte
for i in range(label_num):
n=struct.unpack_from(fmt_label, fb_data, offset)
labels=np.append(labels,[[0,0,0,0,0,0,0,0,0,0]],axis=0)
labels[i][n]=1
offset += struct.calcsize(fmt_label)
return labels
def __init__(self):
#固定的訓練檔案位置
self.img=self.decode_idx3_ubyte("/home/zhangyl/Downloads/mnist/train-images.idx3-ubyte")
self.result=self.decode_idx1_ubyte("/home/zhangyl/Downloads/mnist/train-labels.idx1-ubyte")
print(self.result[0])
print(self.result[1000])
print(self.result[25000])
#固定的驗證檔案位置
self.validate_img=self.decode_idx3_ubyte("/home/zhangyl/Downloads/mnist/t10k-images.idx3-ubyte")
self.validate_result=self.decode_idx1_ubyte("/home/zhangyl/Downloads/mnist/t10k-labels.idx1-ubyte")
#每一批讀訓練資料的起始位置
self.train_read_addr=0
#每一批讀訓練資料的batchsize
self.train_batchsize=100
#每一批讀驗證資料的起始位置
self.validate_read_addr=0
#每一批讀驗證資料的batchsize
self.validate_batchsize=100
#定義用于回傳batch資料的變數
self.train_img_batch=self.img
self.train_result_batch=self.result
self.validate_img_batch=self.validate_img
self.validate_result_batch=self.validate_result
def get_next_batch_traindata(self):
n=len(self.img) #對引數范圍適當約束
if self.train_read_addr+self.train_batchsize<=n :
self.train_img_batch=self.img[self.train_read_addr:self.train_read_addr+self.train_batchsize]
self.train_result_batch=self.result[self.train_read_addr:self.train_read_addr+self.train_batchsize]
self.train_read_addr+=self.train_batchsize #改變起始位置
if self.train_read_addr==n :
self.train_read_addr=0
else:
self.train_img_batch=self.img[self.train_read_addr:n]
self.train_img_batch.append(self.img[0:self.train_read_addr+self.train_batchsize-n])
self.train_result_batch=self.result[self.train_read_addr:n]
self.train_result_batch.append(self.result[0:self.train_read_addr+self.train_batchsize-n])
self.train_read_addr=self.train_read_addr+self.train_batchsize-n #改變起始位置,這里沒考慮batchsize大于n的情形
return self.train_img_batch,self.train_result_batch #測驗一下用臨時變數回傳是否可行
def set_train_read_addr(self,addr):
self.train_read_addr=addr
def set_train_batchsize(self,batchsize):
self.train_batchsize=batchsize
if batchsize <1 :
self.train_batchsize=1
def set_validate_read_addr(self,addr):
self.validate_read_addr=addr
def set_validate_batchsize(self,batchsize):
self.validate_batchsize=batchsize
if batchsize<1 :
self.validate_batchsize=1
myminst=MyMinst() #minst類的實體
batch_size=2 #設定每一輪訓練的Batch大小
learning_rate=0.8 #初始學習率
learning_rate_decay=0.999 #學習率的衰減
max_steps=300000 #最大訓練步數
#定義存盤訓練輪數的變數,在使用tensorflow訓練神經網路時,
#一般會將代表訓練輪數的變數通過trainable引數設定為不可訓練的
training_step = tf.Variable(0,trainable=False)
#定義得到隱藏層和輸出層的前向傳播計算方式,激活函式使用relu()
def hidden_layer(input_tensor,weights1,biases1,weights2,biases2,layer_name):
layer1=tf.nn.relu(tf.matmul(input_tensor,weights1)+biases1)
return tf.matmul(layer1,weights2)+biases2
x=tf.placeholder(tf.float32,[None,784],name="x-input")
y_=tf.placeholder(tf.float32,[None,10],name="y-output")
#生成隱藏層引數,其中weights包含784*500=39200個引數
weights1=tf.Variable(tf.truncated_normal([784,500],stddev=0.1))
biases1=tf.Variable(tf.constant(0.1,shape=[500]))
#生成輸出層引數,其中weights2包含500*10=5000個引數
weights2=tf.Variable(tf.truncated_normal([500,10],stddev=0.1))
biases2=tf.Variable(tf.constant(0.1,shape=[10]))
#計算經過神經網路前后向傳播后得到的y值
y=hidden_layer(x,weights1,biases1,weights2,biases2,'y')
#初始化一個滑動平均類,衰減率為0.99
#為了使模型在訓練前期可以更新的更快,這里提供了num_updates引數,并設定為當前網路的訓練輪數
#averages_class=tf.train.ExponentialMovingAverage(0.99,training_step)
#定義一個更新變數滑動平均值的操作需要向滑動平均類的apply()函式提供一個引數串列
#train_variables()函式回傳集合圖上Graph.TRAINABLE_VARIABLES中的元素。
#這個集合的元素就是所有沒有指定trainable_variables=False的引數
#averages_op=averages_class.apply(tf.trainable_variables())
#再次計算經過神經網路前向傳播后得到的y值,這里使用了滑動平均,但要牢記滑動平均值只是一個影子變數
#average_y=hidden_layer(x,averages_class.average(weights1),
# averages_class.average(biases1),
# averages_class.average(weights2),
# averages_class.average(biases2),
# 'average_y')
#softmax,計算交叉熵損失,L2正則,隨機梯度優化器,學習率采用指數衰減
#函式原型為sparse_softmax_cross_entropy_with_logits(_sential,labels,logdits,name)
#與softmax_cross_entropy_with_logits()函式的計算方式相同,更適用于每個類別相互獨立且排斥
#的情況,即每一幅圖只能屬于一類
#在1.0.0版本的TensorFlow中,這個函式只能通過命名引數的方式來使用,在這里logits引數是神經網
#絡不包括softmax層的前向傳播結果,lables引數給出了訓練資料的正確答案
softmax=tf.nn.softmax(y)
cross_entropy=tf.nn.sparse_softmax_cross_entropy_with_logits(logits=y+1e-10,labels=tf.argmax(y_,1))
#argmax()函式原型為argmax(input,axis,name,dimension)用于計算每一個樣例的預測答案,其中
# input引數y是一個batch_size*10(batch_size行,10列)的二維陣列。每一行表示一個樣例前向傳
# 播的結果,axis引數“1”表示選取最大值的操作只在第一個維度進行。即只在每一行選取最大值對應的下標
# 于是得到的結果是一個長度為batch_size的一維陣列,這個一維陣列的值就表示了每一個樣例的數字識別
# 結果。
regularizer=tf.contrib.layers.l2_regularizer(0.0001)
#計算L2正則化損失函式
regularization=regularizer(weights1)+regularizer(weights2)
#計算模型的正則化損失
loss=tf.reduce_mean(cross_entropy)#+regularization
#總損失
#用指數衰減法設定學習率,這里staircase引數采用默認的False,即學習率連續衰減
learning_rate=tf.train.exponential_decay(learning_rate,training_step,
batch_size,learning_rate_decay)
#使用GradientDescentOptimizer優化演算法來優化交叉熵損失和正則化損失
train_op=tf.train.GradientDescentOptimizer(learning_rate).minimize(loss,
global_step=training_step)
#在訓練這個模型時,每過一遍資料既需要通過反向傳播來更新神經網路中的引數,又需要
# 更新每一個引數的滑動平均值。control_dependencies()用于這樣的一次性多次操作
#同樣的操作也可以使用下面這行代碼完成:
#train_op=tf.group(train_step,average_op)
#with tf.control_dependencies([train_step,averages_op]):
# train_op=tf.no_op(name="train")
#檢查使用了滑動平均模型的神經網路前向傳播結果是否正確
#equal()函式原型為equal(x,y,name),用于判斷兩個張量的每一維是否相等。
#如果相等回傳True,否則回傳False
crorent_predicition=tf.equal(tf.argmax(y,1),tf.argmax(y_,1))
#cast()函式的原型為cast(x,DstT,name),在這里用于將一個布爾型的資料轉換為float32型別
#之后對得到的float32型資料求平均值,這個平均值就是模型在這一組資料上的正確率
accuracy=tf.reduce_mean(tf.cast(crorent_predicition,tf.float32))
#創建會話和開始訓練程序
with tf.Session() as sess:
#在稍早的版本中一般使用initialize_all_variables()函式初始化全部變數
tf.global_variables_initializer().run()
#準備驗證資料
validate_feed={x:myminst.validate_img,y_:myminst.validate_result}
#準備測驗資料
test_feed= {x:myminst.img,y_:myminst.result}
for i in range(max_steps):
if i%1000==0:
#計算滑動平均模型在驗證資料上的結果
#為了能得到百分數輸出,需要將得到的validate_accuracy擴大100倍
validate_accuracy= sess.run(accuracy,feed_dict=validate_feed)
print("After %d trainning steps,validation accuracy using average model is %g%%" %(i,validate_accuracy*100))
#產生這一輪使用一個batch的訓練資料,并進行訓練
#input_data.read_data_sets()函式生成的類提供了train.next_batch()函式
#通過設定函式的batch_size引數就可以從所有的訓練資料中讀取一個小部分作為一個訓練batch
myminst.set_train_batchsize(batch_size)
xs,ys=myminst.get_next_batch_traindata()
var_print=sess.run([x,y,y_,loss,train_op,softmax,cross_entropy,regularization,weights1],feed_dict={x:xs,y_:ys})
print("after ",i," trainning steps:")
print("x=",var_print[0][0],var_print[0][1],"y=",var_print[1],"y_=",var_print[2],"loss=",var_print[3],
"softmax=",var_print[5],"cross_entropy=",var_print[6],"regularization=",var_print[7],var_print[7])
time.sleep(0.5)
#使用測驗資料集檢驗神經網路訓練之后的正確率
#為了能得到百分數輸出,需要將得到的test_accuracy擴大100倍
test_accuracy=sess.run(accuracy,feed_dict=test_feed)
print("After %d training steps,test accuracy using average model is %g%%"%(max_steps,test_accuracy*100))
下面是運行情況的一部分:
x= [ 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0. 0.
0.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/115178.html
標籤:人工智能技術
