您的位置:首页 > 其它

第一次使用tensorflow编写程序

2017-12-20 17:31 197 查看
最近一直在学习机器学习,看了一段时间的机器学习理论后,买了一本tensorflow实战的书,开始实战:

tensorflow的基本单位是tensor即张量,就是矩阵,可以是多维的矩阵,具体一些概念不在这里解释

尝试使用tensorflow去解决的第一个问题是给一个数,如果这个数是3的倍数,那它属于第一类,如果是5的倍数属于第二类,最开始的想法是用regression乱train一发,结果坏掉了,不能work

这里是产生数据的代码,每个数字产生对应二进制的表示作为网络的输入,如果%3==0则label为[1 0],如果能%5==0则label为[0 1],如果%15==0则label为[1 1],使用这些数据进行regression

def int2vector(i):
ele=[]
dim = 10
while (dim != 0):
dim = dim - 1
ele.append(i % 2)
i = i // 2
return ele
def getLabel(x):
ele = []
if x % 3 == 0:
ele.append(1)
else:
ele.append(0)
if x % 5 == 0:
ele.append(1)
else:
ele.append(0)
return ele

def getTranData(x,y):
for i in range(10,900):

y.append(getLabel(i))

x.append(int2vector(i))

训练过程:

def train():
data=[]
label=[]
getTranData(data,label)
x = tf.placeholder(tf.float32,[None,10],name='x-input')
y_ = tf.placeholder(tf.float32,[None,2],name='y-output')
weight1 = tf.Variable(tf.random_normal([10,1000],stddev=0.1) )
bias1 = tf.Variable(tf.zeros([1000]))

weight2 = tf.Variable(tf.random_normal([1000, 2], stddev=0.1))
bias2 = tf.Variable(tf.zeros([2]))

hide = tf.nn.relu( tf.matmul( x,weight1 ) + bias1 )
y = tf.matmul(hide,weight2)+bias2

global_step = tf.Variable(0,trainable=False)
learning_rate = tf.train.exponential_decay(0.1,global_step,100,0.96,staircase=False)
loss = tf.reduce_sum( tf.square(y-y_) )
cross_entropy = -tf.reduce_sum(y_ * tf.log(y))
train_step = tf.train.AdamOptimizer( 0.1 ).minimize(loss, global_step=global_step)

with tf.Session() as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)

for i in range(10000):
sess.run(train_step,feed_dict={x:data,y_:label})
if i % 1000 == 0:
print( sess.run( loss,feed_dict={x:data,y_:label} ))
xx =[]
xx.append(int2vector(500))
print(sess.run(global_step))
print( sess.run(y,feed_dict={x:xx}) )
loss函数分别使用square error和cross_entropy强行train了,发现使用500来测试结果都坏掉了,更不用使用test_data来训练了

虽然train坏了,但是作为第一个程序,还是让我对tensorflow的结构有了一定的了解,比如使用tensorflow的tensor结果进行所有的运算包括加减乘除运算时,是不会真的进行运算的,而直接生成的计算图,使用当调用sess.run时才会真的去进行计算,计算图的形式,相当于保存了计算过程,而不是只保存结果,更新参数的时候,就是需要不断的通过计算过程做类似的运算来求结果。

发现建图的时候,虽然感觉自己建的是一个结点一个结点的神经网络图,但是在tensorflow中,都是使用矩阵(tensor)来表示的,tensorflow中的每个变量都有一个属性trainable,如果创建变量的时候这个属性为true,这个变量就会被tensorflow放在一个专门维护需要更新的数据的位置,每次进行train过程的时候,都会更新这些参数,如果置为false的话,在进行模型的更新的时候则不会更新这个参数,所以矩阵中的参与运算的值都是默认tranable=true,而global_step这种只是用来计算当前更新次数的变量其实不需要进行更新。

后来发现这个应该当做一个分类问题处理,最简单的处理方式应该讲该问题作为4个类的问题,[1 0 0 0]表示既不是3的倍数也不是5的倍数,[0 1 0 0]表示是3的倍数且不是5的倍数,[0 0 1 0]表示是5的倍数且不是3的倍数,[0 0 0 1]表示是15的倍数

正确的完整程序:

def int2vector(i):
ele=[]
dim = 10
while (dim != 0):
dim = dim - 1
ele.append(i % 2)
i = i // 2
return ele

def getLabel(x):
if x % 15 == 0:
return [0,0,0,1]
if x % 5 == 0:
return [0,0,1,0]
if x % 3 == 0:
return [0,1,0,0]
return [1,0,0,0]

def getTranData(x,y):
for i in range(10,900):

y.append(getLabel(i))

x.append(int2vector(i))

def train():

data=[]
label=[]
getTranData(data,label)
x = tf.placeholder(tf.float32,[None,10],name='x-input')
y_ = tf.placeholder(tf.float32,[None,4],name='y-output')
weight1 = tf.Variable(tf.random_normal([10,1000],stddev=0.1) )
bias1 = tf.Variable(tf.zeros([1000]))

weight2 = tf.Variable(tf.random_normal([1000, 4], stddev=0.1))
bias2 = tf.Variable(tf.zeros([4]))

hide = tf.nn.relu( tf.matmul( x,weight1 ) + bias1 )
y = tf.matmul(hide,weight2)+bias2

global_step = tf.Variable(0,trainable=False)
learning_rate = tf.train.exponential_decay(0.1,global_step,100,0.96,staircase=False)
loss = tf.reduce_sum( tf.square(y-y_) )
loss2 =tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(logits=y,labels=y_))
cross_entropy = -tf.reduce_sum(y_ * tf.log(y))
train_step = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss2,global_step=global_step)
correct_prediction = tf.equal( tf.argmax(y,1) , tf.argmax(y_,1) )
accuracy = tf.reduce_mean(tf.cast(correct_prediction,tf.float32))
with tf.Session() as sess:
init_op = tf.global_variables_initializer()
sess.run(init_op)

for i in range(10000):
sess.run(train_step,feed_dict={x:data,y_:label})
if i % 1000 == 0:                 #每1000次训练打印一下在training data上的 loss和准确率
print( sess.run( loss2,feed_dict={x:data,y_:label} ))
print(sess.run(accuracy, feed_dict={x: data, y_: label})*100,'%')
print('hide.name = ',hide.name)
xx =[]
xx.append(int2vector(1000))             #使用training data上没有的1000这个数来测试一下准确率
print( sess.run(y,feed_dict={x:xx}) )
saver = tf.train.Saver()
saver.save(sess,"F:/machineLearning/testtensorflow/data.ckpt")     #保存网络结果

if __name__ == "__main__":
train()


上面的程序...在training data上面的准确率大概也只能达到93左右

考虑了是不是网络不够深,不能适配模型,于是把hide layer变成两层,改了一下网络部分的代码,在1层和2层中间添加了1_5表示1.5层

ps:只是添加一个隐含层会导致参数过多的问题,因此将第一个隐含层的结点数从1000改回100,加上第二个隐含层50的结点,让参数的个数不会变化太大

x = tf.placeholder(tf.float32, [None, 10], name='x-input')
y_ = tf.placeholder(tf.float32, [None, 4], name='y-output')
weight1 = tf.Variable(tf.random_normal([10, 100], stddev=0.1))
bias1 = tf.Variable(tf.zeros([100]))

weight1_5 = tf.Variable(tf.random_normal([100, 50], stddev=0.1))  #添加了一个隐含层
bias1_5 = tf.Variable(tf.zeros([50]))

weight2 = tf.Variable(tf.random_normal([50, 4], stddev=0.1))
bias2 = tf.Variable(tf.zeros([4]))

hide = tf.nn.relu(tf.matmul(x, weight1) + bias1)
hide2 = tf.nn.relu(tf.matmul(hide, weight1_5) + bias1_5)
y = tf.matmul(hide2, weight2) + bias2


T_T 然而在training data上的准确率没有提高超过百分之1,还是93.几

training data只有不到900组,再多的隐含层应该也没有帮助,感觉或许是learning rate导致模型的拟合不好,机智的使用的Adagrad自适应的方式更新参数

train_step = tf.train.AdagradOptimizer( 0.1 ).minimize(loss2, global_step=global_step)

果然。。。在train data上的准确率迅速到达了100% 

发现如果更改一下指数递减的更新参数,也可以在训练数据上达到100的准确率

learning_rate = tf.train.exponential_decay(0.1,global_step,2,0.999999,staircase=False)
然后产生1000-1023的testdata数据进行验证

def getTranData(x,y,start=10,end=900):  #改了一下之前的函数,方便测试数据
for i in range(start,end):

y.append(getLabel(i))

x.append(int2vector(i))

测试数据部分代码

test_data = []
test_label = []
getTranData(test_data,test_label,1000,1023)
print(sess.run(accuracy, feed_dict={x: test_data,y_:test_label}))


在测试数据上的准确率为95%左右~

-----------------------------------------------OVER--------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: