目录
一、数据来源
蒙牛评论数据集:共有2000多条数据,其中一列为label,一列为review,label这一列已经分好差评和好评,差评为0,好评为1,好评和差评占比为1比1.
二、导相应入的库
# 导入数据集预处理、特征工程和模型训练所需的库
from sklearn.model_selection import train_test_split
import os
from keras.callbacks import LearningRateScheduler
from docx import Document
import re
from keras.optimizers import Adam
import jieba
import pandas as pd
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
from keras.models import Sequential, load_model
from keras.layers import Conv1D, GlobalMaxPooling1D, Dense,Dropout
import numpy as np
from gensim.models import KeyedVectors
三、数据预处理
首先我进行了去停用词的处理,停用词调用的飞浆的网址,停用下载:这个链接里面有四个停用词表,有中文停用词表,百度停用词表,哈工大停用词表等,下面开始导入
def load_stop_words_from_file(stopwords_path):
doc = Document(stopwords_path)
stop_words = []
for paragraph in doc.paragraphs:
stop_words.extend(paragraph.text.split())
return stop_words
下面预处理文本,我进行了分词和去停用词这两步骤。
def preprocess_text(text):
# 分词
seg_list = jieba.lcut(text)
# 去除停用词和非中文字符
seg_list = [token for token in seg_list if token not in stop_words and re.match(r'^[\u4e00-\u9fa5]+$', token)]
return ' '.join(seg_list)
对于处理完的数据文本进行再次处理,否则会导致X_input出现为0的情况。在这里我是运用了预先训练好的词嵌入文件,Word2evc文件,他的下载链接如下:腾讯的预先训练好的词嵌入文件,接着我开始定word2evc这个模型。
def word2vec_transform(text, wv, max_length=1291):
vector_size = wv.vector_size
tokens = text.split()
vectors = []
for word in tokens:
if word in wv:
vectors.append(wv[word])
if vectors:
# 取所有词向量的平均值作为文本的表示
avg_vector = np.mean(vectors, axis=0)
# 将向量填充或截断到固定长度 max_length
if len(avg_vector) < max_length:
avg_vector = np.pad(avg_vector, ((0, max_length - len(avg_vector)),), 'constant')
else:
avg_vector = avg_vector[:max_length]
return avg_vector.reshape((max_length, 1)) # 返回 (1291, 1) 的形状
else:
# 如果文本中所有词都不在词汇表中,可以返回一个默认向量或全零向量
return np.zeros((max_length, 1))
记住在所用的文本预处理的时候都需要运行这个函数,否则最后报错要找好久,别问我就是这里有问题。
接下来对文本进行预处理。
# 读取 Excel 文件
df = pd.read_excel(file_path)
# 对评论文本进行预处理
df['review'] = df['review'].apply(preprocess_text)
# 对处理后的评论文本进行 word2vec 转换示例
df['vector_representation'] = df['review'].apply(lambda text: word2vec_transform(text, wv))
# 将处理后的数据保存到一个文件中
processed_file = os.path.join(output_folder, 'processed_data.csv')
df.to_csv(processed_file, index=False, encoding='utf-8')
# 读取处理后的数据文件
processed_data = pd.read_csv(processed_file)
下一步特征工程,基本都是那样的,阿巴阿巴直接看代码吧,我不想打字了,为什么这个写作不能直接粘贴,其实我课设写的挺详细的,代码都有注释的应该能看懂吧,下面我会放完整的代码的,别急着复制,不然会报错的,阿巴阿巴。
这一步是进行划分测试集和训练集的,因为是随机分的,然后我输出训练集和测试集的好评差评比,都是1比1所以是没有问题的。
# 特征工程
X = processed_data['review']
y = processed_data['label']
# 按照7.5:2.5的比例随机划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)
# Word2Vec 特征提取函数
def word2vec_transform(text, wv, max_length=1291):
vector_size = wv.vector_size
tokens = text.split()
vectors = []
for word in tokens:
if word in wv:
vectors.append(wv[word])
if vectors:
# 取所有词向量的平均值作为文本的表示
avg_vector = np.mean(vectors, axis=0)
# 将向量填充或截断到固定长度 max_length
if len(avg_vector) < max_length:
avg_vector = np.pad(avg_vector, ((0, max_length - len(avg_vector)),), 'constant')
else:
avg_vector = avg_vector[:max_length]
return avg_vector.reshape((max_length, 1)) # 返回 (1291, 1) 的形状
else:
# 如果文本中所有词都不在词汇表中,可以返回一个默认向量或全零向量
return np.zeros((max_length, 1))
# 获取 Word2Vec 特征
X_train_w2v = np.array([word2vec_transform(text, wv) for text in X_train])
X_test_w2v = np.array([word2vec_transform(text, wv) for text in X_test])
print(X_train_w2v.shape)
# 将 Pandas Series 转换为 NumPy 数组
y_train = np.array(y_train)
y_test = np.array(y_test)
四、模型的构建
因为我这个是基于CNN的,所以我就写了一个,为什么没写其他的,因为我没时间了而且光报错,还有因为我是大学牲,哎,我放假了还写这个我真佩服我自己。好了我不瞎扯了,我这个是三个卷积层,一个池化,一个Droupout(因为我忘记他中文是啥意思了,就写这个了,哎,我四级还没过,我服了,我服了不知到8月份我能不能过),还有个全连接,最后输出了。我上面没做数据增强,因为没时间了,而且准确率还可以89%左右(这个好难用,刚刚给我加粗了,吓人,好讨厌格式)看代码吧。
# 构建CNN模型
model = Sequential()
model.add(Conv1D(128, 5, activation='relu', input_shape=(1291, 1)))
model.add(Conv1D(128, 5, activation='relu'))
model.add(Conv1D(128, 5, activation='relu'))
model.add(GlobalMaxPooling1D())
#全连接
model.add(Dense(64, activation='relu'))
model.add(Dropout(0.5))
#输出
model.add(Dense(1, activation='sigmoid')) # 二分类任务,输出层使用 sigmoid 激活函数
我添加了一个Adam优化器来进一步优化模型的性能,顺便定义一个调整递减学习率的函数。
# 使用 Adam 优化器,并设置初始学习率
adam = Adam(learning_rate=0.0001)
# # 定义学习率调度器,逐渐降低学习率
def lr_scheduler(epoch, lr):
return lr * 0.95 # 每个 epoch 减少 5% 的学习率
lr_scheduler_cb = LearningRateScheduler(lr_scheduler)
# 定义指标,包括需要的 precision 和 recall
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# 使用学习率调度器回调函数训练模型
history = model.fit(X_train_w2v, y_train, epochs=30, batch_size=32, validation_data=(X_test_w2v, y_test), callbacks=[lr_scheduler_cb])
写完之后千万要记得保存代码,不然还是上次的模型,我就是这样错的,呜呜呜。
model.save('my_model.keras')
# 加载模型
loaded_model = load_model('my_model.keras')
接下来就是计算准确率,精确率,召回率,F1分数等操作
# 假设 X_test_w2v 是您的测试集特征数据,y_test 是对应的真实标签
X_test_w2v = np.array([word2vec_transform(text, wv) for text in X_test])
# 进行预测
y_pred_prob = loaded_model.predict(X_test_w2v)
y_pred = (y_pred_prob > 0.5).astype(int)
# 计算评估指标
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
# 打印评估指标
print(f'Accuracy: {accuracy:.4f}')
print(f'Precision: {precision:.4f}')
print(f'Recall: {recall:.4f}')
print(f'F1 Score: {f1:.4f}')
# 输出模型结构摘要
model.summary()
五、预测函数
首先,惯例的第一步导库。
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.text import Tokenizer
好了,很重要的一步,文本之前调用W2v模型真的,我最后因为这个预测不出来,这个非常重要,这个非常重要,这个非常重要。所以这一步我就不粘了,和上面一样。
对预测的文本进行处理。
def preprocess_input_text(text):
global wv
# 分词
seg_list = jieba.lcut(text)
# 去除停用词和非中文字符
seg_list = [token for token in seg_list if token not in stop_words and re.match(r'^[\u4e00-\u9fa5]+$', token)]
processed_text = ' '.join(seg_list)
return word2vec_transform2(processed_text, wv)
导入你预先保存好的模型,我这里把数字改为好评差评了。
def load_my_model():
try:
return load_model('my_model.keras')
except Exception as e:
print("Failed to load model:", str(e))
return None
model = load_my_model()
label_map = {0: '差评', 1: '好评'}
很好要结束了,输出预测的值和导入相关函数,我那个输出x,y是为了检查为什么错了,你们可以删了。
def predict_sentiment(text):
global model
if model is None:
raise Exception("Model loading failed.")
try:
X_input = preprocess_input_text(text)
X_input = np.expand_dims(X_input, axis=0)
y_pred_prob = model.predict(X_input)
print("Prediction probabilities:", X_input)
print("Prediction probabilities:", y_pred_prob) # Print prediction probabilities
y_pred = int(y_pred_prob[0] > 0.5) # Convert boolean to integer (0 or 1)
sentiment_label = label_map[y_pred]
return sentiment_label
except Exception as e:
print("Prediction error:", str(e))
return None
最后一步导入最后运行的那个玩意,嗨嗨嗨。
if __name__ == '__main__':
while True:
comment = input("请输入评论文本 (输入 'exit' 退出): ")
if comment.lower() == 'exit':
break
try:
sentiment_label = predict_sentiment(comment)
if sentiment_label is None:
print("无法预测情感")
else:
print("情感预测结果:", sentiment_label)
except Exception as e:
print(f'Prediction error: {str(e)}')
好了下面就是完整的代码。
# 导入数据集预处理、特征工程和模型训练所需的库
from sklearn.model_selection import train_test_split
import os
from keras.callbacks import LearningRateScheduler
from docx import Document
import re
from keras.optimizers import Adam
import jieba
import pandas as pd
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
from keras.models import Sequential, load_model
from keras.layers import Conv1D, GlobalMaxPooling1D, Dense,Dropout
import numpy as np
from gensim.models import KeyedVectors
# 替换为你的Word2Vec模型文件路径
model_path = r'D:\蒙牛评论数据集\word2evc.txt'
# 加载Word2Vec模型
wv = KeyedVectors.load_word2vec_format(model_path, binary=False)
# 定义停用词表路径和数据文件路径
stopwords_docx_path = r'D:\蒙牛评论数据集\停用词表.docx'
file_path = r'D:\蒙牛评论数据集\蒙牛评论数据集.xlsx'
output_folder = 'data'
# 读取Excel文件
df = pd.read_excel(file_path)
## 停用词表文件路径
stopwords_docx_path = r'D:\蒙牛评论数据集\停用词表.docx'
# 加载停用词表
def load_stop_words_from_file(stopwords_path):
doc = Document(stopwords_path)
stop_words = []
for paragraph in doc.paragraphs:
stop_words.extend(paragraph.text.split())
return stop_words
# 全局变量停用词列表
stop_words = load_stop_words_from_file(stopwords_docx_path)
# 预处理文本函数
def preprocess_text(text):
# 分词
seg_list = jieba.lcut(text)
# 去除停用词和非中文字符
seg_list = [token for token in seg_list if token not in stop_words and re.match(r'^[\u4e00-\u9fa5]+$', token)]
return ' '.join(seg_list)
# 假设你已经有一个 wv(Word2Vec 模型)
# 示例 word2vec_transform 函数
def word2vec_transform(text, wv, max_length=1291):
vector_size = wv.vector_size
tokens = text.split()
vectors = []
for word in tokens:
if word in wv:
vectors.append(wv[word])
if vectors:
# 取所有词向量的平均值作为文本的表示
avg_vector = np.mean(vectors, axis=0)
# 将向量填充或截断到固定长度 max_length
if len(avg_vector) < max_length:
avg_vector = np.pad(avg_vector, ((0, max_length - len(avg_vector)),), 'constant')
else:
avg_vector = avg_vector[:max_length]
return avg_vector.reshape((max_length, 1)) # 返回 (1291, 1) 的形状
else:
# 如果文本中所有词都不在词汇表中,可以返回一个默认向量或全零向量
return np.zeros((max_length, 1))
# 读取 Excel 文件
df = pd.read_excel(file_path)
# 对评论文本进行预处理
df['review'] = df['review'].apply(preprocess_text)
# 对处理后的评论文本进行 word2vec 转换示例
df['vector_representation'] = df['review'].apply(lambda text: word2vec_transform(text, wv))
# 将处理后的数据保存到一个文件中
processed_file = os.path.join(output_folder, 'processed_data.csv')
df.to_csv(processed_file, index=False, encoding='utf-8')
# 读取处理后的数据文件
processed_data = pd.read_csv(processed_file)
# 特征工程
X = processed_data['review']
y = processed_data['label']
# 按照7.5:2.5的比例随机划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)
# Word2Vec 特征提取函数
def word2vec_transform(text, wv, max_length=1291):
vector_size = wv.vector_size
tokens = text.split()
vectors = []
for word in tokens:
if word in wv:
vectors.append(wv[word])
if vectors:
# 取所有词向量的平均值作为文本的表示
avg_vector = np.mean(vectors, axis=0)
# 将向量填充或截断到固定长度 max_length
if len(avg_vector) < max_length:
avg_vector = np.pad(avg_vector, ((0, max_length - len(avg_vector)),), 'constant')
else:
avg_vector = avg_vector[:max_length]
return avg_vector.reshape((max_length, 1)) # 返回 (1291, 1) 的形状
else:
# 如果文本中所有词都不在词汇表中,可以返回一个默认向量或全零向量
return np.zeros((max_length, 1))
# 获取 Word2Vec 特征
X_train_w2v = np.array([word2vec_transform(text, wv) for text in X_train])
X_test_w2v = np.array([word2vec_transform(text, wv) for text in X_test])
print(X_train_w2v.shape)
# 将 Pandas Series 转换为 NumPy 数组
y_train = np.array(y_train)
y_test = np.array(y_test)
# 构建CNN模型
model = Sequential()
model.add(Conv1D(128, 5, activation='relu', input_shape=(1291, 1)))
model.add(Conv1D(128, 5, activation='relu'))
model.add(Conv1D(128, 5, activation='relu'))
model.add(GlobalMaxPooling1D())
#全连接
model.add(Dense(64, activation='relu'))
model.add(Dropout(0.5))
#输出
model.add(Dense(1, activation='sigmoid')) # 二分类任务,输出层使用 sigmoid 激活函数
# 使用 Adam 优化器,并设置初始学习率
adam = Adam(learning_rate=0.0001)
# # 定义学习率调度器,逐渐降低学习率
def lr_scheduler(epoch, lr):
return lr * 0.95 # 每个 epoch 减少 5% 的学习率
lr_scheduler_cb = LearningRateScheduler(lr_scheduler)
# 定义指标,包括需要的 precision 和 recall
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# 使用学习率调度器回调函数训练模型
history = model.fit(X_train_w2v, y_train, epochs=30, batch_size=32, validation_data=(X_test_w2v, y_test), callbacks=[lr_scheduler_cb])
model.save('my_model.keras')
# 加载模型
loaded_model = load_model('my_model.keras')
# 假设 X_test_w2v 是您的测试集特征数据,y_test 是对应的真实标签
X_test_w2v = np.array([word2vec_transform(text, wv) for text in X_test])
# 进行预测
y_pred_prob = loaded_model.predict(X_test_w2v)
y_pred = (y_pred_prob > 0.5).astype(int)
# 计算评估指标
accuracy = accuracy_score(y_test, y_pred)
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)
# 打印评估指标
print(f'Accuracy: {accuracy:.4f}')
print(f'Precision: {precision:.4f}')
print(f'Recall: {recall:.4f}')
print(f'F1 Score: {f1:.4f}')
# 输出模型结构摘要
model.summary()
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.text import Tokenizer
max_len = 1291
global tokenizer # 假设这是全局的 tokenizer 变量
tokenizer = Tokenizer()
def word2vec_transform2(text, wv, max_length=1291):
vector_size = wv.vector_size
tokens = text.split()
vectors = []
for word in tokens:
if word in wv:
vectors.append(wv[word])
if vectors:
# 取所有词向量的平均值作为文本的表示
avg_vector = np.mean(vectors, axis=0)
# 将向量填充或截断到固定长度 max_length
if len(avg_vector) < max_length:
avg_vector = np.pad(avg_vector, ((0, max_length - len(avg_vector)),), 'constant')
else:
avg_vector = avg_vector[:max_length]
return avg_vector.reshape((max_length, 1)) # 返回 (1291, 1) 的形状
else:
# 如果文本中所有词都不在词汇表中,可以返回一个默认向量或全零向量
return np.zeros((max_length, 1))
def preprocess_input_text(text):
global wv
# 分词
seg_list = jieba.lcut(text)
# 去除停用词和非中文字符
seg_list = [token for token in seg_list if token not in stop_words and re.match(r'^[\u4e00-\u9fa5]+$', token)]
processed_text = ' '.join(seg_list)
return word2vec_transform2(processed_text, wv)
def load_my_model():
try:
return load_model('my_model.keras')
except Exception as e:
print("Failed to load model:", str(e))
return None
model = load_my_model()
label_map = {0: '差评', 1: '好评'}
def predict_sentiment(text):
global model
if model is None:
raise Exception("Model loading failed.")
try:
X_input = preprocess_input_text(text)
X_input = np.expand_dims(X_input, axis=0)
y_pred_prob = model.predict(X_input)
print("Prediction probabilities:", X_input)
print("Prediction probabilities:", y_pred_prob) # Print prediction probabilities
y_pred = int(y_pred_prob[0] > 0.5) # Convert boolean to integer (0 or 1)
sentiment_label = label_map[y_pred]
return sentiment_label
except Exception as e:
print("Prediction error:", str(e))
return None
if __name__ == '__main__':
while True:
comment = input("请输入评论文本 (输入 'exit' 退出): ")
if comment.lower() == 'exit':
break
try:
sentiment_label = predict_sentiment(comment)
if sentiment_label is None:
print("无法预测情感")
else:
print("情感预测结果:", sentiment_label)
except Exception as e:
print(f'Prediction error: {str(e)}')
六、总结
第一、非常重要,文本处理时一定要记得调用W2v模型
第二、记得保持维度一致,就是出现的max-length不然会出现维度不一致的报错
第三、一定要记住保存模型,不然等于白干了
第四、不要一报错就开始喂给GPT,自己检查检查输出输出x,y的值,看看哪里出错了,一般就是x,y值错了,和纬度的问题,GPT的回答就相当于教科书般地回答,你也不可能像教科书一样犯错。
第五、that is all thank you for looking my first prograss.
标签:text,test,Pytorch,vector,max,CNN,Tensorflow,model,avg From: https://blog.csdn.net/weixin_73773376/article/details/140189961