感知器训练过程 :param dataArr:训练集的数据 (list) :param labelArr: 训练集的标签(list) :param iter: 迭代次数,默认50 :return: 训练好的w和b
(dataArr, labelArr, iter=50)
| 46 | return dataArr, labelArr |
| 47 | |
| 48 | def perceptron(dataArr, labelArr, iter=50): |
| 49 | ''' |
| 50 | 感知器训练过程 |
| 51 | :param dataArr:训练集的数据 (list) |
| 52 | :param labelArr: 训练集的标签(list) |
| 53 | :param iter: 迭代次数,默认50 |
| 54 | :return: 训练好的w和b |
| 55 | ''' |
| 56 | print('start to trans') |
| 57 | #将数据转换成矩阵形式(在机器学习中因为通常都是向量的运算,转换称矩阵形式方便运算) |
| 58 | #转换后的数据中每一个样本的向量都是横向的 |
| 59 | dataMat = np.mat(dataArr) |
| 60 | #将标签转换成矩阵,之后转置(.T为转置)。 |
| 61 | #转置是因为在运算中需要单独取label中的某一个元素,如果是1xN的矩阵的话,无法用label[i]的方式读取 |
| 62 | #对于只有1xN的label可以不转换成矩阵,直接label[i]即可,这里转换是为了格式上的统一 |
| 63 | labelMat = np.mat(labelArr).T |
| 64 | #获取数据矩阵的大小,为m*n |
| 65 | m, n = np.shape(dataMat) |
| 66 | #创建初始权重w,初始值全为0。 |
| 67 | #np.shape(dataMat)的返回值为m,n -> np.shape(dataMat)[1])的值即为n,与 |
| 68 | #样本长度保持一致 |
| 69 | w = np.zeros((1, np.shape(dataMat)[1])) |
| 70 | #初始化偏置b为0 |
| 71 | b = 0 |
| 72 | #初始化步长,也就是梯度下降过程中的n,控制梯度下降速率 |
| 73 | h = 0.0001 |
| 74 | |
| 75 | #进行iter次迭代计算 |
| 76 | for k in range(iter): |
| 77 | #对于每一个样本进行梯度下降 |
| 78 | #李航书中在2.3.1开头部分使用的梯度下降,是全部样本都算一遍以后,统一 |
| 79 | #进行一次梯度下降 |
| 80 | #在2.3.1的后半部分可以看到(例如公式2.6 2.7),求和符号没有了,此时用 |
| 81 | #的是随机梯度下降,即计算一个样本就针对该样本进行一次梯度下降。 |
| 82 | #两者的差异各有千秋,但较为常用的是随机梯度下降。 |
| 83 | for i in range(m): |
| 84 | #获取当前样本的向量 |
| 85 | xi = dataMat[i] |
| 86 | #获取当前样本所对应的标签 |
| 87 | yi = labelMat[i] |
| 88 | #判断是否是误分类样本 |
| 89 | #误分类样本特诊为: -yi(w*xi+b)>=0,详细可参考书中2.2.2小节 |
| 90 | #在书的公式中写的是>0,实际上如果=0,说明改点在超平面上,也是不正确的 |
| 91 | if -1 * yi * (w * xi.T + b) >= 0: |
| 92 | #对于误分类样本,进行梯度下降,更新w和b |
| 93 | w = w + h * yi * xi |
| 94 | b = b + h * yi |
| 95 | #打印训练进度 |
| 96 | print('Round %d:%d training' % (k, iter)) |
| 97 | |
| 98 | #返回训练完的w、b |
| 99 | return w, b |
| 100 | |
| 101 | |
| 102 | def model_test(dataArr, labelArr, w, b): |
no outgoing calls
no test coverage detected