1.逻辑斯蒂回归代码实现

#!usr/bin/env python
# -*- coding:utf-8 _*-
"""
@author: liujie
@software: PyCharm
@file: logistic.py
@time: 2020/10/23 21:22
"""
import time
import numpy as np
from tqdm import tqdmdef loaddata(filename):"""加载数据:param filename: 文件路径:return: 返回数据与标签"""# 存放数据与标签dataList = []labelList = []# 打开文件fr = open(filename,'r')# 遍历文件每一行for line in tqdm(fr.readlines()):# 对每一行数据按照切割符“,”进行切割,返回字段列表curLine = line.strip().split(',')# 存放数据,将所有数据除255归一化dataList.append([int(num) / 255 for num in curLine[1:]])# 存放标签,# Mnsit有0-9是个标记,由于是二分类任务,所以将标记0的作为1,其余为0if int(curLine[0]) == 0:labelList.append(1)else:labelList.append(0)# 返回数据与标签return dataList,labelListdef logisticRegression(trainDataList,trainLabelList,iter=200):"""二项逻辑斯蒂回归训练过程:param trainDataList: 训练数据:param trainLabelList: 训练数据标签:param iter: 迭代轮数:return: 学习的w"""# 按照书本“6.1.2 二项逻辑斯蒂回归模型”中式6.5的规则,将w与b合在一起,此时x也需要添加一维,数值为1for i in tqdm(range(len(trainDataList))):trainDataList[i].append(1)# 将数据集由列表转换为数组形式,主要是后期涉及到向量的运算,统一转换成数组形式比较方便trainDataArr = np.array(trainDataList)# 初始化w,维数为样本x维数+1,+1的那一位是b,初始为0w = np.zeros(trainDataArr.shape[1])# 设置步长h = 0.001# 迭代iter次进行随机梯度下降for i in range(iter):# 每次迭代遍历所有样本,进行随机梯度下降for j in range(len(trainDataArr)):# 随机梯度上升部分# 在“6.1.3 模型参数估计”一章中给出了似然函数,我们需要极大化似然函数# 但是似然函数由于有求和项,并不能直接对w求导得出最优w,所以针对似然函数求和# 部分中每一项进行单独地求导w,得到针对该样本的梯度,并进行梯度上升(因为是# 要求似然函数的极大值,所以是梯度上升,如果是极小值就梯度下降。梯度上升是# 加号,下降是减号)# 求和式中每一项单独对w求导结果为:xi * yi - (exp(w * xi) * xi) / (1 + exp(w * xi))# w ,xi均为一维数组,np.dot(w,xi)为向量的内积wx = np.dot(w,trainDataArr[j])xi = trainDataArr[j]yi = trainLabelList[j]# 梯度上升w += h * (xi * yi - (1 + np.exp(wx) * xi) / (1 + np.exp(wx)))# 返回学到的wreturn wdef predict(w,x):"""预测标签:param testDataList: 测试数据:param w: 训练学到的w:return: 返回预测标签"""# dot为两个向量的点积操作,计算得到w * xwx = np.dot(w, x)# 计算标签为1的概率p = np.exp(wx) /(1 + np.exp(wx))if p > 0.5:return 1else:return 0def model_test(testDataList,testLabelList,w):"""验证准确率:param testDataList: 测试数据:param testLabelList:测试数据标签:param w:训练学到的w:return:acc"""# 为方便后续计算,将每个样本添加一维for i in range(len(testDataList)):testDataList[i].append(1)# 错误计数errorCnt = 0# 对每个测试集样本进行验证for i in tqdm(range(len(testDataList))):# 如果标记与预测不一致,则错误值加1if testLabelList[i] != predict(w,testDataList[i]):errorCnt += 1# 返回准确率return 1 - errorCnt / len(testDataList)if __name__ == '__main__':start = time.time()# 加载训练和测试数据集与标签print('start to read trainSet')trainDataList,trainLabelList = loaddata('data/mnist_train.csv')print('start to read testSet')testDataList,testLabelList = loaddata('data/mnist_test.csv')# 开始训练,学习wprint('start to train')w = logisticRegression(trainDataList,trainLabelList)#验证正确率print('start to test')accuracy = model_test(testDataList, testLabelList, w)# 打印准确率print('the accuracy is:', accuracy)# 打印时间print('time span:', time.time() - start)
start to read trainSet
100%|██████████| 60000/60000 [00:11<00:00, 5400.53it/s]
start to read testSet
100%|██████████| 10000/10000 [00:01<00:00, 5404.31it/s]
start to train
100%|██████████| 60000/60000 [00:00<00:00, 2990839.88it/s]
start to test
100%|██████████| 10000/10000 [00:00<00:00, 20395.12it/s]
the accuracy is: 0.902
time span: 204.0601818561554

2.最大熵代码实现-难

# coding=utf-8
# Author:Dodo
# Date:2018-11-30
# Email:lvtengchao@pku.edu.cn
# Blog:www.pkudodo.com'''
数据集:Mnist
训练集数量:60000(实际使用:20000)
测试集数量:10000
------------------------------
运行结果:正确率:96.9%运行时长:8.8h备注:对于mnist而言,李航的统计学习方法中有一些关键细节没有阐述,
建议先阅读我的个人博客,其中有详细阐述。阅读结束后再看该程序。
Blog:www.pkudodo.com
'''import time
import numpy as np
from collections import defaultdictdef loadData(fileName):'''加载Mnist数据集:param fileName:要加载的数据集路径:return: list形式的数据集及标记'''# 存放数据及标记的listdataList = []; labelList = []# 打开文件fr = open(fileName, 'r')# 将文件按行读取for line in fr.readlines():# 对每一行数据按切割福','进行切割,返回字段列表curLine = line.strip().split(',')#二分类,list中放置标签if int(curLine[0]) == 0:labelList.append(1)else:labelList.append(0)#二值化dataList.append([int(int(num) > 128) for num in curLine[1:]])#返回data和labelreturn dataList, labelListclass maxEnt:'''最大熵类'''def __init__(self, trainDataList, trainLabelList, testDataList, testLabelList):'''各参数初始化'''self.trainDataList = trainDataList          #训练数据集self.trainLabelList = trainLabelList        #训练标签集self.testDataList = testDataList            #测试数据集self.testLabelList = testLabelList          #测试标签集self.featureNum = len(trainDataList[0])     #特征数量self.N = len(trainDataList)                 #总训练集长度self.n = 0                                  #训练集中(xi,y)对数量self.M = 10000                              #self.fixy = self.calc_fixy()                #所有(x, y)对出现的次数self.w = [0] * self.n                       #Pw(y|x)中的wself.xy2idDict, self.id2xyDict = self.createSearchDict()        #(x, y)->id和id->(x, y)的搜索字典self.Ep_xy = self.calcEp_xy()               #Ep_xy期望值def calcEpxy(self):'''计算特征函数f(x, y)关于模型P(Y|X)与经验分布P_(X, Y)的期望值(P后带下划线“_”表示P上方的横线程序中部分下划线表示“|”,部分表示上方横线,请根据具体公式自行判断,)即“6.2.2 最大熵模型的定义”中第二个期望(83页最上方的期望):return:'''#初始化期望存放列表,对于每一个xy对都有一个期望#这里的x是单个的特征,不是一个样本的全部特征。例如x={x1,x2,x3.....,xk},实际上是(x1,y),(x2,y),。。。#但是在存放过程中需要将不同特诊的分开存放,李航的书可能是为了公式的泛化性高一点,所以没有对这部分提及#具体可以看我的博客,里面有详细介绍  www.pkudodo.comEpxy = [0] * self.n#对于每一个样本进行遍历for i in range(self.N):#初始化公式中的P(y|x)列表Pwxy = [0] * 2#计算P(y = 0 } X)#注:程序中X表示是一个样本的全部特征,x表示单个特征,这里是全部特征的一个样本Pwxy[0] = self.calcPwy_x(self.trainDataList[i], 0)#计算P(y = 1 } X)Pwxy[1] = self.calcPwy_x(self.trainDataList[i], 1)for feature in range(self.featureNum):for y in range(2):if (self.trainDataList[i][feature], y) in self.fixy[feature]:id = self.xy2idDict[feature][(self.trainDataList[i][feature], y)]Epxy[id] += (1 / self.N) * Pwxy[y]return Epxydef calcEp_xy(self):'''计算特征函数f(x, y)关于经验分布P_(x, y)的期望值(下划线表示P上方的横线,同理Ep_xy中的“_”也表示p上方的横线)即“6.2.2 最大熵的定义”中第一个期望(82页最下方那个式子):return: 计算得到的Ep_xy'''#初始化Ep_xy列表,长度为nEp_xy = [0] * self.n#遍历每一个特征for feature in range(self.featureNum):#遍历每个特征中的(x, y)对for (x, y) in self.fixy[feature]:#获得其idid = self.xy2idDict[feature][(x, y)]#将计算得到的Ep_xy写入对应的位置中#fixy中存放所有对在训练集中出现过的次数,处于训练集总长度N就是概率了Ep_xy[id] = self.fixy[feature][(x, y)] / self.N#返回期望return Ep_xydef createSearchDict(self):'''创建查询字典xy2idDict:通过(x,y)对找到其id,所有出现过的xy对都有一个idid2xyDict:通过id找到对应的(x,y)对'''#设置xy搜多id字典#这里的x指的是单个的特征,而不是某个样本,因此将特征存入字典时也需要存入这是第几个特征#这一信息,这是为了后续的方便,否则会乱套。#比如说一个样本X = (0, 1, 1) label =(1)#生成的标签对有(0, 1), (1, 1), (1, 1),三个(x,y)对并不能判断属于哪个特征的,后续就没法往下写#不可能通过(1, 1)就能找到对应的id,因为对于(1, 1),字典中有多重映射#所以在生成字典的时总共生成了特征数个字典,例如在mnist中样本有784维特征,所以生成784个字典,属于#不同特征的xy存入不同特征内的字典中,使其不会混淆xy2idDict = [{} for i in range(self.featureNum)]#初始化id到xy对的字典。因为id与(x,y)的指向是唯一的,所以可以使用一个字典id2xyDict = {}#设置缩影,其实就是最后的idindex = 0#对特征进行遍历for feature in range(self.featureNum):#对出现过的每一个(x, y)对进行遍历#fixy:内部存放特征数目个字典,对于遍历的每一个特征,单独读取对应字典内的(x, y)对for (x, y) in self.fixy[feature]:#将该(x, y)对存入字典中,要注意存入时通过[feature]指定了存入哪个特征内部的字典#同时将index作为该对的id号xy2idDict[feature][(x, y)] = index#同时在id->xy字典中写入id号,val为(x, y)对id2xyDict[index] = (x, y)#id加一index += 1#返回创建的两个字典return xy2idDict, id2xyDictdef calc_fixy(self):'''计算(x, y)在训练集中出现过的次数:return:'''#建立特征数目个字典,属于不同特征的(x, y)对存入不同的字典中,保证不被混淆fixyDict = [defaultdict(int) for i in range(self.featureNum)]#遍历训练集中所有样本for i in range(len(self.trainDataList)):#遍历样本中所有特征for j in range(self.featureNum):#将出现过的(x, y)对放入字典中并计数值加1fixyDict[j][(self.trainDataList[i][j], self.trainLabelList[i])] += 1#对整个大字典进行计数,判断去重后还有多少(x, y)对,写入nfor i in fixyDict:self.n += len(i)#返回大字典return fixyDictdef calcPwy_x(self, X, y):'''计算“6.23 最大熵模型的学习” 式6.22:param X: 要计算的样本X(一个包含全部特征的样本):param y: 该样本的标签:return: 计算得到的Pw(Y|X)'''#分子numerator = 0#分母Z = 0#对每个特征进行遍历for i in range(self.featureNum):#如果该(xi,y)对在训练集中出现过if (X[i], y) in self.xy2idDict[i]:#在xy->id字典中指定当前特征i,以及(x, y)对:(X[i], y),读取其idindex = self.xy2idDict[i][(X[i], y)]#分子是wi和fi(x,y)的连乘再求和,最后指数#由于当(x, y)存在时fi(x,y)为1,因为xy对肯定存在,所以直接就是1#对于分子来说,就是n个wi累加,最后再指数就可以了#因为有n个w,所以通过id将w与xy绑定,前文的两个搜索字典中的id就是用在这里numerator += self.w[index]#同时计算其他一种标签y时候的分子,下面的z并不是全部的分母,再加上上式的分子以后#才是完整的分母,即z = z + numeratorif (X[i], 1-y) in self.xy2idDict[i]:#原理与上式相同index = self.xy2idDict[i][(X[i], 1-y)]Z += self.w[index]#计算分子的指数numerator = np.exp(numerator)#计算分母的zZ = np.exp(Z) + numerator#返回Pw(y|x)return numerator / Zdef maxEntropyTrain(self, iter = 500):#设置迭代次数寻找最优解for i in range(iter):#单次迭代起始时间点iterStart = time.time()#计算“6.2.3 最大熵模型的学习”中的第二个期望(83页最上方哪个)Epxy = self.calcEpxy()#使用的是IIS,所以设置sigma列表sigmaList = [0] * self.n#对于所有的n进行一次遍历for j in range(self.n):#依据“6.3.1 改进的迭代尺度法” 式6.34计算sigmaList[j] = (1 / self.M) * np.log(self.Ep_xy[j] / Epxy[j])#按照算法6.1步骤二中的(b)更新wself.w = [self.w[i] + sigmaList[i] for i in range(self.n)]#单次迭代结束iterEnd = time.time()#打印运行时长信息print('iter:%d:%d, time:%d'%(i, iter, iterStart - iterEnd))def predict(self, X):'''预测标签:param X:要预测的样本:return: 预测值'''#因为y只有0和1,所有建立两个长度的概率列表result = [0] * 2#循环计算两个概率for i in range(2):#计算样本x的标签为i的概率result[i] = self.calcPwy_x(X, i)#返回标签#max(result):找到result中最大的那个概率值#result.index(max(result)):通过最大的那个概率值再找到其索引,索引是0就返回0,1就返回1return result.index(max(result))def test(self):'''对测试集进行测试:return:'''#错误值计数errorCnt = 0#对测试集中所有样本进行遍历for i in range(len(self.testDataList)):#预测该样本对应的标签result = self.predict(self.testDataList[i])#如果错误,计数值加1if result != self.testLabelList[i]:   errorCnt += 1#返回准确率return 1 - errorCnt / len(self.testDataList)if __name__ == '__main__':start = time.time()# 获取训练集及标签print('start read transSet')trainData, trainLabel = loadData('../Mnist/mnist_train.csv')# 获取测试集及标签print('start read testSet')testData, testLabel = loadData('../Mnist/mnist_test.csv')#初始化最大熵类maxEnt = maxEnt(trainData[:20000], trainLabel[:20000], testData, testLabel)#开始训练print('start to train')maxEnt.maxEntropyTrain()#开始测试print('start to test')accuracy = maxEnt.test()print('the accuracy is:', accuracy)# 打印时间print('time span:', time.time() - start)

统计学习方法读书笔记14-逻辑斯蒂回归代码实现与最大熵代码实现相关推荐

  1. 统计学习方法读书笔记15-逻辑斯蒂回归习题

    文章目录 1.课后习题 2.视频课后习题 1.课后习题 import numpy as np import time import matplotlib.pyplot as plt from mpl_ ...

  2. 刘二大人 PyTorch深度学习实践 笔记 P6 逻辑斯蒂回归

    刘二大人 PyTorch深度学习实践 笔记 P6 逻辑斯蒂回归 P6 逻辑斯蒂回归 1.torchversion 提供的数据集 2.基本概念 3.代码实现 P6 逻辑斯蒂回归 1.torchversi ...

  3. 【笔记】逻辑斯蒂回归

    一.逻辑斯蒂回归概述 (1)逻辑斯蒂回归的目的:分类. 逻辑斯蒂回归常常解决分类问题,特别是二分类问题. (2)逻辑斯蒂回归的过程:回归. 计算结果是0~1之间的连续值,代表发生的可能性(类概率). ...

  4. 数据挖掘-二项逻辑斯蒂回归模型算法的R实现

    本次为学生时期所写的实验报告,代码程序为课堂学习和自学,对网络程序有所参考,如有雷同,望指出出处,谢谢! 基础知识来自教材:李航的<统计学习方法> 本人小白,仍在不断学习中,有错误的地方恳 ...

  5. 逻辑斯蒂回归 逻辑回归_逻辑回归简介

    逻辑斯蒂回归 逻辑回归 Logistic regression is a classification algorithm, which is pretty popular in some commu ...

  6. 统计学习方法读书笔记(六)-逻辑斯蒂回归与最大熵模型(迭代尺度法(IIS))

    全部笔记的汇总贴:统计学习方法读书笔记汇总贴 逻辑斯谛回归 (logistic regression )是统计学习中的经典分类方法.最大熵是概率模型学习的一个准则,将其推广到分类问题得到最大熵模型(m ...

  7. 逻辑斯蒂回归_逻辑斯蒂回归详细解析 | 统计学习方法学习笔记 | 数据分析 | 机器学习...

    本文包括: 重要概念 逻辑斯蒂回归和线性回归 二项逻辑斯谛回归模型 逻辑斯蒂回顾与几率 模型参数估计 多项逻辑斯谛回归 其它有关数据分析,机器学习的文章及社群 1.重要概念: 在正式介绍逻辑斯蒂回归模 ...

  8. 李航统计学习方法 Chapter6 逻辑斯蒂回归

    第6章 逻辑斯蒂回归和最大熵模型 逻辑斯谛回归(LR)是经典的分类方法 1.逻辑斯谛回归模型是由以下条件概率分布表示的分类模型.逻辑斯谛回归模型可以用于二类或多类分类. P(Y=k∣x)=exp⁡(w ...

  9. 学习笔记——逻辑斯蒂回归与最大熵模型

    逻辑斯蒂回归(logistic regression)是统计学习中的经典分类方法.最大熵是概率模型学习的一个准则,将其推广到分类问题得到最大熵模型(maximum entropy).都属于对数线性模型 ...

  10. 局部加权回归、逻辑斯蒂回归、感知器算法—斯坦福ML公开课笔记3

    转载请注明:http://blog.csdn.net/xinzhangyanxiang/article/details/9113681 最近在看Ng的机器学习公开课,Ng的讲法循循善诱,感觉提高了不少 ...

最新文章

  1. 美国科技界高度关注中国科技创新进展
  2. Oracle常用语句记录
  3. AutoMapper之投影
  4. YII2集成GOAOP,实现面向方面编程!
  5. 课程 预编译框架,开发高性能应用 - 微软技术暨生态大会 2018
  6. GCD Game HDU - 7061
  7. 求职小记(持续更新)
  8. 着迷英语900句_开明的系统管理员如何让我着迷于Linux
  9. 苹果鼓励美国员工赴中国出差 一天500美元奖金
  10. 提升访问github.com网址的速度
  11. 考上MBA,为自己装一双翅膀
  12. Moss网站在不同服务器的迁移
  13. Android --- GreenDao的实现(ORM框架)
  14. 按键精灵手机助手计算时间差
  15. hairline!ios实现边框0.5px
  16. border 属性样式
  17. FIR数字滤波器在MATLAB中的实现
  18. java分享微博_java_java实现的新浪微博分享代码实例,weibo.java {@link IWeiboShareAPI#handle - phpStudy...
  19. PMBOK(第六版) 学习笔记 ——《第五章 项目范围管理》
  20. 如何接入中国工商银行网上银行B2C在线支付接口

热门文章

  1. 转:为 setuptools 开路搭桥
  2. 放弃微博,继续回来写月经
  3. lt;转载自刘佳ID:freedom0203和waretgt; C++中成员初始化列表的使用
  4. ASP.NET站点性能提升-缩短首页生成时间
  5. java day39【HTTP协议:响应消息 、Response对象 、ServletContext对象】
  6. babel-preset-env使用介绍
  7. go tcp socket
  8. 智能手持设备产品设计“八戒”
  9. 41.django中auth用户认证
  10. 面试高并发,看这篇就够了(下)