5.4.1 随机梯度下降法
# -*- coding: utf-8 -*-
"""
Created on Mon Dec 4 18:31:14 2017
#qr 5.2.2 linear perceptron
@author: 96379
"""
#导入需要的包
# -*- coding : utf - 8 -*-
import numpy as np
#from common_libs import * # 使用散点图绘制函数
import matplotlib.pyplot as plt
import random
#数据文件转矩阵
#path 数据文件路径
#返回转换后的矩阵形式
def file2matrix(path):
floatRows = []
fp = open(path, "r")#qr 以只读形式打开文件
data_raw = fp.readlines() #qr 按行读取文件 形成一个一维的列表
for row in data_raw:
rowlist = row.strip('\n').split()#qr (strip())对每行去除换行符 (split())按空格切分字符 列表中的元素以逗号分隔
#print(rowlist)
floatRow = [float(i) for i in rowlist]#qr 将字符型数据转换为float型
floatRows.append(floatRow) #qr append() 函数并没有返回值
#print(np.mat(floatRows))
#data = [ [int(j) for j in i] for i in data_strlst]
return np.mat(floatRows)
#qr 利用数据集构造一个矩阵
def buildMat(dataSet):
m, n = np.shape(dataSet)
dataMat = np.zeros((m, n)) # 样本以行的形式展开 m * n ,m个样本 n个特征
dataMat[:, 0] = 1 #矩阵的第一列全部设置为 1 #qr 即为每个样本数据的 w0 系数
dataMat[:, 1:] = dataSet[:, :-1] #第一列和倒数第二列保持数据源不变,删除最后一列
return dataMat #qr 根据训练样本数据集 构造线性分类器的系数矩阵
def drawScatterbyLabel(plt,Input):
#plt.figure(3)
targetLabel = Input[: , -1] #提取数据标签
lenLabel = len(targetLabel)
for i in range(lenLabel):
if targetLabel[i] == 0:
plt.plot(Input[i, 0], Input[i , 1],color = 'red',marker = 'o')
else:
plt.plot(Input[i, 0], Input[i , 1],color = 'blue', marker = 's')
#1.导入数据
Input = file2matrix("testSet.txt") # 参见第一章
target = Input[ : , -1] #获取分类标签列表
[m , n] = np.shape(Input)
#2.按分类绘制散点图
drawScatterbyLabel(plt ,Input)
#3构建 x + b 系数矩阵 : b 默认为 1
dataMat = buildMat(Input)
#print(dataMat)
#4定义步长和迭代次数
alpha = 0.001 #步长
steps = 500 #迭代次数
weights = np.ones((n,1)) #初始化权重向量 权重值初始化为 1
def logistic(wTx):
return 1.0 / (1.0 + np.exp(-wTx))
weightlist = []
#算法主程序
#1. 对数据集的每个行向量进行 m 次随机抽取,保证每个向量都抽取到,而且不重复抽取
#2. 对抽取之后的行向量计算动态步长
#3. 进行梯度计算
#4. 求得行向量的权重,合并为矩阵的权重
for j in range(steps): #进行 500次迭代 0 ~ 499
dataIndex = list(range(m)) #以导入数据的行数 m 为个数 产生索引向量: 0 ~ 99
for i in range(m):
alpha = 2 / (1.0 + j + i) + 0.0001 #动态修改 alpha 步长 ->一种 alpha 值动态修改的策略
randIndex = int(random.uniform(0, len(dataIndex))) #生成 0~m之间的随机索引
#计算 dataMat 随机索引与权重的点积和
vectSum = dataMat[randIndex] * np.mat(weights)
grad = logistic(vectSum) #计算点积和的梯度
errors = target[randIndex] - grad #计算误差 #qr 期望 - 输出值
errors = float(errors)
weights = weights + alpha * errors * (np.mat(dataMat[randIndex]).T) #计算列向量权重
del(dataIndex[randIndex]) #从数据集中删除选取的随机索引
#5.程序的输出
print(weights) #输出训练后的权重
#weights = weights.tolist()[0]
#6.绘制训练后的超平面
X = np.linspace(-5 , 5, 100)
Y = -(float(weights[0]) + X*(float(weights[1]))) /float(weights[2])
plt.plot(X,Y)
plt.show



浙公网安备 33010602011771号