1,本Notebook实验背景 前几天发布的论文范例研究:《基于最小二乘法的突发事件网络舆情演化规律研究》 ,使用信息提取工具包GooSeeker,挖掘突发事件的网媒报道数据,获得突发事件网络舆情的散点图。利用基于最小二乘法的多项式拟合法,获取各种舆情数据的拟合函数,并以近年来的突发事件作为相关案例进行实证分析。研究表明,根据各网络舆情的函数特征,其演化模式可分为突发型、连续型和复合型等,该方法能够有效地揭示突发事件网络舆情的演化过程和演化规律,为突发事件网络舆情的实时应对提供理论基础。 不过有同事在阅读了该论文的原文后,对最小二乘法在该研究中的应用提出了疑问,见帖子“怎样用最小二乘法给网络舆情突发性事件建模?”, 问题是: "我看了这篇论文的全文,前面讲了多项式拟合,后面讲了3种事件的函数分布,似乎与前面的多项式拟合没有太大联系。 至于怎样算多项式拟合,估计是用了matlab的多项式拟合函数。 其实,关于多项式拟合,我一直不懂,是不是只能用于局部区域?除非是一个周期函数才能全局拟合,可以通过傅里叶分解,拟合到{cosθ, sinθ, cos2θ, sin2θ, cos3θ, sin3θ, ....}这样的线性空间上。" 因为大部分教程都选用了极其简单的被拟合函数,那么,我们在这个notebook中手工在坐标纸上画出来复杂的曲线形状,用高阶的多项式拟合,看看拟合能力。 查了一些资料,多项式在闭区间上拟合连续函数的能力是不容置疑的,有数学证明。 查了几个参考资料 1. 用多项式逼近连续函数 2. 多项式逼近连续函数 为了对最小二乘法作进一步的了解,今天就尝试在Jupyter Notebook的python环境下做实际计算。 1.1,最小二乘法的原理和要解决的问题 1.2,为什么做成Jupyter Notebook模板的形式 GooSeeker每年都要支持各个大学的毕业生采集数据完成他们的毕业设计。GooSeeker有一套微博数据采集工具,专门面向不希望编写网络爬虫程序的研究者设计的。 例如,可以先从微博关键词搜索入口,把搜到的涉及“xx城市空气”的微博话题采集下来,然后把这些话题的微博博文采集下来。微博博文内容呈现方式很丰富,文字、图片、视频都有。这些内容都可以采集下来,分别进行分析。例如,将视频采集下来以后抽取关键帧图片,利用图片分析方法进行分析。 针对重点的微博内容,可以深入采集转发和评论,转发者和评论者,可分析和描述传播的特征和转发者和评论者的传播者特征。还可以根据博主的粉丝数计算传播的量化特征。 GooSeeker推出多个微博采集工具,匹配高校师生从不同角度、不同传播路径、不同内容呈现采集数据的需求。同样也适用于公共领域和民间舆论场分析,市场和商业环境分析等。 数据采集下来之后,需要趁手的工具来做数据处理和数据分析,GooSeeker提供了文本分词和情感分析软件, 同时也推出了系列Jupyter Notebook,借助于python的大量第三方库,为数据分析大量强大的工具。 Jupyter Notebook这类交互式数据探索和分析工具代表了一股不容忽视的潮流,借助于Python编程的强大力量,数据加工的能力和灵活性已经有相当明显的优势,尤其是程序代码和文字描述可以混合编排,数据探索和数据描述做完了,一篇研究报告也基本上成型了。 然而Python毕竟是一个全功能的编程语言,对于非编程出身的数据分析师来说,Pandas,Numpy,Matplotlib这些词让人望而生畏。本系列Notebook将设法解决这个问题,让非编程出身的数据分析师能够忽略复杂的编程过程,专注于数据处理和统计分析部分,就像使用Excel的公式一样驾驭Python。 所以,我们将尝试发布一系列Jupyter Notebook,像文档模板,一些基本的程序环境设置、文件操作等固化下来,在设定的分析场景下不需要改动程序代码。而数据处理部分的代码可以根据需要截取选用。每一项功能用一个code cell存代码,不需要的处理功能可以删除。 1.3,notebook模板的存储结构 本notebook项目目录都预先规划好了,具体参看Jupyter Notebook项目目录规划参考。如果要做多个分析项目,可以把整个模板目录专门拷贝一份给每个分析项目。 2,第三方库 无新增 3,数据源 无。基于测试数据 4,修改历史 2021-07-22:第一版发布 5,版权说明 本notebook是GooSeeker大数据分析团队开发的,所分析的源数据是GooSeeker网络爬虫软件从互联网上收集的公开数据,本notebook中的数据和代码可自由共享使用,包括转发、复制、修改、用于其他项目中。 6,准备程序环境 导入必要的Python程序包 6.1,引入科学计算库 import numpy as np import scipy as sp 6.2,引入绘图库 import matplotlib.pyplot as plt from pylab import * mpl.rcParams['font.sans-serif'] = ['SimHei'] mpl.rcParams['axes.unicode_minus'] = False 6.3,引入最小二乘法算法 from scipy.optimize import leastsq 设置warning信息显示模式 %xmode Verbose import warnings warnings.filterwarnings("ignore", category=DeprecationWarning) 6.4,设置样本数据 ##样本数据(Xi,Yi),需要转换成数组(列表)形式 ##Xi=np.array([6.19,2.51,7.29,7.01,5.7,2.66,3.98,2.5,9.1,4.2]) ##Yi=np.array([5.25,2.83,6.41,6.71,5.1,4.23,5.05,1.98,10.5,6.3]) Xi=np.array([1,2,2,2,3,3,3,4,5,6,6,7, 8,9,10,11,12,13,14,15, 16,17,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,38,39,40,41,42, 43,43,44,44,45,46,46,46,47,47,47,48,49,50,51,52,52,53, 54,55,56,57,57,58,59,60,61,62,63,64,65]) Yi=np.array([36,35,34,33,32,31,30,29,28,27,26,25,24,23,22,22,22,23, 24,25,26,27,28,29,30,31,32,32,31,31,30,29,28,27,27,27,26,25,25,24,24,23,22,23,22,20,18,17,16,15,14,13,12,11,10,9,8,7,6,5, 4,4,5,6,7,8, 9,10,11,12, 13,14,15,15,17,18,19,19,19,18]) 6.5,设定拟合函数和偏差函数 函数的形状确定过程: 1.先画样本图像 2.根据样本图像大致形状确定函数形式(直线、抛物线、正弦余弦等) 本notebook想尝试一下用高阶多项式来拟合一个复杂的函数。 6.6,需要拟合的函数func 应该根据样本数据画出来一个曲线,看看用什么函数拟合比较好,本样本数据是通过手工在坐标纸上画了一个复杂曲线,取得样本点坐标,所以,打算用一个高阶多项式函数。 下面k1,k2,...表示多项式系数,为了做实验,可以增加和减少k。但是要注意,如果增加或者减少了,以下三个位置的代码也要做相应调整: 1. 定义p0的时候也要增加和减少 2. 读取结果的时候,应该增加或者减少要解析的变量 3. 画图的时候,y函数也要增加或者减少项数 def func(p,x): k1,k2,k3,k4,k5,k6,k7,b=p return k1*x+k2*x*x+k3*x*x*x+k4*x*x*x*x+k5*x*x*x*x*x+k6*x*x*x*x*x*x+k7*x*x*x*x*x*x*x+b 6.7,偏差函数 x,y都是列表:这里的x,y更上面的Xi,Yi中是一一对应的 def error(p,x,y): return func(p,x)-y 6.8,说明 1.leastsq函数的返回值tuple,第一个元素是求解结果,第二个是求解的代价值(个人理解) 2.官网的原话(第二个值):Value of the cost function at the solution 3.实例:Para=>(array([ 0.61349535, 1.79409255]), 3) 4.返回值元组中第一个值的数量跟需要求解的参数的数量一致 6.9,k,b的初始值 可以任意设定,经过几次试验,发现p0的值会影响cost的值:Para[1] p0=[1,1,1,1,1,1,1,1] 6.10,把error函数中除了p0以外的参数打包到args中(使用要求) Para=leastsq(error,p0,args=(Xi,Yi)) 7,读取结果 k1,k2,k3,k4,k5,k6,k7,b=Para[0] print("k1=",k1,"k2=",k2,"k3",k3,"k4",k4,"k5",k5,"k6",k6,"k7",k7,"b=",b) print("cost:"+str(Para[1])) print("求解的拟合曲线为:") print("y="+str(round(k1,8))+"x+"+str(round(k2,8))+"x*x+"+str(round(k3,8))+"x*x*x+"+str(round(k4,8))+"x*x*x*x+"+str(round(k5,8))+"x*x*x*x*x+"+str(round(k6,8))+"x*x*x*x*x*x+"+str(round(k7,8))+"x*x*x*x*x*x*x+"+str(round(b,8))) 输出结果: k1= -5.538626072535966 k2= 0.5935204648033131 k3 -0.03169723062415789 k4 0.0010780981889737474 k5 -2.4060332063518592e-05 k6 2.986767018396916e-07 k7 -1.4935906682360128e-09 b= 42.82007345274152 cost:1 求解的拟合曲线为: y=-5.53862607x+0.59352046x*x+-0.03169723x*x*x+0.0010781x*x*x*x+-2.406e-05x*x*x*x*x+3e-07x*x*x*x*x*x+-0.0x*x*x*x*x*x*x+42.82007345 8,画图:画样本点和拟合直线 plt.figure(figsize=(8,6)) ##指定图像比例: 8:6 plt.scatter(Xi,Yi,color="green",label="样本数据",linewidth=2) x=np.linspace(0,65,300) ##在0-65直接画300个连续点 y=k1*x + k2*x*x + k3*x*x*x + k4*x*x*x*x + k5*x*x*x*x*x + k6*x*x*x*x*x*x + k7*x*x*x*x*x*x*x + b ##函数式 plt.plot(x,y,color="red",label="拟合曲线",linewidth=2) plt.legend(loc='lower right') #绘制图例 plt.show() 9,下载本Jupyter Notebook |