赞
踩
- def load_dataset(filename):
- # 特征数据
- dataset = []
- # 标签数据
- labels = []
- with open(filename) as file:
- for eachline in file.readlines():
- # 将每一行的换行符去除并以空格拆分整行
- data_list = eachline.strip('\n').split('\t')
- # 初始化Xo为1,X1,X2为读取数据中的第一位、第二位值
- # 注意加上数值类型转化,不加容易出错
- dataset.append([1.0, float(data_list[0]), float(data_list[1])])
- labels.append(int(data_list[2]))
- return dataset, labels
- def sigmoid(x):
- # 跃阶函数表达式
- return 1.0/(1 + np.exp(-x))
-
- import numpy as np
- # 梯度上升优化算法
- def grad_ascent(dataset, labels):
- # 将列表转换成矩阵,方便进行矩阵运算
- data_matrix_mn = np.mat(dataset)
- label_matrix_m1 = np.mat(labels).transpose()
- # m:样本个数 n:特征个数
- m, n = np.shape(data_matrix_mn)
- # 初始化权重矩阵
- weight_matrix_n1 = np.ones((n, 1))
- # 步长
- alpha = 0.001
- # 训练次数
- times = 500
- for i in range(times):
- h_matrix_m1 = sigmoid(data_matrix_mn * weight_matrix_n1)
- error_matrix_m1 = label_matrix_m1 - h_matrix_m1
- # 根据计算出来error矩阵和步长调整权重矩阵 [1]
- weight_matrix_n1 = weight_matrix_n1 + alpha * data_matrix_mn.transpose() * error_matrix_m1
- return weight_matrix_n1
关于[1]的原理可见
点击打开链接。用一个例子定性解释了一下,没有严格证明。
- def draw_divide_line(dataset, labels, weights):
- import matplotlib.pyplot as plt
- # 类别1和类别0的坐标
- x1 = []
- y1 = []
- x0 = []
- y0 = []
- # 将数据集的数据分类并存入坐标
- for i in range(len(dataset)):
- if labels[i] == 1:
- x1.append(dataset[i][1])
- y1.append(dataset[i][2])
- else:
- x0.append(dataset[i][1])
- y0.append(dataset[i][2])
-
- # 计算决策边界坐标
- x = np.arange(-3, 3, 0.1)
- # weight[0] + weight[1]*x + weight[2]*y = 0 . 反算出y值
- y = (-weights[0] - weights[1] * x) / (weights[2])
-
- # 绘制数据集散点
- fig = plt.figure()
- ax = fig.add_subplot(111)
- type1 = ax.scatter(x1, y1, c='r', marker='s')
- type0 = ax.scatter(x0, y0, c='g')
-
- # 绘制决策边界
- ax.plot(x, y)
-
- # 添加标签
- plt.xlabel('x1')
- plt.ylabel('x2')
- # 添加图例
- ax.legend((type0, type1), ('0', '1'))
- plt.show()
输出效果:
- def stoc_grad_ascent(dataset, labels, times=300):
- dataset = np.array(dataset)
- m, n = np.shape(dataset)
- weight = np.ones(n)
- alaph = 0.001
- # 记录权重变化情况
- weight_change = []
- # 在数据集中循环训练次数
- for j in range(times):
- for i in range(m):
- # 利用每一条样本调整权重系数
- error = labels[i] - sigmoid(sum(dataset[i] * weight))
- weight = weight + alaph * error * dataset[i]
- # 记录权重
- weight_change.append(weight)
- return weight, weight_change
利用下述代码 先将权重的变化情况通过图形表示出来。
- def draw_weight_change(weight_change):
- import matplotlib.pyplot as plt
-
- times = np.arange(0, len(weight_change), 1)
-
- W0 = [weight[0] for weight in weight_change]
- W1 = [weight[1] for weight in weight_change]
- W3 = [weight[2] for weight in weight_change]
-
- fig = plt.figure('权重变化')
- ax1 = fig.add_subplot(311)
- ax2 = fig.add_subplot(312)
- ax3 = fig.add_subplot(313)
-
- ax1.plot(times, W0)
- ax2.plot(times, W1)
- ax3.plot(times, W3)
-
- ax1.set_ylabel('W0')
- ax2.set_ylabel('W1')
- ax3.set_ylabel('W2')
- plt.show()
- # 改进的随机梯度上升算法
- def stoc_grad_ascent2(dataset, labels, times=300):
- dataset = np.array(dataset)
- m, n = np.shape(dataset)
- weight = np.ones(n)
- weight_change = []
- for i in range(times):
- data_index = list(range(m))
- # 在一次数据集上训练时,不重复抽取数据集中一条样本进行权重训练
- for j in range(m):
- # 在 0至len(data_index) 上随机抽取一个整数rand_index
- rand_index = int(np.random.uniform(0, len(data_index)))
- # j增大时,减小步长的大小,减小权重调整的高频变动
- alpha = 4.0/(1.0 + i + j) + 0.001
- error = labels[rand_index] - sigmoid(sum(dataset[rand_index] * weight))
- weight = weight + alpha * error * dataset[rand_index]
- weight_change.append(weight)
- del(data_index[rand_index])
- return weight, weight_change
权重变化图:
-
- def load_dataset(filename):
- # 特征数据
- dataset = []
- # 标签数据
- labels = []
- with open(filename) as file:
- for eachline in file.readlines():
- # 将每一行的换行符去除并以空格拆分整行
- data_list = eachline.strip('\n').split('\t')
- # 初始化Xo为1,X1,X2为读取数据中的第一位、第二位值
- # 注意加上数值类型转化,不加容易出错
- dataset.append([1.0, float(data_list[0]), float(data_list[1])])
- labels.append(int(data_list[2]))
- return dataset, labels
-
- def sigmoid(x):
- # 跃阶函数表达式
- return 1.0/(1 + np.exp(-x))
-
- import numpy as np
- # 梯度上升优化算法
- def grad_ascent(dataset, labels):
- # 将列表转换成矩阵,方便进行矩阵运算
- data_matrix_mn = np.mat(dataset)
- label_matrix_m1 = np.mat(labels).transpose()
- # m:样本个数 n:特征个数
- m, n = np.shape(data_matrix_mn)
- # 初始化权重矩阵
- weight_matrix_n1 = np.ones((n, 1))
- # 步长
- alpha = 0.001
- # 训练次数
- times = 500
- for i in range(times):
- h_matrix_m1 = sigmoid(data_matrix_mn * weight_matrix_n1)
- error_matrix_m1 = label_matrix_m1 - h_matrix_m1
- # 根据计算出来error矩阵和步长调整权重矩阵
- weight_matrix_n1 = weight_matrix_n1 + alpha * data_matrix_mn.transpose() * error_matrix_m1
- return weight_matrix_n1
-
- def stoc_grad_ascent(dataset, labels, times=300):
- dataset = np.array(dataset)
- m, n = np.shape(dataset)
- weight = np.ones(n)
- alaph = 0.001
- # 记录权重变化情况
- weight_change = []
- # 在数据集中循环训练次数
- for j in range(times):
- for i in range(m):
- # 利用每一条样本调整权重系数
- error = labels[i] - sigmoid(sum(dataset[i] * weight))
- weight = weight + alaph * error * dataset[i]
- # 记录权重
- weight_change.append(weight)
- return weight, weight_change
-
- # 改进的随机梯度上升算法
- def stoc_grad_ascent2(dataset, labels, times=300):
- dataset = np.array(dataset)
- m, n = np.shape(dataset)
- weight = np.ones(n)
- weight_change = []
- for i in range(times):
- data_index = list(range(m))
- # 在一次数据集上训练时,不重复抽取数据集中一条样本进行权重训练
- for j in range(m):
- # 在 0至len(data_index) 上随机抽取一个整数rand_index
- rand_index = int(np.random.uniform(0, len(data_index)))
- # j增大时,减小步长的大小,减小权重调整的高频变动
- alpha = 4.0/(1.0 + i + j) + 0.001
- error = labels[rand_index] - sigmoid(sum(dataset[rand_index] * weight))
- weight = weight + alpha * error * dataset[rand_index]
- weight_change.append(weight)
- del(data_index[rand_index])
- return weight, weight_change
-
- def draw_weight_change(weight_change):
- import matplotlib.pyplot as plt
-
- times = np.arange(0, len(weight_change), 1)
-
- W0 = [weight[0] for weight in weight_change]
- W1 = [weight[1] for weight in weight_change]
- W3 = [weight[2] for weight in weight_change]
-
- fig = plt.figure('权重变化')
- ax1 = fig.add_subplot(311)
- ax2 = fig.add_subplot(312)
- ax3 = fig.add_subplot(313)
-
- ax1.plot(times, W0)
- ax2.plot(times, W1)
- ax3.plot(times, W3)
-
- ax1.set_ylabel('W0')
- ax2.set_ylabel('W1')
- ax3.set_ylabel('W2')
- plt.show()
-
-
-
-
-
-
- def draw_divide_line(dataset, labels, weights):
- import matplotlib.pyplot as plt
- # 类别1和类别0的坐标
- x1 = []
- y1 = []
- x0 = []
- y0 = []
- # 将数据集的数据分类并存入坐标
- for i in range(len(dataset)):
- if labels[i] == 1:
- x1.append(dataset[i][1])
- y1.append(dataset[i][2])
- else:
- x0.append(dataset[i][1])
- y0.append(dataset[i][2])
-
- # 计算决策边界坐标
- x = np.arange(-3, 3, 0.1)
- # weight[0] + weight[1]*x + weight[2]*y = 0 . 反算出y值
- y = (-weights[0] - weights[1] * x) / (weights[2])
-
- # 绘制数据集散点
- fig = plt.figure('数据集及决策边界')
- ax = fig.add_subplot(111)
- type1 = ax.scatter(x1, y1, c='r', marker='s')
- type0 = ax.scatter(x0, y0, c='g')
-
- # 绘制决策边界
- ax.plot(x, y.reshape((60, 1)))
-
- # 添加标签
- plt.xlabel('x1')
- plt.ylabel('x2')
- # 添加图例
- ax.legend((type0, type1), ('0', '1'))
- plt.savefig('divide_line.png')
-
-
-
-
- if __name__ == '__main__':
- dataset, labels = load_dataset(r'machine learning\Ch05\testSet.txt')
- weights, weight_change = stoc_grad_ascent2(dataset, labels)
- draw_divide_line(dataset, labels, weights)
- draw_weight_change(weight_change)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。