第一次使用tensorflow编写程序

来源:互联网 发布:绘声绘色软件怎么使用 编辑:程序博客网 时间:2024/06/01 08:32

最近一直在学习机器学习,看了一段时间的机器学习理论后,买了一本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 eledef 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 eledef 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 eledef 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--------------------------------------------


原创粉丝点击