第一次个人编程作业

第一次修改:看了大佬的代码,下了Pycharm来跑一下profile,更新性能部分。

  • GitHub链接(3')

首先,应作业要求,先给出GitHub连接

  • PSP表格(6')

PSP2.1 Persnal Software Process Stages 预估耗时 实际耗时
Planning 计划 10 20
· Estimate · 估计这个任务需要多少时间 15 20
Development 开发 480 600
· Analysis · 需求分析(包括学习新技术) 100 180
· Design Spec 生成设计文档 30 ----
· Design Review 设计复审 15 ----
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 10 30
· Design · 具体设计 20 45
· Coding · 具体编码 60 200
· Code Review · 代码复审 20 15
· Test · 测试(自我测试,修改代码,提交修改) 40 60
Reporting 报告 ---- ----
· Test Repor · 测试报告 ---- ----
· Size Measurement · 计算工作量 ---- ----
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 ---- ----
· 合计 800 1170
表格中----的内容为未估计、未做。
  • 计算机模块的设计与实现过程(18')

这次的作业用到了Python来完成,含有以下几个部分。

文本的输入输出部分

#   文本输入函数,将文本从硬盘读入内存
def Readin(TextAddress):
    f = open(TextAddress,"r",encoding="UTF-8")
    Str = f.read()
    f.close()
    return Str

#   结果输入函数,将内存中的结果写入硬盘
def WriteOut(Jaccard, TextAddress):
    f = open(TextAddress,"w",encoding="UTF-8")
    f.write( str(Jaccard) )
    f.close()

Jaccard系数计算部分

这部分是整个程序的核心,当然也不是我自己写出来的。在我面向百度的程序设计的时候,查到文本相似度计算方法。原贴的链接在这儿,(在此感谢这位大佬让我有了做完作业的机会)。这篇文章介绍了几个可以用于计算文本相似度的系数,在用代码跑了几个测试之后,还是选择了好理解、结果也好看的Jaccard系数。

Jaccard系数是一个基于词频的、用于比较有限样本集之间的相似性,系数越大,相似度越高。
用一个例子来解释一下这个过程。
比如有两句话,“你是什么人”,“你是哪里人”。
经过 Sklearn 库中的 CountVectorizer 后得到:

["你", "是", "什", "么", "哪", "里", "人"]

然后再经过 fit_transform 得到:

[ [1 1 1 1 0 0 1]
  [1 1 0 0 1 1 1] ]

之后再借助第三方模块 numpy 中的函数来求得这两个集合的交集 numerator 和并集 denominator,Jaccard就等于 numerator / denominator。
在此附上 sklearn(scikit-learn)的 ·官网·中文文档
至于第三方模块jieba,我放在改进性能来讲。

#   Jaccard系数计算模块
#   输入两个string,输出一个int的系数
def Jaccard_Similarity(Str1, Str2):
    def Add_Space(Str):
        #   引入第三方模块jieba来进行中文分词
        Str_list = jieba.cut(Str, cut_all=False)
        #   把分词后的词用空格连接成string,以便转化成TF矩阵
        return ' '.join(list(Str_list))

    Str1, Str2 = Add_Space(Str1), Add_Space(Str2)
    #   记录词频,分词器为以' '为分隔符的lambda
    cv = CountVectorizer(tokenizer=lambda s: s.split())
    corpus = [Str1, Str2]
    #   转化为TF(Term Frequencies)矩阵
    vectors = cv.fit_transform(corpus).toarray()
    #   用第三方模块numpy求交并集
    numerator = numpy.sum(numpy.min(vectors,axis=0))    #   交集
    denominator = numpy.sum(numpy.max(vectors,axis=0))  #   并集
    #   返回Jaccard系数
    return 1.0 * numerator / denominator

性能测试部分

#   性能分析函数
def Analyze():
    print(u'当前进程的内存使用:%.4f MB' % (psutil.Process(os.getpid()).memory_info().rss / 1024 / 1024) )
    print(u'当前进程的使用的CPU时间:%.4f s' % (psutil.Process(os.getpid()).cpu_times().user) )
  • 计算模块接口部分的性能改进(12')

性能测试来自psutil模块os模块
在刚写出代码的时候,没有引入分词系统,只是简单的Jaccard系数。

然后引入了分词系统。

只是增加了运行时间和占用的内存,而我才疏学浅,主要内容也是引用第三方库,暂时无力改进性能

从大佬的博客中学到的Pycharm Profile:

  • 函数调用图

  • 各个部分的运行时间

  • 整个程序的用时

  • 计算模块部分单元测试处理说明(12')

首先是没有分词系统的测试结果:

在图中可以看出来,dis的文本的Jaccard都崩溃了。后来找到结果,因为Jaccard是基于词频的系数,dis文件的将文本中的字序进行改变,那这样一来得到的TF矩阵就没有差别。
为了解决问题,我从大佬们的博客学到了分词,所以就找到了第三方模块,·jieba
举个例子

["我来自福州大学"]

经过jieba里面的函数之后可以得出:

["我", "来自", "福州大学"]

借此来减轻因为Jaccard系数纯基于词频而导致的结果不如意。
引入了jieba之后:

大部分的结果就相对更尽人意。(虽然比不上大佬们个个都在0.8上下的结果,但是对于我这种菜鸡真的是尽力了)

  • 计算模块部分异常处理说明(6')

这个方面是我没有想到的,暂时没有内容,希望在今后的学习里面,能有机会学到并且更新博客的这个部分。

  • 记录PSP表格(3')

PSP表格已经填写在上面了。

最后是自己的一点瞎逼逼:

1.这门课真的是妙啊,作业一出来的时候就让我觉得我是不是比大家少上了一年的课,咋无从下手呢。在自己学了一点点python之后,似乎稍微能够理解一点“人生苦短,我选Python”了。
2.在自己做作业期间,大佬们开始交博客了,看到大佬们的博客思路又清晰,代码又规范,果然,我还是个垃圾。
3.明明自己花了蛮多时间才写出来的,稍微有点样子的结果,但是在写博客的时候又感觉确实没有做什么东西。好像是做事效率特别低的感觉。
4.不知道后面还有什么样的作业,to be continue。

posted @ 2020-09-15 16:43  阿_源儿  阅读(339)  评论(0编辑  收藏  举报