自然语言处理 -文本预处理以及逻辑回归分类的简单实现(附代码)

注:本博客基于python3.7 Anaconda

使用到的库

import nltk 
from nltk import word_tokenize
import simplejson as jsons
import sklearn
from sklearn.feature_extraction.text import * 
from sklearn.model_selection import train_test_split 

from sklearn import linear_model 
from sklearn import metrics 

import numpy as np
import matplotlib.pyplot as plt

在文本预处理中,主要使用了nltk库,此外,nltk有可能需要手动下载一些包。
由于输入文本是json文件,我们需要用到simplejson读取。
sklearn主要用作后续的逻辑回归模型。

文本预处理分解函数

letter_percentage函数

  • 参数:
    text: 字符串
    letter: 字符(小写)
  • 返回值:在字符串中特定字符出现的百分比(不考虑大小写)
def letter_percentage(text, letter):
	print("输入字符串为:", text)
	
	#把字符串中所有字母字符按照小写提取到list中
	charlist = [char.lower() for char in text if char.isalpha()]
	
	#创建一个fdist对象来储存所有字符
	fdist = nltk.FreqDist(charlist)

	#计算特定字符letter出现的百分比
	frequency = fdist.freq(letter)
	
	character_percent = 100*frequency
	p = '{0:.2f}'.format(character_percent)
	print(letter,'字符在输入语句中占百分比为', p)
	return character_percent

Tokenization(标记化)

token:
   文本字符串或文档的字符组
   单一的“单词” + 可能的数字,标点等等

tokenization是文本预处理中很重要的一步。它的目的是接收一个字符串,或者一个list,内为nltk.text.Text类型的tokens。
接下来,把输入转换为单词的tokens,再把这些tokens用’universal’的标签集运行nltk的语言解释器。‘

tokenizer主要省略空格,标点等。

parts_of_speech函数

  • 参数:
    s: 字符串
    printflag: 1为打印输入字符串,0为不打印
  • 返回值:一个包含tokens和他们的POS标签的list
def parts_of_speech(s,printflag):
    '''例子:
    s = 'This is a sentence. And this is a second sentence! Cool.'
    z1, z2 = parts_of_speech(s,0)
        Tokens的总数量为14
        Tag: DET           Percentage of tokens =  28.57
		Tag: .             Percentage of tokens =  21.43
		Tag: NOUN          Percentage of tokens =  21.43
		....
    '''
    if printflag == 1:
    	print('输入为:',s)
    
    #把字符串标记化tokenize成单词tokens
    tokens = nltk.word_tokenize(s)

	#把POS标签用universal标签集提取出来
	tokens_and_tags = nltk.pos_tag(tokens, 'universal')

	#计算并打印tokens总数量
	n = len(tokens_and_tags)
	print('Tokens的总数量为',n)

	#使用FreqDist计数每个tag出现的次数(nltk)
	tag_counts = nltk.FreqDist(tags)
	
	#把上述FreqDist类排序,使用其内置函数
	sorted_tag_counts = tag_counts.most_common(len(tag_counts))

	#打印出每个tag和其出现的百分比,降序排列
	for item in sorted_tag_counts:
		tag_percent = 100 * item[1]/n
		p = '{0:.2f}'.format(tag_percent)
		print('Tag:',item[0],'\t   Percentage of tokens = ', p )

	return tokens_and_tags

review_pos函数

读取json文件,运行parts_of_speech函数去计算每个数据的tokens的百分比

  • 参数:
    k:第k个数据
    filename:读取文件
def review_pos(k,filename):
	print('加载文件: \n', filename)
	with open(filename, 'r') as jfile:
		data = json.load(jfile)
	print('提取的总数据个数为:', len(data),'\n')
	
	print('计算第',k,'条数据的百分比\n')

	#由于索引从零开始,提取k-1条数据
	d = data[k-1] 
	#提取和text关联的字符串
	s = d['text']
	print('第',k,'条数据的文本为:')
	print(s)
	parts_of_speech(s,0)

Bags of Words(BOW)

了解完上述简单几个步骤后,可以使用sklearn中的CountVectorizer函数直接把文本变成词袋(bags of words),从而向量化。

“CountVectorizer 类会将文本中的词语转换为词频矩阵,例如矩阵中包含一个元素a[i][j],它表示j词在i类文本下的词频。它通过 fit_transform 函数计算各个词语出现的次数,通过get_feature_names()可获取词袋中所有文本的关键字,通过 toarray()可看到词频矩阵的结果。
————————————————
版权声明:本文为CSDN博主「木水_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_37324740/article/details/79411651”

create_bow_from_reviews函数

  • 参数:
    filename:读取文件
    min_pos:大于等于这个数值,评分为1
    max_pos:小于等于这个数值,评分为0
def create_bow_from_reviews(filename, min_pos=4, max_neg=2):
	
	print('加载文件:', filename)
	with open(filename, 'r') as jfile:
		data = json.load(jfile)
	print('提取的总数据个数为:', len(data))

	#记录所有的文本信息
	text = []
	#记录所有的评分(也是class)
	Y = []
	
	print('正在提取每条数据的tokens,速度由数据量决定...')
	for d in data:#如果想测试,可以把data切片2
		#只留文本和评分
		review = d['text']
		stars = int(d['stars'])
		if stars >= min_pos:
			score = 1
		elif stars<=max_neg:
			score = 0
		else:
			#评分为3,不做记录(中立)
			continue
		text.append(review)
		Y.append(score)

	#text和score记录完毕
	#创建一个CountVectorizer实例,使用
	#1. 标准'english'停止词(stopword)集合
	#2. 只保留出现频率大于1%的词汇
	#3. 允许unigrams和bigrams(使用ngram_range=(1,2))

	vectorizer = CountVectorizer(stop_words = 'english', min_df = 0.01, ugram_range = (1,2))
		
	#创建一个稀疏的BOW数组/矩阵
	X = vectorizer.fit_transform(text)

	print('数据大小为:',X.shape)

	# vectorizer.get_feature_names()可以看到所有的词汇(features)

	return X, Y, vectorizer

现在,需要把X,Y数据集(X为特征,Y为标签)分成训练集和测试集。
基于训练集,要建立一个逻辑回归分类模型。
再用测试集去判断模型的性能

logistic_classification函数

  • 参数:
    X:特征数据
    Y:标签数据
    test_fraction:拆分比例
  • 返回值:分类模型
def logistic_classification(X, Y, test_fraction):
	
	#拆分X,Y数据
	X_train, X_test, Y_train, Y_test = train_test_split(X,Y, test_size=test_fraction, random_state = 42)
	#把random state设置成42为了我们可以生成同样的结果

	print("训练集的数量为:", X_train.shape[0])
	print("测试集的数量为:", X_test.shape[0])
	print("词汇的数量为:", X_train.shape[1])

	#指定一个逻辑回归分类模型。
	classifier = linear_model.LogisticRegression(penalty='l2', fit_intercept=True)

	#训练这个逻辑回归分类模型,并且评测在训练集上的准确度及AUC。
	print('\n使用',X_train.shape[0],'条数据训练模型中')
	classifier.fit(X_train, Y_train)
	train_predictions = classifier.predict(X_train)
	train_accuracy = metrics.accuracy.score(Y_train, train_predictions)

	class_probabilities_train = classifier.predict_proba(X_train)
	train_auc_score = metrics.roc_auc_score(Y_train, class_probabilities_train[:,1])
	
	print('\n训练集:')
	print('accuracy:', format(100*train_accuracy, '.2f'))
	print('AUC value:', format(100*train_auc_score, '.2f'))

	#评测在测试集上的准确度及AUC。
	print('\n测试集:')
	test_predictions = classifier.predict(X_test)
	test_accuracy = metrics.accuracy_score(Y_test, test_predictions)
	print('accuracy:', format(100*test_accuracy, '.2f'))

	class_probabilities = classifier.predict_proba(X_test)
	test_auc_score = metrics.roc_auc_score(Y_test, class_probabilities[:,1])
	print('AUC value:', format(100*test_auc_score, '.2f'))

	return classifier

训练应用待续…

此博客仅用于自我学习的记录,如有不当请指正。02/03/2022

你可能感兴趣的:(机器学习,自然语言处理,逻辑回归,分类,机器学习)