目录

  • 导入数据
  • 建立模型
  • 启动会话


导入数据

网上有很多的关于鸢尾花分类的博客都是从sklearn中直接导入的,因为上课的需要,需要用自己的数据来导入。我的数据是放在txt文件中的,首先看看大概的数据:

机器学习鸢尾花逻辑回归 逻辑回归鸢尾花分类_导入数据


这里的前4列是花的特征,且我的数据只有100行,且只有两种花(最后一列独热编码只有0,1),当然3种花的做法和两种花的做法是一样的。后面用softmax来进行分类时会用到150行的数据,且有3种花。

导入数据的代码:

def log_re(path,*batch):
# 从文件夹中读取数据
data = np.loadtxt(path, dtype='float32', delimiter=None)

# 总的数据的80%用于训练,其余的用于测试
length = int(len(data)*0.8)

# 注意这里的x_trian,y_train都是二阶的,特别注意y_train
x_train = []
y_train = []

# 当输入的batch的参数个数为1个时,表示会随机的输出batch个数据
if len(batch)> 0 and len(batch) < 2:
    # 随机的得到0到length之间的batch[0]个数,这里的batch[0]就是你输出的那个数
    ran = random.sample(range(0,length),batch[0])
    for i in ran:
        x = []
        y = []
        for j in range(len(data[0]) - 1):
            x.append(data[i][j])
        if data[i][-1] == 0:
            y.append(1)
            y.append(0)
        if data[i][-1] == 1:
            y.append(0)
            y.append(1)
        # y.append(data[i][-1])
        x_train.append(x)
        y_train.append(y)
    return x_train,y_train

# 假如batch个数等于0,表示没有输入,即随机输出length个数
elif len(batch) == 0:
    batch1=length
    ran = random.sample(range(0, length), batch1)
    for i in ran:
        x = []
        y = []
        for j in range(len(data[0]) - 1):
            x.append(data[i][j])
        if data[i][-1] == 0:
            y.append(1)
            y.append(0)
        if data[i][-1] == 1:
            y.append(0)
            y.append(1)
        # y.append(data[i][-1])
        x_train.append(x)
        y_train.append(y)
    return x_train,y_train
else:
    print("参数错误,请从新输出两个参数")
return x_train,y_train

这里得到的数据是总的数据的80%,这是用于训练的,并且每次输出都是随机的一个batch,batch的大小就是这个函数的第二个参数,这里默认的是batch=80,所以x_train和y_train的shape是(80,4)和(80,2)。

这里是直接把y_train变成了独热编码:

机器学习鸢尾花逻辑回归 逻辑回归鸢尾花分类_导入数据_02


这里建议从在导入自己txt数据时用np.loadtxt(),个人觉得很好用。

建立模型

首先是定义参数和占位符:
input_n = 4 #输入维度是4
output_n = 2 #输出维度是2
learn_rate = 0.5 #学习率
epoch = 20 #迭代次数,个人实验之后发现15次迭代之后就会有比较好的效果

x1 = tf.placeholder(tf.float32,shape=[None,input_n])
y = tf.placeholder(tf.float32,shape=[None,output_n])

w1 = tf.Variable(tf.ones([input_n,output_n]),name='weight1')
b1 = tf.Variable(tf.zeros([output_n]),name='base1')


#下面的两句代码的功能相同
y_pre = tf.matmul(x1,w1) + b1
#y_pre = tf.nn.bias_add(tf.matmul(x1,w1),b1)

#这里仅仅使用sigmoid函数和交叉熵来求解,没有用到softmax。
loss = tf.nn.sigmoid_cross_entropy_with_logits(labels=y, logits=y_pre, name='loss')

#这里用tf.reduce_mean()函数,表示的是平均的损失值
cross_entropy = tf.reduce_mean(loss)

train_step = tf.train.GradientDescentOptimizer(learn_rate).minimize(cross_entropy)

#tfarg_max()函数得到的是一行中最大的数的下标,tf.equal()函数是比较两个矩阵或向量是不是相同的,如果相同就是True
#不是就是False,
correct_prediction = tf.equal(tf.arg_max(y_pre, 1), tf.arg_max(y, 1))

#tf.cast()函数是转化类型的,这里就是转化为tf.float32类型,因为这里转化之后的值不是1就是0,所以用tf.reduce_mean()
#函数之后得到的就是正确率
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

启动会话

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

for i in range(epoch):
    x,y_ = log_re(path)

    sess.run(train_step,feed_dict={x1:x , y:y_})


    cross_entr,acc = sess.run([cross_entropy,accuracy],feed_dict={x1:x,y:y_})
    y_pred,corr = sess.run([y_pre,correct_prediction],feed_dict={x1:x,y:y_})
    print("第%d次迭代,cross_entropy=%f" % (i,cross_entr))
    print("第%d次迭代,acc=%f" % (i,acc))

    # 通过验证大概在迭代15次左右就能达到很好的效果,甚至是100%的效果,所以还以存在过拟合的
    # 当输出的值是一个向量或者矩阵时,建议用format来输出,这样可以整个输出矩阵或向量的值
    print("第{}次迭代,correct_pre={}" .format(i,corr))
    print("第{}次迭代,correct_pre={}" .format(i,y_pred))

第一次迭代的结果:

机器学习鸢尾花逻辑回归 逻辑回归鸢尾花分类_数据_03


从第一次迭代结果可以看出正确率比较小的,从correct_pre中就可以看出,里面的True和False有很多

第15次迭代结果:

机器学习鸢尾花逻辑回归 逻辑回归鸢尾花分类_导入数据_04


从15次迭代看出,correct_pre全部都为True,猜想可能是出现过拟合,当然从另一方面看正确率确实是变高了。