首页 > 其他分享 >基于CNN的蒙牛评论情感分析(用的Tensorflow,因为不会Pytorch)

基于CNN的蒙牛评论情感分析(用的Tensorflow,因为不会Pytorch)

时间:2024-07-04 22:56:11浏览次数:3  
标签:text test Pytorch vector max CNN Tensorflow model avg

目录

一、数据来源

二、导相应入的库

  三、数据预处理

四、模型的构建

五、预测函数

六、总结


一、数据来源

  蒙牛评论数据集:共有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

相关文章

  • 基于PSO粒子群优化的CNN-LSTM的时间序列回归预测matlab仿真
    1.算法运行效果图预览  2.算法运行软件版本matlab2022a 3.部分核心程序fori=1:Iteriforj=1:Npeoprng(i+j)iffunc_obj(x1(j,:))<pbest1(j)p1(j,:)=x1(j,:);%变量pbest1(j)=func_obj(x1(j,:));......
  • 基于卷积神经网络的交通标志识别系统(通过TensorFlow构建LeNet-5模型,并使用GTSRB德国交
    完成程序下载点此下载1、资源项目源码均已通过严格测试验证,保证能够正常运行;2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通;3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业......
  • TensorFlow中numpy与tensor数据相互转化(支持tf1.x-tf2.x)
    TensorFlow中numpy与tensor数据相互转化(支持tf1.x-tf2.x)TF1.x版本有时候解决起来很简单,就是错误比较难找到,所以我推荐的方法为将数据进行显式的转化。Numpy2Tensor虽然TensorFlow网络在输入Numpy数据时会自动转换为Tensor来处理,但是我们自己也可以去显式的转换:data_tensor......
  • 基于卷积神经网络的交通标志识别系统(通过TensorFlow构建LeNet-5模型,并使用GTSRB德国交
    完成程序下载点此下载1、资源项目源码均已通过严格测试验证,保证能够正常运行;2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通;3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业......
  • 如何处理TensorFlow中的InvalidArgumentError:数据类型不匹配
    如何处理TensorFlow中的InvalidArgumentError:数据类型不匹配......
  • pytorch实现:PINN 模拟抛射运动(基于时间)
    pytorch实现:PINN模拟抛射运动(基于时间)1.抛射运动(基于时间)2.理想和现实的差异2.1.理想完美情况2.2.实际不完美数据2.2.1.过拟合2.2.2正则化3.物理信息神经网络4.代码实现5.结果展示1.抛射运动(基于时间)将问题置于抛射运动场景,在处于自由落体运动中的抛射......
  • 在Ubuntu上用Docker轻松实现GPU加速的TensorFlow
    前言在深度学习和机器学习的世界中,GPU的使用可以显著加速模型训练和推理的速度。NVIDIAContainerToolkit允许我们在Docker容器中使用NVIDIAGPU,从而简化了在GPU上运行TensorFlow等深度学习框架的过程。本文将详细介绍如何在Ubuntu上配置NVIDIAContainerToolkit并运行GP......
  • 适用于PyTorch 2.0.0的Ubuntu 22.04上CUDA v11.8和cuDNN 8.7安装指南
    将下面内容保存为install.bash,直接用shell执行一把梭解决#!/bin/bash###steps#####verifythesystemhasacuda-capablegpu#downloadandinstallthenvidiacudatoolkitandcudnn#setupenvironmentalvariables#verifytheinstallation######toverify......
  • 工地安全着装识别系统 CNN
    工地安全着装识别系统依据很多工作服图片信息数据训练识别模型,工地安全着装识别系统对现场视频监控画面实时分析,工地安全着装识别系统利用视频监控机器学习算法判断工地作业人员着装、工作服颜色识别;工地安全着装识别系统识别到违规信息后系统马上把违规图片、违规视频等信息发......
  • 在使用基于Pytorch的DeeplabV3+模型(Bubbliiiing)训练以及预测时遇到的问题
    原博:憨批的语义分割重制版9——Pytorch搭建自己的DeeplabV3+语义分割平台-CSDN博客github:https://github.com/bubbliiiing/deeplabv3-plus-pytorch最近在使用Bubbliiing的deeplabv3+模型对自己的数据集进行训练时,使用博主提供的json_to_dataset.py对labelme标注的数据进行......