🤵♂️ 个人主页:@艾派森的个人主页
✍🏻作者简介:Python学习者
🐋 希望大家多多支持,我们一起进步!😄
如果文章对你有帮助的话,
欢迎评论 💬点赞👍🏻 收藏 📂加关注+
喜欢大数据分析项目的小伙伴,希望可以多多支持该系列的其他文章
大数据分析案例-基于随机森林算法预测人类预期寿命 |
大数据分析案例-基于随机森林算法的商品评价情感分析 |
大数据分析案例-用RFM模型对客户价值分析(聚类) |
大数据分析案例-对电信客户流失分析预警预测 |
大数据分析案例-基于随机森林模型对北京房价进行预测 |
大数据分析案例-基于RFM模型对电商客户价值分析 |
大数据分析案例-基于逻辑回归算法构建垃圾邮件分类器模型 |
大数据分析案例-基于决策树算法构建员工离职预测模型 |
大数据分析案例-基于KNN算法对茅台股票进行预测 |
大数据分析案例-基于多元线性回归算法构建广告投放收益模型 |
大数据分析案例-基于随机森林算法构建返乡人群预测模型 |
大数据分析案例-基于决策树算法构建金融反欺诈分类模型 |
目录
1.项目背景
2.项目简介
2.1项目说明
2.2数据说明
2.3技术工具
3.算法原理
4.项目实施步骤
4.1理解数据
4.2数据预处理
4.3探索性数据分析
4.4特征工程
4.5模型构建
4.6模型评估
4.7模型预测
5.实验总结
源代码
1.项目背景
近年来,随着社交媒体的迅速发展和普及,人们越来越倾向于在平台上分享自己的情感和经历。推文,作为社交媒体中最为常见和直接的表达方式之一,不仅反映了用户的日常生活状态,还蕴含着丰富的情感信息。在这些海量信息中,有一部分内容涉及了用户的心理健康状况,尤其是抑郁症等心理疾病的讨论。然而,由于抑郁症的隐蔽性和复杂性,许多患者往往无法及时得到专业的诊断和治疗,导致病情恶化,甚至引发严重的后果。
因此,开发一种能够自动识别和预测抑郁症的推文识别模型,对于提高抑郁症的识别率、促进患者及时就医以及预防潜在的心理健康问题具有重要的现实意义和广泛的应用前景。
逻辑回归算法作为一种经典的分类算法,在文本分类领域有着广泛的应用。它通过将线性回归的输出结果通过Sigmoid函数转换为概率值,实现了对文本的二分类预测。逻辑回归算法具有模型简单、计算效率高、易于理解和实现等优点,特别适合于处理大规模的文本数据。
在构建抑郁非抑郁推文识别模型时,逻辑回归算法可以通过分析推文中的词汇、语法、语义等特征,提取出与抑郁症相关的关键信息,并基于这些信息对推文进行分类。具体来说,我们可以将推文中的词汇作为特征,利用词频、TF-IDF等统计方法计算每个词汇在推文中的权重,然后将其作为逻辑回归模型的输入。通过对大量标注好的抑郁和非抑郁推文进行训练,模型可以学习到这些特征与分类结果之间的映射关系,从而实现对新推文的自动分类和预测。
2.项目简介
2.1项目说明
本项目基于逻辑回归算法构建抑郁非抑郁推文识别模型具有重要的研究背景和应用价值。通过该模型的研究和应用,我们可以更好地理解和预测社交媒体中用户的心理健康状况,为抑郁症等心理疾病的防治提供有力的支持。
2.2数据说明
本数据集来源于Kaggle,该数据集是2019 年 12 月至 2020 年 12 月期间的抑郁/非抑郁推文主要来自印度和印度次大陆的部分地区。原始数据集共有134348条,2个变量。分别为
text:推文文本内容。
sentiment:0表示非抑郁,1表示抑郁。
2.3技术工具
Python版本:3.9
代码编辑器:jupyter notebook
3.算法原理
1.逻辑回归
逻辑回归就是这样的一个过程:面对一个回归或者分类问题,建立代价函数,然后通过优化方法迭代求解出最优的模型参数,然后测试验证我们这个求解的模型的好坏。
Logistic回归虽然名字里带“回归”,但是它实际上是一种分类方法,主要用于两分类问题(即输出只有两种,分别代表两个类别)
回归模型中,y是一个定性变量,比如y=0或1,logistic方法主要应用于研究某些事件发生的概率
2. 逻辑回归的优缺点
优点:
1)速度快,适合二分类问题
2)简单易于理解,直接看到各个特征的权重
3)能容易地更新模型吸收新的数据
缺点:
对数据和场景的适应能力有局限性,不如决策树算法适应性那么强
3. 逻辑回归和多重线性回归的区别
Logistic回归与多重线性回归实际上有很多相同之处,最大的区别就在于它们的因变量不同,其他的基本都差不多。正是因为如此,这两种回归可以归于同一个家族,即广义线性模型(generalizedlinear model)。
这一家族中的模型形式基本上都差不多,不同的就是因变量不同。这一家族中的模型形式基本上都差不多,不同的就是因变量不同。
如果是连续的,就是多重线性回归
如果是二项分布,就是Logistic回归
如果是Poisson分布,就是Poisson回归
如果是负二项分布,就是负二项回归
4. 逻辑回归用途
寻找危险因素:寻找某一疾病的危险因素等;
预测:根据模型,预测在不同的自变量情况下,发生某病或某种情况的概率有多大;
判别:实际上跟预测有些类似,也是根据模型,判断某人属于某病或属于某种情况的概率有多大,也就是看一下这个人有多大的可能性是属于某病。
5. Regression 常规步骤
寻找h函数(即预测函数)
构造J函数(损失函数)
想办法使得J函数最小并求得回归参数(θ)
6. 构造预测函数h(x)
1) Logistic函数(或称为Sigmoid函数),函数形式为:
对于线性边界的情况,边界形式如下:
其中,训练数据为向量
最佳参数
构造预测函数为:
函数h(x)的值有特殊的含义,它表示结果取1的概率,因此对于输入x分类结果为类别1和类别0的概率分别为:
P(y=1│x;θ)=h_θ (x) P(y=0│x;θ)=1-h_θ (x)
4.项目实施步骤
4.1理解数据
导入数据
查看数据大小
查看数据基本信息
4.2数据预处理
统计数据缺失值情况
可以发现数据集中有18个缺失值
统计数据集中的重复值
可以发现数据集中有10331个重复值
过滤文本长度小于20的数据,将长度小于20的数据设置为空值
可以发现共有4216条数据文本长度小于20
删除缺失值和重复值
4.3探索性数据分析
4.4特征工程
文本预处理
4.5模型构建
准备建模数据,并拆分数据集为训练集和测试集,其中测试集比例为0.2
构建逻辑回归模型
构建决策树模型
构建xgboost模型
从构建的三个模型可以看出,逻辑回归模型的准确率最高为91%,故我们最终选取其作为最终训练模型。
4.6模型评估
4.7模型预测
随机抽取10个预测结果与真实值进行对比,可以发现10个中只有1个预测错误,说明模型效果不错
5.实验总结
在本次实验中,我们探索了使用不同的机器学习算法——逻辑回归、决策树和XGBoost——来构建抑郁非抑郁推文识别模型。经过严格的模型训练和验证过程,我们对比了三种模型的性能,并发现逻辑回归模型在准确率上达到了91%,超过了决策树和XGBoost模型。因此,我们最终选择了逻辑回归模型作为本次实验的最终模型。
逻辑回归模型在本次实验中的高准确率表明,该模型能够有效地从推文中提取出与抑郁症相关的特征,并基于这些特征对推文进行准确的分类。这一结果证明了逻辑回归算法在文本分类任务中的有效性,尤其是在处理与情感分析相关的文本数据时。
尽管决策树和XGBoost模型在某些情况下可能表现出色,但在本次实验的特定数据集和任务中,逻辑回归模型展现出了更好的性能。这可能与推文数据的特性有关,如文本长度、词汇多样性以及情感表达的复杂性等。逻辑回归模型能够较好地处理这些特性,并准确地识别出与抑郁症相关的推文。
综上所述,我们得出结论:在本次实验中,逻辑回归模型是构建抑郁非抑郁推文识别模型的最佳选择。该模型不仅具有较高的准确率,而且易于理解和实现,具有广泛的应用前景。未来,我们将进一步探索逻辑回归模型在抑郁症识别领域的应用,并尝试结合其他先进技术来提高模型的性能和泛化能力。
心得与体会:
通过这次Python项目实战,我学到了许多新的知识,这是一个让我把书本上的理论知识运用于实践中的好机会。原先,学的时候感叹学的资料太难懂,此刻想来,有些其实并不难,关键在于理解。
在这次实战中还锻炼了我其他方面的潜力,提高了我的综合素质。首先,它锻炼了我做项目的潜力,提高了独立思考问题、自我动手操作的潜力,在工作的过程中,复习了以前学习过的知识,并掌握了一些应用知识的技巧等
在此次实战中,我还学会了下面几点工作学习心态:
1)继续学习,不断提升理论涵养。在信息时代,学习是不断地汲取新信息,获得事业进步的动力。作为一名青年学子更就应把学习作为持续工作用心性的重要途径。走上工作岗位后,我会用心响应单位号召,结合工作实际,不断学习理论、业务知识和社会知识,用先进的理论武装头脑,用精良的业务知识提升潜力,以广博的社会知识拓展视野。
2)努力实践,自觉进行主角转化。只有将理论付诸于实践才能实现理论自身的价值,也只有将理论付诸于实践才能使理论得以检验。同样,一个人的价值也是透过实践活动来实现的,也只有透过实践才能锻炼人的品质,彰显人的意志。
3)提高工作用心性和主动性。实习,是开端也是结束。展此刻自我面前的是一片任自我驰骋的沃土,也分明感受到了沉甸甸的职责。在今后的工作和生活中,我将继续学习,深入实践,不断提升自我,努力创造业绩,继续创造更多的价值。
这次Python实战不仅仅使我学到了知识,丰富了经验。也帮忙我缩小了实践和理论的差距。在未来的工作中我会把学到的理论知识和实践经验不断的应用到实际工作中,为实现理想而努力。
源代码
import pandas as pd
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')
plt.style.use('fivethirtyeight')
df = pd.read_csv("clean_tweet_Dec19ToDec20.csv")
df.head()
df.shape
df.info()
df.isnull().sum()
df.duplicated().sum()
# 过滤文本长度小于20的数据
df['text'] = df['text'].apply(lambda x:x if len(str(x))>20 else None)
df.isnull().sum()
df.dropna(inplace=True)
df.drop_duplicates(inplace=True)
df["sentiment"].value_counts().plot(kind="bar",figsize=(8, 4))
plt.title('Distribution of classes')
plt.show()
# 可视化抑郁和非抑郁推文的比例
sentiment_counts = df['sentiment'].value_counts()
plt.figure(figsize=(8, 8))
plt.pie(sentiment_counts, labels=['Non-Depressive', 'Depressive'], autopct='%1.2f%%', startangle=140)
plt.title('Proportion of Depressive vs. Non-Depressive Tweets')
plt.axis('equal')
plt.show()
from wordcloud import WordCloud
depressive_tweets = df[df['sentiment'] == 1]['text'].dropna().str.cat(sep=' ')
non_depressive_tweets = df[df['sentiment'] == 0]['text'].dropna().str.cat(sep=' ')
depressive_wordcloud = WordCloud(width=800, height=400, background_color='white').generate(depressive_tweets)
non_depressive_wordcloud = WordCloud(width=800, height=400, background_color='white').generate(non_depressive_tweets)
plt.figure(figsize=(14, 7))
plt.subplot(1, 2, 1)
plt.imshow(depressive_wordcloud, interpolation='bilinear')
plt.title('Word Cloud for Depressive Tweets')
plt.axis('off')
plt.subplot(1, 2, 2)
plt.imshow(non_depressive_wordcloud, interpolation='bilinear')
plt.title('Word Cloud for Non-Depressive Tweets')
plt.axis('off')
plt.show()
文本预处理
# 删除HTML标记和特殊字符
import re
from nltk.corpus import stopwords
import nltk
import string
def clean_text_part1(df, column_name):
df = df.copy()
df[column_name] = df[column_name].apply(lambda x: re.sub(r'<.*?>', '', x))
df[column_name] = df[column_name].apply(lambda x: re.sub(r"(@\[A-Za-z0-9]+)|([^0-9A-Za-z \t])|(\w+:\/\/\S+)|^rt|http.+?", "", x))
return df
def clean_text_part2(df, column_name):
df[column_name] = df[column_name].str.lower()
df[column_name] = df[column_name].apply(nltk.word_tokenize)
stop_words = set(stopwords.words('english'))
df[column_name] = df[column_name].apply(lambda tokens: [token for token in tokens if token not in stop_words])# stopwords
df[column_name] = df[column_name].apply(lambda tokens: [token for token in tokens if token not in string.punctuation])# punctuation
df[column_name] = df[column_name].apply(' '.join)
return df
part_one = clean_text_part1(df,'text')
part_tow = clean_text_part2(part_one, 'text')
part_tow.head(3)
def text_properties(df):
df = df.copy()
df['num_characters']= df['text'].apply(len)
df['text'].apply(lambda x: nltk.word_tokenize(x))
df['num_words']= df['text'].apply(lambda x:len(nltk.word_tokenize(x)))
return df
df_prop = text_properties(part_tow)
df_prop.head()
import seaborn as sns
df_filtered = df_prop[df_prop['num_characters'] != 0]
sns.set_theme(rc={'figure.figsize':(12,8)})
sns.boxplot(data=df_filtered, x="sentiment", y="num_words")
plt.title(' Word Distribution for each class',fontsize=22)
plt.xlabel('labels')
plt.ylabel('Count')
plt.show()
sns.set_theme(rc={'figure.figsize':(12,6)})
sns.set_palette("bright")
sns.histplot(df_filtered, x='num_characters',hue='sentiment' ,bins=50, kde=True)
plt.title('Text characters Distribution',fontsize=22)
plt.xlabel('characters')
plt.ylabel('Count')
plt.show()
unique_classes = df_filtered['sentiment'].unique()
num_rows = 1
num_cols = 2
fig, axes = plt.subplots(num_rows, num_cols, figsize=(12, 4))
for i, label in enumerate(unique_classes):
texts_for_class = df_filtered[df_filtered['sentiment'] == label]['text']
all_text_for_class = ' '.join(texts_for_class)
wordcloud = WordCloud(background_color='white').generate(all_text_for_class)
axes[i].imshow(wordcloud, interpolation='bilinear')
axes[i].set_title(label)
axes[i].axis('off')
plt.tight_layout()
plt.suptitle('Most frequent words for each class', fontsize=20)
plt.show()
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
vectorizer = CountVectorizer(stop_words='english', max_features=20)
num_rows = 1
num_cols = 2
fig, axes = plt.subplots(num_rows, num_cols, figsize=(12, 4))
for i, label in enumerate(unique_classes):
texts_for_class = df_filtered[df_filtered['sentiment'] == label]['text']
word_counts = vectorizer.fit_transform(texts_for_class)
top_words = pd.DataFrame(word_counts.sum(axis=0), columns=vectorizer.get_feature_names_out())
top_words = top_words.transpose().sort_values(0, ascending=False).head(10)
top_words.plot(kind='bar', ax=axes[i], legend=False)
axes[i].set_title(label)
axes[i].set_ylabel('Frequency')
axes[i].tick_params(axis='x', rotation=40)
plt.tight_layout()
plt.suptitle('Most 10 frequent words for each category', fontsize=13)
plt.show()
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.model_selection import train_test_split
vectorizer = TfidfVectorizer()
X = vectorizer.fit_transform(df['text'])
y = df['sentiment']
X_train,X_test,y_train,y_test = train_test_split(X,y,test_size=0.2,random_state=42)
# 构建逻辑回归模型
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression()
lr.fit(X_train,y_train)
print('逻辑回归模型准确率:',lr.score(X_test,y_test))
# 构建决策树模型
from sklearn.tree import DecisionTreeClassifier
tree = DecisionTreeClassifier()
tree.fit(X_train,y_train)
print('决策树模型准确率:',tree.score(X_test,y_test))
# 构建xgboost模型
from xgboost import XGBClassifier
xgb = XGBClassifier()
xgb.fit(X_train,y_train)
print('xgboost模型准确率:',xgb.score(X_test,y_test))
from sklearn.metrics import f1_score,r2_score,confusion_matrix,classification_report,auc,roc_curve
# 模型评估
y_pred = lr.predict(X_test)
print('模型的F1值:',f1_score(y_test,y_pred))
print('模型的R方值:',r2_score(y_test,y_pred))
print('模型混淆矩阵:','\n',confusion_matrix(y_test,y_pred))
print('模型分类报告:','\n',classification_report(y_test,y_pred))
# 画出ROC曲线
y_prob = lr.predict_proba(X_test)[:,1]
false_positive_rate, true_positive_rate, thresholds = roc_curve(y_test, y_prob)
roc = auc(false_positive_rate, true_positive_rate)
plt.figure(figsize=(8,8))
plt.title('ROC')
plt.plot(false_positive_rate,true_positive_rate, color='red',label = 'AUC = %0.2f' % roc)
plt.legend(loc = 'lower right')
plt.plot([0, 1], [0, 1],linestyle='--')
plt.axis('tight')
plt.ylabel('True Positive Rate')
plt.xlabel('False Positive Rate')
plt.show()
# 模型预测
res = pd.DataFrame()
res['真实值'] = y_test
res['预测值'] = y_pred
res.sample(10)