一个最简单的分类,是在平面上画一条直线,左边为类0,右边为类1,直线表示为z=ax+by+c这是一个分类器,输入(x,y),那么,要求的参数有三个:a,b,c。另外注意c的作用,如果没有c,这条直线一定会过原点。
第一步:将线性方程转化为矩阵计算之后代入Sigmoid函数
将该直线转换为:z=w1x1+w2x2+w3*1形式。
使用矩阵代替线性方程组即:z=XW
矩阵X
系数W
但是,由于z的值可能为[−∞,+∞],为了方便处理,需要将其压缩到一个合理的范围。
需要代入sigmoid函数:g(z)=1/(1+e^-z)这样的激励函数,能够将刚才的区间,压缩到[0,1]。
处理二分类问题时:
我们根据伯努利分布(二项分布)分别计算z划分为类0,类1的概率为:
p(z=0|X;W)=g(XW)=1/(1+e^-XW)
p(z=1|X;W)=1-g(XW)=e^-XW/1+e^-XW
合并为z划分为某一类的概率为(每个样本点的概念):
p(z|X;W)=g(XW)^(1-z)*(1-g(XW))^(z)
第二步:获取最大似然估计
L(z|X;W)=求乘操作(g(XW)(1-z)*(1-g(XW))(z))
但由于最大似然估计值每一个都是[0,1]之间的值,如果直接相乘那么导致的结果就是:计算机可以没有办法表示那么高的精确度。
为了让计算机可以表示该结果,因此对最大似然估计求对数:
根据对数法则:
ln(AB)=lnA+lnB可知:
ln(A^b)=blnA
ln(A/B)=lnA-lnB
ln1=0
lne=1
LL(z|X;W)=求和操作(ln(g(XW)^(1-z))+ln((1-g(XW))^(z)))
化简过程为:
第三步:计算W使得最大似然估计值最大
计算方式:梯度上升
W0=W0+步长*梯度的方向
其中:
步长自己设定;
梯度的方向=LL(z|X;W)的导数;
计算LL(z|X;W)的导数
根据求导公式以及复合函数求导法则:
有关复合函数求导具体过程可以参照https://blog.csdn.net/angeliacmm/article/details/88188528里的复合函数求导。
LL(z|X;W)的导数的推导过程为:
在这个推导过程中第一部分属于复合函数求导,请参看上边那个链接,有具体的推导过程。
在机器学习算法中,在最小化损失函数时,可以通过梯度下降法来一步步的迭代求解,得到最小化的损失函数,和模型参数值。反过来,如果我们需要求解损失函数的最大值,这时就需要用梯度上升法来迭代了。
梯度下降法和梯度上升法是可以互相转化的。比如我们需要求解损失函数f(θ)的最小值,这时我们需要用梯度下降法来迭代求解。但是实际上,我们可以反过来求解损失函数 -f(θ)的最大值,这时梯度上升法就派上用场了。
因此可以根据梯度下降的办法进行处理。
梯度下降法是按下面的流程进行的:
1)首先对w赋值,这个值可以是随机的,也可以让w是一个全零的向量。
2)改变w的值,使得LL(w)按梯度下降的方向进行减少。
梯度方向由LL(w)对w的偏导数确定,由于求的是极大值,因此梯度方向是偏导数的正方向。结果为:
迭代更新的方式有两种,一种是批梯度下降,也就是对全部的训练数据求得误差后再对θ进行更新,另外一种是增量梯度下降,每扫描一步都要对θ进行更新。前一种方法能够不断收敛,后一种方法结果可能不断在收敛处徘徊。
有关梯度 下降的可以参考此文章https://www.cnblogs.com/pinard/p/5970503.html,说得很清楚详细。
第四步:编码实现
导入依赖的库
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt
装载数据
np.random.seed(4)
tf.set_random_seed(4)
N = 20000
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def inputs():
x_data = np.random.randn(N, 2)
w_real = [0.3, 0.5]
b_real = -0.2
wxb = np.matmul(w_real, x_data.T) + b_real
y_data_pre_noise = sigmoid(wxb)
y_data = [1.0 if e >= 0. else 0.0 for e in wxb]
return x_data, np.expand_dims(y_data, 1)
x_vals, y_vals = inputs()
def draw(x, y):
x_true = []
x_false = []
z = zip(x, y)
filter(filter_fun, Z)
for (e1, e2) in z:
if e2[0] == 0.0:
x_true.append(e1)
else:
x_false.append(e1)
x_true = np.array(x_true)
x_false = np.array(x_false)
return x_true, x_false
x_true, x_false = draw(x_vals, y_vals)
plt.plot(x_true[:, 0], x_true[:, 1], 'r.')
plt.plot(x_false[:, 0], x_false[:, 1], 'b.')
plt.title('Original Data')
plt.xlabel('X1')
plt.ylabel('X2')
plt.show()
np.random.seed(4)
tf.set_random_seed(4)
def get_batch():
batch_size = 50
rand_idx = np.random.choice(len(x_vals), batch_size)
rand_x_vals = x_vals[rand_idx]
rand_y_vals = y_vals[rand_idx]
return rand_x_vals, rand_y_vals
g = tf.Graph()
with g.as_default():
x_data = tf.placeholder(tf.float32, shape=(None, 2), name='x_data')
y_data = tf.placeholder(tf.float32, shape=(None, 1), name='y_data')
with tf.name_scope('inference') as scope:
w_data = tf.Variable(tf.random_normal((2, 1)), name='w_data')
b_data = tf.Variable(tf.random_normal(()), name='b_data')
y_pred = tf.sigmoid(tf.add(tf.matmul(x_data, w_data, name='xw'), b_data, name='add'))
with tf.name_scope('loss') as scope:
entropy = -(y_data * tf.log(y_pred) + (1.0 - y_data) * tf.log(1.0-y_pred))
loss = tf.reduce_mean(entropy)
with tf.name_scope('train') as scope:
optimizer = tf.train.GradientDescentOptimizer(1e-3)
train_step = optimizer.minimize(loss, name='train')
with tf.name_scope('accuracy') as scope:
prediction = tf.round(y_pred)
prediction_correct = tf.cast(tf.equal(prediction, y_data), tf.float32)
accuracy = tf.reduce_mean(prediction_correct)
train_acc = []
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for step in range(8000):
rand_x, rand_y = get_batch()
sess.run(train_step, feed_dict={x_data: rand_x, y_data: rand_y})
acc = sess.run(accuracy, feed_dict={x_data: x_vals, y_data: y_vals})
train_acc.append(acc)
y_pred_vals = sess.run(prediction, feed_dict={x_data: x_vals})
plt.plot(train_acc, 'r.')
plt.title('My Code')
plt.xlabel('Generation')
plt.ylabel('Accuracy')
plt.show()
x_true, x_false = draw(x_vals, y_pred_vals)
plt.plot(x_true[:, 0], x_true[:, 1], 'r.')
plt.plot(x_false[:, 0], x_false[:, 1], 'b.')
plt.title('My Result')
plt.xlabel('X1')
plt.ylabel('X2')
plt.show()
np.random.seed(4)
tf.set_random_seed(4)
def get_batch():
batch_size = 50
rand_idx = np.random.choice(len(x_vals), batch_size)
rand_x_vals = x_vals[rand_idx]
rand_y_vals = y_vals[rand_idx]
return rand_x_vals, rand_y_vals
g = tf.Graph()
with g.as_default():
x_data = tf.placeholder(tf.float32, shape=(None, 2), name='x_data')
y_data = tf.placeholder(tf.float32, shape=(None, 1), name='y_data')
with tf.name_scope('inference') as scope:
w_data = tf.Variable(tf.random_normal((2, 1)), name='w_data')
b_data = tf.Variable(tf.random_normal((1, 1)), name='b_data')
y_pred = tf.add(tf.matmul(x_data, w_data, name='xw'), b_data, name='add')
with tf.name_scope('loss') as scope:
entropy = tf.nn.softmax_cross_entropy_with_logits(labels=y_data, logits=y_pred)
loss = tf.reduce_mean(entropy)
with tf.name_scope('train') as scope:
optimizer = tf.train.GradientDescentOptimizer(1e-3)
train_step = optimizer.minimize(loss, name='train')
with tf.name_scope('accuracy') as scope:
prediction = tf.round(tf.sigmoid(y_pred))
prediction_correct = tf.cast(tf.equal(prediction, y_data), tf.float32)
accuracy = tf.reduce_mean(prediction_correct)
train_acc = []
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
for step in range(8000):
rand_x, rand_y = get_batch()
sess.run(train_step, feed_dict={x_data: rand_x, y_data: rand_y})
acc = sess.run(accuracy, feed_dict={x_data: x_vals, y_data: y_vals})
train_acc.append(acc)
y_pred_vals = sess.run(prediction, feed_dict={x_data: x_vals})
plt.plot(train_acc, 'r.')
plt.title('Other Code')
plt.xlabel('Generation')
plt.ylabel('Accuracy')
plt.show()
x_true, x_false = draw(x_vals, y_pred_vals)
plt.plot(x_true[:, 0], x_true[:, 1], 'r.')
plt.plot(x_false[:, 0], x_false[:, 1], 'b.')
plt.title('Other Result')
plt.xlabel('X1')
plt.ylabel('X2')
plt.show()