使用scikit - learn进行文本和多类分类
在机器学习领域,分类是一个重要的任务,有多种方法可以实现。本文将介绍几种使用scikit - learn库进行分类的方法,包括线性判别分析(LDA)、二次判别分析(QDA)、随机梯度下降(SGD)、朴素贝叶斯分类以及半监督学习中的标签传播。
1. 使用LDA进行分类
线性判别分析(LDA)试图拟合特征的线性组合来预测结果变量,常作为预处理步骤。
准备工作
- 安装支持最新股票读取器的pandas版本,在Anaconda命令行输入:
conda install -c anaconda pandas - datareader
-
打开笔记本,检查
pandas - datareader是否正确导入:
from pandas_datareader import data
操作步骤
-
数据获取与准备
- 导入必要的库,存储要使用的股票代码、数据的起始日期和结束日期:
%matplotlib inline
from pandas_datareader import data
import pandas as pd
tickers = ["F", "TM", "GM", "TSLA"]
first_date = '2009 - 01 - 01'
last_date = '2016 - 12 - 31'
- 拉取股票数据:
stock_panel = data.DataReader(tickers, 'google', first_date, last_date)
- 查看收盘价数据:
stock_df = stock_panel.Close.dropna()
stock_df.plot(figsize=(12, 5))
- 比较每只股票当前价格与六个月后的价格,若更高则标记为1,否则标记为0:
classes = (stock_df.shift(-180) > stock_df).astype(int)
- 扁平化数据集:
X = stock_panel.to_frame()
classes = classes.unstack()
classes = classes.swaplevel(0, 1).sort_index()
classes = classes.to_frame()
classes.index.names = ['Date', 'minor']
data = X.join(classes).dropna()
data.rename(columns={0: 'is_higher'}, inplace=True)
- 使用`patsy`库创建NumPy矩阵:
import patsy
X = patsy.dmatrix("Open + High + Low + Close + Volume + is_higher - 1", data.reset_index(), return_type='dataframe')
- 拟合LDA模型
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
lda = LDA()
lda.fit(X.iloc[:, :-1], X.iloc[:, -1])
- 评估模型
from sklearn.metrics import classification_report
print(classification_report(X.iloc[:, -1].values, lda.predict(X.iloc[:, :-1])))
评估指标解释
| 指标 | 含义 |
|---|---|
| 精确率(precision) | 模型预测为正例时,实际为正例的比例 |
| 召回率(recall) | 实际为某一类时,被模型正确选择的比例 |
| F1分数(f1 - score) | 尝试总结召回率和精确率之间的关系 |
工作原理
LDA与聚类类似,先从数据中拟合基本模型,然后预测并比较每个类中数据的似然性,选择更可能的选项。它是二次判别分析(QDA)的简化,假设每个类的协方差相同。
2. 使用QDA(非线性LDA)
QDA是二次回归等常见技术的推广,允许更复杂的模型拟合。
准备工作
在之前LDA的基础上,放松对模型协方差的假设。
操作步骤
from sklearn.discriminant_analysis import QuadraticDiscriminantAnalysis as QDA
qda = QDA()
qda.fit(X.iloc[:, :-1], X.iloc[:, -1])
predictions = qda.predict(X.iloc[:, :-1])
from sklearn.metrics import classification_report
print(classification_report(X.iloc[:, -1].values, predictions))
工作原理
假设收盘价服从对数正态分布,通过交叉验证创建训练集和测试集,计算每个类的似然性,然后比较并分配类。
from sklearn.model_selection import ShuffleSplit
import scipy.stats as sp
shuffle_split_inst = ShuffleSplit()
for test, train in shuffle_split_inst.split(X):
train_set = X.iloc[train]
train_close = train_set.Close
train_0 = train_close[~train_set.is_higher.astype(bool)]
train_1 = train_close[train_set.is_higher.astype(bool)]
test_set = X.iloc[test]
test_close = test_set.Close.values
ll_0 = sp.norm.pdf(test_close, train_0.mean())
ll_1 = sp.norm.pdf(test_close, train_1.mean())
(ll_0 > ll_1).mean()
3. 使用SGD进行分类
随机梯度下降(SGD)是用于拟合回归模型的基本技术,在分类和回归中有自然联系。
准备工作
在回归中最小化连续尺度上惩罚错误选择的成本函数,在分类中最小化惩罚两种(或更多)情况的成本函数。
操作步骤
- 创建数据
from sklearn import datasets
X, y = datasets.make_classification(n_samples = 500)
- 划分训练集和测试集
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=y)
- 实例化并训练分类器
from sklearn import linear_model
sgd_clf = linear_model.SGDClassifier()
sgd_clf.fit(X_train, y_train)
- 评估性能
from sklearn.metrics import accuracy_score
accuracy_score(y_test, sgd_clf.predict(X_test))
4. 使用朴素贝叶斯进行文档分类
朴素贝叶斯是一种有趣的模型,虽有一些简化假设,但在很多情况下表现良好。
准备工作
使用
sklearn
中的
newgroups
数据集,将文档表示为词袋模型。
import numpy as np
from sklearn.datasets import fetch_20newsgroups
categories = ["rec.autos", "rec.motorcycles"]
newgroups = fetch_20newsgroups(categories=categories)
from sklearn.feature_extraction.text import CountVectorizer
count_vec = CountVectorizer()
bow = count_vec.fit_transform(newgroups.data)
bow = np.array(bow.todense())
words = np.array(count_vec.get_feature_names())
操作步骤
- 划分数据集
X = bow
y = newgroups.target
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.5, stratify=y)
- 训练模型
from sklearn import naive_bayes
clf = naive_bayes.GaussianNB().fit(X_train, y_train)
- 评估模型
from sklearn.metrics import accuracy_score
accuracy_score(y_test, clf.predict(X_test))
工作原理
朴素贝叶斯的基本思想是根据特征向量估计数据点属于某一类的概率,通过贝叶斯公式得到最大后验(MAP)估计,选择特征向量概率最大的类。
多类分类扩展
可以使用多项式似然扩展朴素贝叶斯进行多类分类。
from sklearn.datasets import fetch_20newsgroups
mn_categories = ["rec.autos", "rec.motorcycles", "talk.politics.guns"]
mn_newgroups = fetch_20newsgroups(categories=mn_categories)
mn_bow = count_vec.fit_transform(mn_newgroups.data)
mn_bow = np.array(mn_bow.todense())
X = mn_bow
y = mn_newgroups.target
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.5, stratify=y)
from sklearn.naive_bayes import MultinomialNB
clf = MultinomialNB().fit(X_train, y_train)
from sklearn.metrics import accuracy_score
accuracy_score(y_test, clf.predict(X_test))
5. 半监督学习中的标签传播
标签传播是一种半监督技术,利用有标签和无标签的数据来学习无标签数据的标签。
准备工作
处理半监督或删失数据时,需要进行一些数据预处理。
操作步骤
- 数据准备
from sklearn import datasets
d = datasets.load_iris()
X = d.data.copy()
y = d.target.copy()
names = d.target_names.copy()
names = np.append(names, ['unlabeled'])
y[np.random.choice([True, False], len(y))] = -1
- 使用标签传播方法预测标签
from sklearn import semi_supervised
lp = semi_supervised.LabelPropagation()
lp.fit(X, y)
- 评估准确率
preds = lp.predict(X)
(preds == d.target).mean()
通过以上几种方法,我们可以在不同的场景下进行有效的分类任务。每种方法都有其特点和适用范围,在实际应用中需要根据具体情况选择合适的方法。
使用scikit - learn进行文本和多类分类
6. 方法总结与对比
为了更清晰地了解上述几种分类方法的特点和适用场景,我们可以通过以下表格进行总结对比:
| 方法 | 特点 | 适用场景 | 操作复杂度 |
| ---- | ---- | ---- | ---- |
| LDA | 假设各类协方差相同,线性模型,可用于降维 | 数据近似线性可分,需要预处理的场景 | 中等 |
| QDA | 放松协方差假设,可拟合更复杂模型 | 数据非线性,需要更复杂模型拟合的场景 | 中等 |
| SGD | 基本的优化技术,适用于大规模数据 | 大规模数据集的分类或回归问题 | 低 |
| 朴素贝叶斯 | 基于概率估计,假设特征条件独立 | 文本分类、垃圾邮件过滤等 | 低 |
| 标签传播 | 半监督学习,利用有标签和无标签数据 | 标签数据获取成本高的场景 | 中等 |
7. 实际应用中的考虑因素
在实际应用中,选择合适的分类方法需要考虑多个因素,下面是一个简单的决策流程图:
graph LR
A[数据规模] --> B{小规模数据}
A --> C{大规模数据}
B --> D{线性可分}
B --> E{非线性}
D --> F[LDA]
E --> G[QDA]
C --> H{文本数据}
C --> I{非文本数据}
H --> J[朴素贝叶斯]
I --> K{标签数据充足}
I --> L{标签数据不足}
K --> M[SGD]
L --> N[标签传播]
8. 优化与改进建议
- LDA和QDA :可以尝试不同的参数设置,如正则化参数,以提高模型的泛化能力。同时,可以结合其他特征选择方法,减少不必要的特征,提高模型的效率。
- SGD :调整学习率、批量大小等参数,避免模型陷入局部最优解。可以使用不同的损失函数,如hinge损失、log损失等,以适应不同的分类任务。
- 朴素贝叶斯 :对于文本数据,可以进行更复杂的预处理,如去除停用词、词干提取等,以提高特征的质量。同时,可以尝试不同的先验概率估计方法,如拉普拉斯平滑。
- 标签传播 :调整核函数、邻居数量等参数,以优化模型的性能。可以结合主动学习方法,选择最有价值的无标签数据进行标注,提高模型的效率。
9. 代码优化示例
以下是对上述部分代码的优化示例,以提高代码的可读性和性能:
LDA优化
# 导入必要的库
import pandas as pd
from pandas_datareader import data
import patsy
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis as LDA
from sklearn.metrics import classification_report
# 数据获取与准备
tickers = ["F", "TM", "GM", "TSLA"]
first_date = '2009-01-01'
last_date = '2016-12-31'
stock_panel = data.DataReader(tickers, 'google', first_date, last_date)
stock_df = stock_panel.Close.dropna()
classes = (stock_df.shift(-180) > stock_df).astype(int)
X = stock_panel.to_frame()
classes = classes.unstack()
classes = classes.swaplevel(0, 1).sort_index()
classes = classes.to_frame()
classes.index.names = ['Date', 'minor']
data = X.join(classes).dropna()
data.rename(columns={0: 'is_higher'}, inplace=True)
X = patsy.dmatrix("Open + High + Low + Close + Volume + is_higher - 1", data.reset_index(), return_type='dataframe')
# 拟合LDA模型
lda = LDA()
lda.fit(X.iloc[:, :-1], X.iloc[:, -1])
# 评估模型
print(classification_report(X.iloc[:, -1].values, lda.predict(X.iloc[:, :-1])))
朴素贝叶斯优化
import numpy as np
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.model_selection import train_test_split
from sklearn.naive_bayes import GaussianNB, MultinomialNB
from sklearn.metrics import accuracy_score
# 数据获取与预处理
categories = ["rec.autos", "rec.motorcycles"]
newgroups = fetch_20newsgroups(categories=categories)
count_vec = CountVectorizer()
bow = count_vec.fit_transform(newgroups.data)
bow = np.array(bow.todense())
words = np.array(count_vec.get_feature_names())
# 划分数据集
X = bow
y = newgroups.target
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.5, stratify=y)
# 训练高斯朴素贝叶斯模型
clf_gaussian = GaussianNB().fit(X_train, y_train)
print("高斯朴素贝叶斯准确率:", accuracy_score(y_test, clf_gaussian.predict(X_test)))
# 多类分类扩展
mn_categories = ["rec.autos", "rec.motorcycles", "talk.politics.guns"]
mn_newgroups = fetch_20newsgroups(categories=mn_categories)
mn_bow = count_vec.fit_transform(mn_newgroups.data)
mn_bow = np.array(mn_bow.todense())
X_mn = mn_bow
y_mn = mn_newgroups.target
X_train_mn, X_test_mn, y_train_mn, y_test_mn = train_test_split(X_mn, y_mn, test_size = 0.5, stratify=y_mn)
clf_multinomial = MultinomialNB().fit(X_train_mn, y_train_mn)
print("多项式朴素贝叶斯准确率:", accuracy_score(y_test_mn, clf_multinomial.predict(X_test_mn)))
10. 总结
本文介绍了使用scikit - learn进行文本和多类分类的几种常见方法,包括LDA、QDA、SGD、朴素贝叶斯和标签传播。每种方法都有其独特的特点和适用场景,在实际应用中需要根据数据的特点、任务的需求以及资源的限制来选择合适的方法。同时,通过优化代码和调整参数,可以进一步提高模型的性能和效率。希望本文能够帮助读者更好地理解和应用这些分类方法,解决实际中的分类问题。
在未来的研究和应用中,我们可以继续探索这些方法的改进和扩展,结合深度学习等其他技术,以应对更加复杂和多样化的分类任务。同时,随着数据量的不断增加和计算能力的提升,我们可以尝试处理更大规模的数据集,挖掘更多有价值的信息。
超级会员免费看
300

被折叠的 条评论
为什么被折叠?



