中文情感分類

本小結是對中文評論進行處理,利用word2vec工具獲得特徵數據,進而完成情感分析的目的

注意:本文重點是如何獲得特徵向量
根據項目本身的語料情況,一條評論就是一個txt文檔,有兩個語料文件:pos文件下包含1000條積極的評論,neg文件下包含1000條消極的評論

1-初始語料的預處理-把正向和負向評論分別規整到一個txt文件中,實施代碼如下

import logging
import os,os.path
import codecs,sys

#設置讀取文件內容的函數
def getContent(fullname):
    f = codecs.open(fullname,"r")
    #需要注意的時在原始語料中一個txt文檔中只有一句評論
    content=f.readline()
    f.close()
    return content

if __name__=="__main__":
    #得到文件名
    program = os.path.basename(sys.argv[0])
    logger=logging.getLogger(program)
    logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s')
    logging.root.setLevel(level=logging.INFO)

    #輸入文件目錄
    inp = "data\ChnSentiCorp_htl_ba_2000"
    #這裏時輸入文件目錄下正向評論文件夾和負向評論文件夾
    folders=["neg","pos"]

    #這裏開始遍歷兩個文件夾
    for foldername in folders:
        #日誌文件
        logging.info("running"+foldername+"files.")

        #這裏是定義輸出文件
        outp = "2000_"+foldername+".txt"
        output = codecs.open(outp,"w")
        i=0

        rootdir = inp+"\\"+foldername
        #三個參數:分別返回1-父目錄 2-所有文件夾名字(不包含路徑) 3-所有文件名字
        for parent,dirnames,filenames in os.walk(rootdir):
            for filename in filenames:
                content = getContent(rootdir+"\\"+filename)
                output.writelines(content)
                i=i+1
        #遍歷結束將1000個數據完全寫入到"2000_"+foldername+".txt"文件下
        output.close()
        #書寫日誌
        logger.info("saved"+str(i)+"files")

經過上一階段的處理現在得到了兩個txt文件,一個正向的txt文件和一個負向的txt文件,每一個txt文件下都包含1000條語句,下一步我們要將兩個txt文件的中文數據做分詞處理,這裏我們使用結巴分詞

2-逐行讀取數據進行jieba分詞-實施代碼如下

import jieba
import jieba.analyse
import codecs,sys,string,re

#首先定義文本分詞的方法
def prepareData(sourceFile,targetFile):
    f=codecs.open(sourceFile,"r",encoding="utf-8")
    target=codecs.open(targetFile,"w",encoding="utf-8")
    print("open source file:"+sourceFile)
    print("open target file:"+target)

    lineNum=1
    line = f.readline()
    while line:
        print("---------processing"+lineNum+"article--------")
        #經過兩個函數的處理獲得單詞
        line = clearText(line)
        seg_line = sent2word(line)
        target.writelines(seg_line+"\n")
        lineNum+=1
        #再次讀入一行數據
        line = f.readline()
    #工作完成關閉文件
    print("done")
    f.close()
    target.close()

#定義clearText函數用來對文本進行清洗-去掉停用詞等操作
def clearText(line):
    if line!="":
        #去除空格
        line=line.strip()

        #定義兩個空字符串
        intab=""
        outtab=""

        trantab = string.makettrans(intab,outtab)
        pun_num = string.punctuation+string.digits

        line =line.encode("utf-8")
        line = line.translate(trantab,pun_num)
        line = line.decode("utf-8")

        #去掉文本中的英文和數字
        line = re.sub("[a-zA-Z0-9]","",line)
        #去除文本中的中英文符號
        line = re.sub("[\s+\.\!\/_,$%^*(+\"\';:“”.]+|[+——!,。??、~@#¥%……&*()]+".decode("utf8"), "", line)
    #文本清洗完成並返回
    return line
#定義sent2word函數將句子切分成詞語
def sent2word(line):
    segList=jieba.cut(line,cut_all=False)
    segSentence=""
    for word in segList:
        if word!="\t":
            segSentence+=word+" "
    #返回詞組並且去掉兩端的空格
    return segSentence.strip()
if __name__=="__main__":
    sourceFile = "2000_neg.txt"
    targetFile = "2000_neg_cut.txt"
    prepareData(sourceFile,targetFile)

    sourceFile = "2000_pos.txt"
    targetFile = "2000_pos_cut.txt"
    prepareData(sourceFile, targetFile)

分詞完成後,即可讀取停用詞表中的停用詞,對分詞後的正負語料進行去除停用詞
1-讀取停用詞表
2-遍歷分詞後的句子,將沒歌詞丟到此表中進行匹配,若存在則替換爲空

3-#去除停用詞,具體實施代碼如下


import codecs,sys

#定義去除函數
def stopWord(sourceFile,targetFile,stopkey):
    sourcef = codecs.open(sourceFile,"r",encoding="utf-8")
    targetf = codecs.open(targetFile,"w",encoding="utf-8")
    print("open source file:" + sourceFile)
    print("open target file:" + targetFile)

    lineNum = 1
    line = sourcef.readline()
    while line:
        print("---------processing" + lineNum + "article--------")
        #調用delstopword函數將句子中的停用詞刪除
        sentence = delstopword(line,stopkey)

        targetf.writelines(sentence + "\n")
        lineNum += 1
        # 再次讀入一行數據
        line = f.readline()
    # 工作完成關閉文件
    print("done")
    targetf.close()
    sourcef.close()

#定義delstopword函數來刪除停用詞
def delstopword(line,stopkey):
    wordList = line.split(" ")
    sentence=""
    for word in wordList:
        if word not in stopkey:
            if word!="\t":
                sentence+=word+""
    return sentence.strip()

if __name__=="__main__":
    stopkey = [w.strip() for w in codecs.open('data\stopWord.txt', 'r', encoding='utf-8').readlines()]

    sourceFile = "2000_neg_cut.txt"
    targetFile = "2000_neg_cut_stopword.txt"
    stopWord(sourceFile,targetFile,stopkey)

    sourceFile = "2000_pos_cut.txt"
    targetFile = "2000_pos_cut_stopword.txt"
    stopWord(sourceFile, targetFile, stopkey)

4-獲得特徵向量

經過分詞處理後我們就得到了可以訓練word2vec的語料,下面要進行詞向量模型的訓練
從wiki中文語料生成的詞向量中抽取本文語料的特徵詞向量
即本文從文章最後得到的wiki.zh.text.vector中抽取特徵詞向量作爲模型的輸入

獲取特徵詞向量的主要步驟如下:
1-讀取模型詞向量矩陣
2-遍歷語句中的每一個詞,從模型詞向量矩陣中抽取當前詞的數值向量,一條語句即可的得到一個二維矩陣,行數爲詞的個數,列數爲模型設定的維數
3-根據得到的矩陣計算矩陣均值作爲當前語句的特徵詞向量
4-全部語句計算完成後,拼接語句類別代表的值,寫入csv文件

import warnings
# 加入詞條語句的意思是忽略警告
warnings.filterwarnings(action='ignore', category=UserWarning, module='gensim')
import logging
import os.path
import codecs,sys
#導入用於科學計算處理矩陣的兩個工具包
import numpy as np
import pandas as pd

import gensim

#構建函數返回一個詞序列表的詞向量
def getWordVecs(wordList,model):
    #定義一個空數組
    vecs=[]
    for word in wordList:
        word=word.replace("\n"," ")
        try:
            vecs.append(model[word])
        except KeyError:
            continue
    return np.array(vecs,dtype="float")

#構建文檔詞向量
def buildVecs(filename,model):
    fileVecs=[]
    with codecs.open(filename,"rb",encoding="utf-8")as contents:
        for line in contents:
            #更新日誌文件
            logger.info("Start line: " + line)
            wordList=line.split(" ")
            #這裏得到的是一句評論的向量矩陣
            vecs=getWordVecs(wordList,model)

            if len(vecs)>0:
                #經過這一步的處理將向量矩陣變成了一個向量
                vecsArray=sum(np.array(vecs))/len(vecs)
                #將這一句話的一個向量添加到fileVecs下
                fileVecs.append(vecsArray)
    #最終返回的是pos文件和neg文件內所有數據的向量
    return fileVecs

if __name__=="__main__":
    #這一塊解決的是日誌的問題
    program = os.path.basename(sys.argv[0])
    logger = logging.getLogger(program)
    logging.basicConfig(format='%(asctime)s: %(levelname)s: %(message)s', level=logging.INFO)
    logger.info("running %s" % ' '.join(sys.argv))

    #設置讀取文件的目錄
    fdir = '/Users/sy/Desktop/pyRoot/SentimentAnalysis/'
    inp = fdir + 'wiki.zh.text.vector'
    # 下載訓練好的詞向量模型-從inp目錄導入詞向量模型
    model = gensim.models.KeyedVectors.load_word2vec_format(inp, binary=False)

    #調用buildVecs函數將文檔內的數據進行向量化
    posInput = buildVecs(fdir + '2000_pos_cut_stopword.txt', model)
    negInput = buildVecs(fdir + '2000_neg_cut_stopword.txt', model)

    #要設置類別-積極的評論設置爲1,消極的評論設置爲0
    Y = np.concatenate((np.ones(len(posInput)), np.zeros(len(negInput))))

    X=posInput[:]
    for neg in negInput:
        X.append(neg)
    X=np.append(X)

    #將上述數據寫入到csv文件中

    df_x=pd.DataFrame(X)
    df_y=pd.DataFrame(Y)
    data=pd.concat([df_y,df_x],axis=1)

    data.to_csv(fdir+"2000_data.csv")
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章