准备数据
从sklearn库中导入make_moon数据集,并绘制数据分布散点图:
import sklearn.datasets
np.random.seed(1) # 设置随机种子
X, Y = sklearn.datasets.make_moons(n_samples=200, noise=.2) # 导入 make_moon 数据集,样本个数 m=200,噪声标准差为 0.2 X[200,2] Y[200,]
X, Y = X.T, Y.reshape(1, Y.shape[0]) # X shape: [2,200],Y shape: [1,200]
m = X.shape[1] # 样本个数200
dim = X.shape[0] # 特征维度2
plt.scatter(X[0, Y[0,:]==0], X[1, Y[0,:]==0], c='r', marker='s') # 负类
plt.scatter(X[0, Y[0,:]==1], X[1, Y[0,:]==1], c='b', marker='o') # 正类
plt.show()
结果为
接下来定义Sigmoid函数:
def sigmoid(x):
"""
函数输入:
- x:sigmoid 函数输入
函数输出:
- y:sigmoid 输出
"""
y = 1 / (1 + np.exp(-x))
return y
定义逻辑回归优化算法,并进行训练
def optimizer(X, Y, num_iterations=200, learning_rate=0.01):
"""
函数输入:
- X:输入数据特征,维度 = (dim, m)
- Y:输入数据标签,维度 = (1, m)
- num_iteration:训练次数
- learning_rate:学习速率
函数输出:
- W:训练后的权重参数
- b:训练后的偏置参数
- cost:每次训练计算的损失存放在 cost 列表中
"""
cost = [] # 列表,存放每次训练的损失
m = X.shape[1] # 样本个数
dim = X.shape[0] # 特征维度
# 参数初始化
W = np.zeros((dim, 1))
b = 0
# 迭代训练
for i in range(num_iterations):
Z = np.dot(W.T, X) + b # 线性部分
Y_hat = sigmoid(Z) # 非线性部分
J = -1.0 / m * np.sum(Y * np.log(Y_hat) + (1 - Y) * np.log(1 - Y_hat)) # 代价函数
cost.append(J)
# 梯度下降
dW = 1.0 / m * np.dot(X, (Y_hat - Y).T)
db = 1.0 / m * np.sum(Y_hat - Y)
W = W - learning_rate * dW # W 更新公式
b = b - learning_rate * db # b 更新公式
if (i+1) % 20 == 0:
print('Iteration: %d, J = %f' % (i+1, J))
return W, b, cost
W, b, cost = optimizer(X, Y, num_iterations=1000, learning_rate=0.1)
绘制训练过程中的损失函数
plt.plot(cost)
plt.xlabel('迭代次数')
plt.ylabel('损失函数')
plt.show()
预测
定义预测函数并对输入数据X进行预测
def predict(X, W, b):
"""
函数输入:
- X:输入数据特征,维度 = (dim, m)
- W:训练后的权重参数
- b:训练后的偏置参数
函数输出:
- Y_pred:预测输出标签,维度 = (1, m)
"""
Y_pred = np.zeros((1, X.shape[1])) # 初始化 Y_pred
Z = np.dot(W.T, X) + b # 线性部分
Y_hat = sigmoid(Z) # 非线性部分
Y_pred[Y_hat > 0.5] = 1 # Y_hat 大于 0.5 的预测为正类
return Y_pred
Y_pred = predict(X, W, b)
print(Y_pred)
某次运行结果为
[[0. 0. 0. 0. 1. 1. 0. 1. 0. 1. 1. 0. 1. 0. 0. 1. 1. 0. 1. 0. 0. 0. 0. 0.
0. 1. 0. 0. 1. 0. 0. 1. 1. 1. 1. 1. 1. 0. 0. 1. 1. 0. 1. 0. 0. 0. 0. 0.
1. 1. 1. 1. 1. 0. 0. 1. 1. 0. 1. 1. 0. 0. 0. 0. 0. 1. 1. 0. 0. 0. 0. 0.
1. 1. 1. 1. 0. 0. 0. 1. 1. 0. 0. 1. 1. 0. 0. 1. 1. 0. 0. 0. 1. 1. 1. 0.
1. 1. 1. 1. 0. 0. 0. 1. 1. 0. 0. 1. 1. 0. 1. 1. 0. 0. 0. 1. 0. 1. 0. 0.
0. 0. 1. 1. 1. 0. 1. 1. 1. 1. 0. 0. 1. 0. 1. 0. 1. 1. 1. 0. 1. 1. 1. 1.
0. 1. 0. 1. 1. 0. 0. 0. 0. 0. 0. 1. 1. 0. 1. 1. 1. 0. 1. 1. 1. 1. 0. 1.
1. 0. 0. 0. 0. 1. 1. 1. 0. 0. 0. 0. 1. 1. 1. 1. 1. 0. 0. 1. 0. 1. 0. 1.
1. 1. 0. 1. 1. 0. 1. 0.]]
准确率为
accuracy = np.mean(Y_pred == Y)
print(accuracy)
0.86
绘制分类直线,可视化分类效果
from matplotlib.colors import ListedColormap
x_min, x_max = X[0, :].min() - 0.5, X[0, :].max() + 0.5
y_min, y_max = X[1, :].min() - 0.5, X[1, :].max() + 0.5
step = 0.001
xx, yy = np.meshgrid(np.arange(x_min, x_max, step), np.arange(y_min, y_max, step))
Z = predict(np.c_[xx.ravel(), yy.ravel()].T, W, b)
Z = Z.reshape(xx.shape)
plt.contourf(xx, yy, Z, cmap=plt.cm.Spectral) # 绘制边界,cmap = plt.cm.Spectral实现的功能是给label为1的点一种颜色,给label为0的点另一种颜色
plt.scatter(X[0, Y[0,:]==0], X[1, Y[0,:]==0], c='g', marker='s', label='负类') # 负类
plt.scatter(X[0, Y[0,:]==1], X[1, Y[0,:]==1], c='y', marker='o', label='正类') # 正类
plt.legend()
plt.show()
参考文献
王柳,《深度学习入门:基于Pytorch和TensorFlow的理论与实现》