【论文实现】一篇Sigkdd的弹幕分析论文的python实现【LDA 实践者】

本文介绍了作者Jasper Yang在Bupt实现的一篇关于弹幕分析的A类会议论文的Python版LDA模型。文章详细阐述了如何处理数据,包括分词、计算词向量和Delta值,以及实现mpres和πc的过程。作者提到,初版实现耗时较长,但通过优化减少了主题数量和采用多线程,显著提升了运行速度。
摘要由CSDN通过智能技术生成

【论文实现】一篇Sigkdd的弹幕分析论文的python实现 【LDA 实践者】

Author : Jasper Yang
School : Bupt

warning : 此篇文章基于较为熟悉GibbsLDA++的源码的前提下阅读。

论文link

在开始之前,我想提前说明一下,这篇文章是我实现了基于用户喜好和评论的前后影响的改进LDA,因为实验室在做弹幕分析这方面的研究,就找到了这篇A类会议的文章,本来找他们要源码的,但是他们一作并不理我。。。然后我只好自己实现了。

由于是第一次写这类文章,不知道在逻辑上表达的清不清楚,~.~,望有看的各位给点建议,哈。

怎么实现

first of first
    from scipy.special import digamma
    import eulerlib
    import numpy as np
    import math
    from scipy.special import gamma
    import jieba
    import pandas as pd
    from scipy import stats

以上是本文所需库。

let’s begin(前期准备工作)

首先是处理数据

数据来源:bilibili(爬虫爬取)

数据格式如下。

                                                                                                    <?xml version="1.0" encoding="UTF-8"?><i>   <chatserver>chat.bilibili.com</chatserver><chatid>1007373</chatid><mission>0</mission><maxlimit>8000</maxlimit><source>e-r</source><ds>274694331</ds><de>3034701550</de><max_count>8000</max_count>
                                                                                                    <d p="72.409,1,25,16777215,1375542175,0,7526c714,274694331">我来组成弹幕..................</d>

<d p="33.551,1,25,16777215,1375543533,0,925384b2,274711742">大佬系边 </d>

<d p="117.977,1,25,16777215,1375543631,0,925384b2,274712904">甘嗨假噶 </d>

<d p="134.849,1,25,16777215,1375547487,0,D3dfe4a5,274755463">呢个日文..一个字都听唔明</d>
...

下面写了段代码解析获得上面的用户id以及每个用户的评论。
最后形成一个所有评论的列表以及每个用户对应其评论的字典。

    user = {}
    comments = []
    split_num = 10 # 分割一部电影为几个片段

    # 数据和停用词
    danmu = open('danmu/1007373.xml')
    stopwords = {}.fromkeys([ line.rstrip().decode('gbk') for line in open('stopwords.txt') ])
    # 读取文件,分析后存储到 user 和 comments
    for line in danmu.readlines()[:-1]:
        start = line.find('p=')
        stop = line.find('">')
        sub1 = line[start+3:stop]
        time = sub1.split(',')[0]
        sub1 = sub1.split(',')[6]
        start = line.find('">')
        stop = line.find('</d>')
        sub2 = line[start+2:stop].decode('utf-8')
        comments.append((float(time),sub2))
        temp = []
        if not user.has_key(sub1) :
            temp.append(sub2)
            user[str(sub1)] = temp
        else:
            user[str(sub1)].append(sub2)

经过以上处理后,我们还需要分片,我这里默认分割成十份。

    # 统计user的个数 , 现在统计的是这个文档里的user,后期要做成对所有文档的统计量,还要能支持增量
    user_num = len(user)

    # comments的数量
    comments_num = len(comments)

    # 排序,分割comments ---> shots
    comments = sorted(comments)
    spli = (comments[-1][0]-comments[0][0])/split_num
    shots = []
    for i in range(10):
        shots.append([x[1] for x in comments if x[0] > i*spli and x[0] <= (i+1)*spli ])

分割之后就是分词,我这里用的是python版的jieba,效果很一般,以后再更新。

注意:这里的切词我分成了两个部分。因为在文中认为片段(shot)和片段之间有时间上的影响,然后每个片段里的每一个comment之间有时间上的影响。但是不同的片段之间的comment是没有关系的。

def cut_word(x):
    words = jieba.cut(x, cut_all=False)
    final = []
    for word in words:
        if word not in stopwords:
            final.append(word)
    return final

def null(l):
    return len(l) > 0 or l[0] == ' '

for i in range(split_num):
    shots[i] = map(cut_word,shots[i])
    shots[i] = filter(null,shots[i])

上面的代码对每一个shot里面的所有comment进行切词。

准备工作到此为止~

real work

由于这是我第一次还原论文的实现内容,一开始也是一头雾水,无从下手。慢慢多看了几遍公式,我发现了一些规律。

这里写图片描述

这里写图片描述

了解LDA的同学对上面的一系列定义应该不陌生。
这是一个我们要实现的所有的矩阵的描述。

从头开始,对每一个用户生成一个用户对应主题的矩阵( xu )。每一个用户都有一个自己的 σ2u 。但是,由于我们是在初步实验阶段,我就写了个文件,里面存储所有的 σ2 值并且都为0.1。

    # 制造假的sigma文件
    user_num = len(user)
    f = open('sigma_u_t.csv','w')
    f.write(',user')
    for i in range(split_num*10):
        f.write(',topic'+str(i))
    f.write('\n')
    for key in user.keys():
        f.write(','+key)
        for j in range(split_num*10):
            f.write(',0.1')
        f.write('\n')


    # 每一个用户的user-topic分布
    # sigma_u_t 是每个用户对于每一个topic的sigma值
    # 从文件里面读取每一个用户的每一个topic的sigma值
    # 每一行一个用户 (顺序就是下面生成的 user_ 中的顺序)
    user_sigma = pd.read_csv('sigma_u_t.csv')
    user_sigma = user_sigma.drop(['Unnamed: 0'],1)
    user_sigma.fillna(0.1)


    # 利用上面的用户对应评论的字典 make 一个 dataframe
    user_ = pd.DataFrame()
    temp1 = []
    temp2 = []
    for key in user.keys():
        for i in range(len(user[key])):
            temp1.append(key)
            temp2.append(user[key][i])
    user_['user'] = temp1
    user_['comment'] = temp2

【后期的做法可以是去通过标签统计分析每一个用户对于主题的概率再去确定每一个用户的 σ2 值】

下面我们需要实现

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值