数据集划分:train_test_split()
测试集一般占数据集20%-30%
训练集特征值,测试集特征值,训练集目标值,测试集目标值:x_train,x_test,y_train,y_test
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
def dataset_demo():
iris = load_iris()
#数据集划分
#train_test_split(特征值,目标值,测试集比例(默认0.25),随机数种子)
x_train,x_test,y_train,y_test = train_test_split(iris.data,iris.target,test_size=0.2,random_state=22)
if __name__ == '__main__':
dataset_demo()
特征工程(Feature Engineering)
数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。
pandas:数据清洗、数据处理
sklearn:特征工程
特征提取:将任意数据(如文本或图像)转换为可用于机器学习的数字特征
特征抽取
字典特征提取
sklearn.feature_extraction.DictVectorizer(sparse=True,…)
DictVectorizer.fit_transform(X)
- X:字典或者包含字典的迭代器返回值:返回sparse矩阵
DictVectorizer.inverse_transform(X)
- X:array数组或者sparse矩阵 返回值:转换之前数据格式
DictVectorizer.get_feature_names_out()
- 返回特征类别名称
![稀疏矩阵:将非零值用坐标表现出来,节省内存空间](https://i-blog.csdnimg.cn/blog_migrate/0579f0d2effb8a5adb8b18e0b6166af9.png)
类别特征可以用one-hot编码来处理
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
def dict_demo():
data = [{'city': '北京','temperature':100},{'city': '上海','temperature':60},{'city': '深圳','temperature':30}]
#1.实例化一个转换器类
transfer = DictVectorizer(sparse=False)
#调用fit_transform()
data_new = transfer.fit_transform(data)
print('data_new:\n',data_new)
print('特征类别:\n',transfer.get_feature_names_out())
if __name__ == '__main__':
dict_demo()
![](https://i-blog.csdnimg.cn/blog_migrate/ea078f38135b088145759df4e805add4.png)
文本特征提取
单词作为特征,统计每个样本特征值出现的次数
sklearn.feature_extraction.text.CountVectorizer(stop_words=[ ])
- 返回词频矩阵
- stopword里输入不需要参与统计(没有实际意义的)的词
CountVectorizer.fit_transform(X)
- X:文本或者包含文本字符串的可迭代对象 返回值:返回sparse矩阵
CountVectorizer.inverse_transform(X)
- X:array数组或者sparse矩阵 返回值:转换之前数据格
CountVectorizer.get_feature_names()
- 返回值:单词列表
利用toarray()进行sparse矩阵转换array数组
from sklearn.feature_extraction.text import CountVectorizer
def count_demo():
data = ["life is short,i like like python", "life is too long,i dislike python"]
# 1.实例化一个转换器类
transfer1 = CountVectorizer()
transfer2 = CountVectorizer(stop_words=['is','too'])
# 2.调用fit_transform()
data_new1 = transfer1.fit_transform(data)
data_new2 = transfer2.fit_transform(data)
# sparse自带方法toarray转化成数组
print('特征名字1:\n', transfer1.get_feature_names_out())
print('data_new1:\n', data_new1.toarray())
print('特征名字2:\n', transfer2.get_feature_names_out())
print('data_new2:\n', data_new2.toarray())
if __name__ == '__main__':
count_demo()
![](https://i-blog.csdnimg.cn/blog_migrate/2cd7d51841a43218122e57d3424f0544.png)
![](https://i-blog.csdnimg.cn/blog_migrate/18fa3f012fe26757d1a0a69fc283a7e0.png)
中文文本特征抽取
结巴分词
输入的 `text` 是 `'我爱北京天安门'`,通过 `jieba.cut(text)` 进行分词后,生成器会返回一个可迭代对象 `['我', '爱', '北京', '天安门']`。然后,`.join()` 方法将这些分词结果连接起来,得到一个字符串 `'我 爱 北京 天安门'`。
import jieba
def cut_word(text):
# 进行中文分词:'我爱北京天安门' -> '我 爱 北京 天安门'
text = ' '.join(jieba.cut(text)) #将生成器进行强转换成一个字符串
print(text)
return text
if __name__ == '__main__':
cut_word('我爱北京天安门')
分词与特征提取
CountVectorizer()
from sklearn.feature_extraction.text import CountVectorizer
import jieba
def cut_word(text):
# 进行中文分词:'我爱北京天安门' -> '我 爱 北京 天安门'
text = ' '.join(jieba.cut(text)) #将生成器进行强转换成一个字符串
return text
def count_chinese_demo():
data = ["一种还是一种今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。",
"我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去。",
"如果只用一种方式了解某样事物,你就不会真正了解它。了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。"]
# 1.将中文文本进行分词
data_new = [cut_word(i) for i in data]
# 2.实例化一个转换器类
transfer = CountVectorizer(stop_words=['一种','所以'])
# 3.调用fit_transform()
data_final = transfer.fit_transform(data_new)
print('特征名字:\n', transfer.get_feature_names_out())
print('data_final:\n', data_final.toarray())
if __name__ == '__main__':
count_chinese_demo()
![](https://i-blog.csdnimg.cn/blog_migrate/8b48ec1b42669de2462b772fda519ae0.png)
Tf-idf文本特征提取
TF-IDF的主要思想是:如果某个词或短语在一篇文章中出现的概率高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。
TF-IDF作用:用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。
- 词频(term frequency,tf)指的是某一个给定的词语在该文件中出现的频率
- 逆向文档频率(inverse document frequency,idf)是一个词语普遍重要性的度量。某一特定词语的idf,可以由总文件数目除以包含该词语之文件的数目,再将得到的商取以10为底的对数得到
最终得出结果可以理解为重要程度。
TfidfVectorizer()
import jieba
from sklearn.feature_extraction.text import TfidfVectorizer
def tfidf_demo():
data = ["一种还是一种今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。",
"我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去。",
"如果只用一种方式了解某样事物,你就不会真正了解它。了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。"]
# 1.将中文文本进行分词
data_new = [cut_word(i) for i in data]
# 2.实例化一个转换器类
transfer = TfidfVectorizer(stop_words=['一种', '所以'])
# 3.调用fit_transform()
data_final = transfer.fit_transform(data_new)
print('特征名字:\n', transfer.get_feature_names_out())
print('data_final:\n', data_final.toarray())
if __name__ == '__main__':
tfidf_demo()
结果:输出每个词TF-IDF(重要程度)的值
特征预处理
通过一些转换函数将特征数据转换成更加适合算法模型的特征数据过程
![](https://i-blog.csdnimg.cn/blog_migrate/7d887238b9d6b7a396c800d13f08cf30.png)
数值型数据的无量纲化:归一化、标准化
特征预处理API:
sklearn.preprocessing
归一化
通过对原始数据进行变换把数据映射到(默认为[0,1])之间
![](https://i-blog.csdnimg.cn/blog_migrate/788069d94b353a70727a5be51120b25c.png)
sklearn.preprocessing.MinMaxScaler (feature_range=(0,1)… )
MinMaxScalar.fit_transform(X)
- X:numpy array格式的数据[n_samples,n_features]
- 返回值:转换后的形状相同的array
from sklearn.preprocessing import MinMaxScaler
def minmax_demo():
iris = load_iris()
iris = iris['data']
data = pd.DataFrame(iris,columns=['sepal length', 'sepal width', 'petal length', 'petal width'])
transfer = MinMaxScaler()
data_new = transfer.fit_transform(data)
print('data_new:\n', data_new)
if __name__ == '__main__':
minmax_demo()
![](https://i-blog.csdnimg.cn/blog_migrate/46c2edff56526eae72e695e275edc310.png)
标准化
由于归一化是根据最大值最小值算出来的,如果最大值最小值恰好是异常值,那么健壮性较差,所以归一化只适合精确小数据场景
![](https://i-blog.csdnimg.cn/blog_migrate/e30be0086379213d0fc2f3e624003410.png)
sklearn.preprocessing.StandardScaler( )
- 处理之后每列来说所有数据都聚集在均值0附近标准差差为1
StandardScaler.fit_transform(X)
- X:numpy array格式的数据[n_samples,n_features]
- 返回值:转换后的形状相同的array
from sklearn.preprocessing import StandardScaler
def stand_demo():
iris = load_iris()
iris = iris['data']
data = pd.DataFrame(iris, columns=['sepal length', 'sepal width', 'petal length', 'petal width'])
transfer = StandardScaler()
data_new = transfer.fit_transform(data)
print('data_new:\n', data_new)
if __name__ == '__main__':
stand_demo()
特征降维
指降低随机变量(特征)个数
降低自变量之间的相关性(多重共线性)
降维方法:特征选择、主成分分析
- Filter(过滤式):主要探究特征本身特点、特征与特征和目标值之间关联
- 方差选择法:低方差特征过滤
- 相关系数:特征与特征之间的相关程度
- Embedded (嵌入式):算法自动选择特征(特征与目标值之间的关联)
- 决策树:信息熵、信息增益
- 正则化:L1、L2
- 深度学习:卷积等
sklearn.feature_selection
低方差特征过滤
删除低方差的一些特征
- 特征方差小:某个特征大多样本的值比较相近
- 特征方差大:某个特征很多样本的值都有差别
sklearn.feature_selection.VarianceThreshold(threshold = 0.0)
- 删除所有低方差特征
- threshold =输入方差小于几都被过滤掉
- Variance.fit_transform(X)
- X:numpy array格式的数据[n_samples,n_features]
- 返回值:训练集差异低于threshold的特征将被删除。默认值是保留所有非零方差特征,即删除所有样本中具有相同值的特征。
from sklearn.feature_selection import VarianceThreshold
def variance_demo():
data = pd.read_csv('factor_returns.csv')
data = data.iloc[:,1:-2]
#方差小于10的特征列都过滤掉
transfer = VarianceThreshold(threshold=10)
data_new = transfer.fit_transform(data)
print('data_new:\n', data_new)
print(data_new.shape)
if __name__ == '__main__':
variance_demo()
相关系数过滤
当r>0时,表示两变量正相关,r<0时,两变量为负相关
当|r|=1时,表示两变量为完全相关,当r=0时,表示两变量间无相关关系
当0<|r|<1时,表示两变量存在一定程度的相关。且|r|越接近1,两变量间线性关系越密切;|r|越接近于0,表示两变量的线性相关越弱
一般可按三级划分:|r|<0.4为低度相关;0.4≤|r|<0.7为显著性相关;0.7≤|r|<1为高度线性相关
from scipy.stats import pearsonr
x : (N,) array_like
y : (N,) array_like Returns: (Pearson’s correlation coefficient, p-value)
from scipy.stats import pearsonr
def variance_demo():
data = pd.read_csv('factor_returns.csv')
data = data.iloc[:,1:-2]
r = pearsonr(data['pe_ratio'],data['pb_ratio'])
print('相关系数:\n',r)
if __name__ == '__main__':
variance_demo()
- 当特征与特征之间相关性很高:
- 1.选取其中一个
- 2.加权求和
- 3.主成分分析
主成分分析
-
定义:高维数据转化为低维数据的过程,在此过程中可能会舍弃原有数据、创造新的变量
-
作用:是数据维数压缩,尽可能降低原数据的维数(复杂度),损失少量信息。
![](https://i-blog.csdnimg.cn/blog_migrate/b421b1f143b9a2fc49fe92089fa7c724.png)
sklearn.decomposition.PCA(n_components=None)
- 将数据分解为较低维数空间
- n_components:
- 小数:表示保留百分之多少的信息
- 整数:减少到多少特征
- PCA.fit_transform(X)
- X:numpy array格式的数据[n_samples,n_features]
- 返回值:转换后指定维度的array
from sklearn.decomposition import PCA
def pca_demo():
data = [[2, 8, 4, 5], [6, 3, 0, 8], [5, 4, 9, 1]]
# 降成两个特征
transfer = PCA(n_components=2)
data_new = transfer.fit_transform(data)
print('data_new:\n', data_new)
if __name__ == '__main__':
pca_demo()
分类算法
sklearn转换器和估计器
转化器
我们把特征工程的接口称之为转换器,其中转换器调用有这么几种形式
- fit_transform
- fit
- transform
转换器:特征工程的父类
实例化:实例化一个转换器类 (实例化的是一个转换器类(Transformer))
估计器
在sklearn中,估计器(estimator)是一个重要的角色,是一类实现了算法的API
- 1、用于分类的估计器:
- sklearn.neighbors k-近邻算法
- sklearn.naive_bayes 贝叶斯
- sklearn.linear_model.LogisticRegression 逻辑回归
- sklearn.tree 决策树与随机森林
- 2、用于回归的估计器:
- sklearn.linear_model.LinearRegression 线性回归
- sklearn.linear_model.Ridge 岭回归
- 3、用于无监督学习的估计器
- sklearn.cluster.KMeans 聚类
![](https://i-blog.csdnimg.cn/blog_migrate/6abbb4051118e40da002631f3d1427c3.png)
KNN算法
定义
核心思想:根据你的“邻居”来推断出你的类别
定义:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。
两个样本的距离可以通过如下公式计算,又叫欧式距离
![](https://i-blog.csdnimg.cn/blog_migrate/a9cdb715e339ddb4df8223a4014ba8d2.png)
k值过小:容错率低;k值过大:准确率低
knn算法要做无量纲化处理
- sklearn.neighbors.KNeighborsClassifier(n_neighbors=5,algorithm='auto')
- n_neighbors:int,可选(默认= 5),k_neighbors查询默认使用的邻居数
- algorithm:{‘auto’,‘ball_tree’,‘kd_tree’,‘brute’},可选用于计算最近邻居的算法:‘ball_tree’将会使用 BallTree,‘kd_tree’将使用 KDTree。‘auto’将尝试根据传递给fit方法的值来决定最合适的算法。 (不同实现方式影响效率)
案例:鸢尾花种类预测
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
def knn_iris():
# 1.获取数据
iris = load_iris()
# 2.数据集划分
x_train,x_test,y_train,y_test = train_test_split(iris.data,iris.target,random_state=6)
# 3.特征工程:标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test) #用训练集fit出来的数据对测试集进行标准化
# 4.KNN预估器流程
estimator = KNeighborsClassifier(n_neighbors=3)
estimator.fit(x_train,y_train)
# 5.模型评估
#方法1:直接对比真实值和预测值
y_predict = estimator.predict(x_test)
print('y_predict:\n',y_predict)
print('对比真实值和预测值\n',y_test==y_predict)
#方法2:计算准确率
score = estimator.score(x_test,y_test)
print('准确率为:\n',score)
if __name__ == '__main__':
knn_iris()
![](https://i-blog.csdnimg.cn/blog_migrate/1dbbe0a5a6d21947e49aac2d862370a2.png)
优缺点
- 优点:
- 简单,易于理解,易于实现,无需训练
- 缺点:
- 懒惰算法,对测试样本分类时的计算量大,内存开销大
- 必须指定K值,K值选择不当则分类精度不能保证
- 使用场景:小数据场景,几千~几万样本,具体场景具体业务去测试
模型选与调优——网格搜索
交叉验证
将拿到的训练数据,分为训练和验证集。以下图为例:将数据分成5份,其中一份作为验证集。然后经过5次(组)的测试,每次都更换不同的验证集。即得到5组模型的结果,取平均值作为最终结果。又称5折交叉验证。
我们之前知道数据分为训练集和测试集,但是为了让从训练得到模型结果更加准确。做以下处理
- 训练集:训练集+验证集
- 测试集:测试集
超参数搜索-网格搜索(Grid Search)
通常情况下,有很多参数是需要手动指定的(如k-近邻算法中的K值),这种叫超参数。但是手动过程繁杂,所以需要对模型预设几种超参数组合。每组超参数都采用交叉验证来进行评估。最后选出最优参数组合建立模型。
- sklearn.model_selection.GridSearchCV(estimator, param_grid=None,cv=None)
- 对估计器的指定参数值进行详尽搜索
- estimator:估计器对象
- param_grid估计器参数(dict):{“n_neighbors”:[1,3,5]}
- cv:指定几折交叉验证
- fit:输入训练数据
- score:准确率
- 结果分析:
- best_params_:最佳参数
- cv_results_:每次交叉验证后的验证集准确率结果和训练集准确率结果
- best_estimator_:最好的参数模型
- best_score_:在交叉验证中验证的最好结果_
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import GridSearchCV
def knn_iris_gscv():
# 1.获取数据
iris = load_iris()
# 2.数据集划分
x_train,x_test,y_train,y_test = train_test_split(iris.data,iris.target,random_state=6)
# 3.特征工程:标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test) #用训练集fit出来的数据对测试集进行标准化
# 4.KNN预估器流程
estimator = KNeighborsClassifier()
#加入网格搜索与交叉验证
param_dict = {'n_neighbors':[1,3,5,7,9,11]}
estimator = GridSearchCV(estimator,param_grid=param_dict,cv=10)
estimator.fit(x_train, y_train)
# 5.模型评估
#方法1:直接对比真实值和预测值
y_predict = estimator.predict(x_test)
print('y_predict:\n',y_predict)
print('对比真实值和预测值\n',y_test==y_predict)
#方法2:计算准确率
score = estimator.score(x_test,y_test)
print('准确率为:\n',score)
print('最佳参数:\n',estimator.best_params_)
print('最佳结果:\n',estimator.best_score_)
print('最佳估计器\n',estimator.best_estimator_)
print('交叉验证结果:\n',estimator.cv_results_)
if __name__ == '__main__':
knn_iris_gscv()
![](https://i-blog.csdnimg.cn/blog_migrate/74c9b94228f8d070a31c3b790fb72dcf.png)
朴素贝叶斯算法
定义
![](https://i-blog.csdnimg.cn/blog_migrate/16ba6f35ec55fc5c0951495373ac38d3.png)
朴素:假设特征与特征之间是独立的
朴素贝叶斯算法=朴素+贝叶斯公式
应用场景:文本分类、单词做特征
朴素贝叶斯算法算的是属于不同类别的概率,判断对象属于概率最大的那个类别
拉普拉斯平滑系数
目的:防止计算出的分类概率为0
![](https://i-blog.csdnimg.cn/blog_migrate/e8dfd7b4165489886edef1988844cfa0.png)
m:有几种特征词
sklearn.naive_bayes.MultinomialNB(alpha = 1.0)
- 朴素贝叶斯分类
- alpha:拉普拉斯平滑系数
from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
def nb_news():
#1.获取数据
news = fetch_20newsgroups(subset='all')
#2.划分数据集
x_train,x_test,y_train,y_test = train_test_split(news.data,news.target)
#3.特征工程:文本特征抽取-tfidf
transfer = TfidfVectorizer()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
#4.朴素贝叶斯预估器流程
estimator = MultinomialNB()
estimator.fit(x_train,y_train)
#5.模型评估
#方法1:直接对比真实值和预测值
y_predict = estimator.predict(x_test)
print('y_predict:\n',y_predict)
print('对比真实值和预测值\n',y_test==y_predict)
#方法2:计算准确率
score = estimator.score(x_test,y_test)
print('准确率为:\n',score)
if __name__ == '__main__':
nb_news()
优点:
- 朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率。
- 对缺失数据不太敏感,算法也比较简单,常用于文本分类。
- 分类准确度高,速度快
缺点:
- 由于使用了样本属性独立性的假设,所以如果特征属性有关联时其效果不好
决策树
原理
信息熵(Entropy):信息熵是信息理论中的一个概念,用于衡量随机变量的不确定性或信息量的平均值。
![](https://i-blog.csdnimg.cn/blog_migrate/cd6dc66d13b286e4ce3534517c295028.png)
(一般默认log的底数是2,但其它任意都可以)
信息增益(Information Gain)——决策树划分支路的依据
信息增益 = 原信息熵 - 根据某依据分类后的信息熵(条件熵)
H(总信息熵)= -( 6/15 * log6/15 + 9/15 * log9/15 ) ≈ 0.917
H(基于年龄分类后的子信息熵)= 5/15(青年) + 5/15(中年) + 5/15(老年)
信息增益高的特征选项优先作为决策树的下一级分支
当然决策树的原理不止信息增益这一种,还有其他方法。但是原理都类似。
ID3
- 信息增益 最大的准则
C4.5
- 信息增益比 最大的准则
CART
- 分类树: 基尼系数 最小的准则 在sklearn中可以选择划分的默认原则
- 优势:划分更加细致(从后面例子的树显示来理解)
代码
class sklearn.tree.DecisionTreeClassifier(criterion=’gini’, max_depth=None,random_state=None)
- 决策树分类器
- criterion:默认是’gini’系数,也可以选择信息增益的熵’entropy’
- max_depth:树的深度大小
- random_state:随机数种子
- 其中会有些超参数:max_depth:树的深度大小
- 其它超参数我们会结合随机森林讲解
from sklearn.datasets import load_iris
from sklearn.tree import DecisionTreeClassifier
def decision_iris():
# 1.获取数据
iris = load_iris()
# 2.划分数据集
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=22)
# 3.决策树预估器
estimator = DecisionTreeClassifier(criterion='entropy',)
estimator.fit(x_train,y_train)
# 4.模型评估
# 方法1:直接对比真实值和预测值
y_predict = estimator.predict(x_test)
print('y_predict:\n', y_predict)
print('对比真实值和预测值\n', y_test == y_predict)
# 方法2:计算准确率
score = estimator.score(x_test, y_test)
print('准确率为:\n', score)
if __name__ == '__main__':
decision_iris()
决策树可视化
sklearn.tree.export_graphviz()
tree.export_graphviz(estimator,out_file='tree.dot’,feature_names=[‘’,’’])
- 该函数能够导出DOT格式的文件
- 利用工具将dot转换为图片:
- Webgraphviz
接上图案例:
from sklearn.tree import DecisionTreeClassifier,export_graphviz
# 5.可视化决策树
export_graphviz(estimator,out_file='iris_tree.dot',feature_names=iris.feature_names)
决策树优点:可视化——可解释能力强
决策树缺点:容易产生过拟合
泰坦尼克号案例
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier,export_graphviz
#获取数据
titanic = pd.read_csv("titanic.csv")
#筛选目标值和特征值
x = titanic[['Pclass','Age','Sex']]
y = titanic['Survived']
#数据处理
#缺失值处理
x['Age'].fillna(x['Age'].mean(),inplace=True)
#转换成字典
x = x.to_dict(orient='records')
x_train, x_test, y_train, y_test = train_test_split(x,y)
#字典特征抽取
transfer = DictVectorizer()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
#决策树预估器
estimator = DecisionTreeClassifier(criterion='entropy',max_depth=8)
estimator.fit(x_train,y_train)
# 模型评估
# 方法1:直接对比真实值和预测值
y_predict = estimator.predict(x_test)
print('y_predict:\n', y_predict)
print('对比真实值和预测值\n', y_test == y_predict)
# 方法2:计算准确率
score = estimator.score(x_test, y_test)
print('准确率为:\n', score)
#可视化决策树
export_graphviz(estimator,out_file='titanic_tree.dot',feature_names=transfer.get_feature_names_out())
随机森林
原理
在机器学习中,随机森林是一个包含多个决策树的分类器,并且其输出的类别是由个别树输出的类别的众数而定。
例如, 如果你训练了5个树, 其中有4个树的结果是True, 1个数的结果是False, 那么最终投票结果就是True
随机森林根据下列算法而建造每棵树:
- 用N来表示训练样本的个数,M表示特征数目。
- 1、一次随机选出一个样本,重复N次(随机有放回抽样)
- 2、随机选出m个特征, m <<M,建立决策树
优点:
- 起降维效果,且每棵树运算都会快点
- 能防止过拟合
- 拥有重要特征的树会脱颖而出
代码
class sklearn.ensemble.RandomForestClassifier(n_estimators=10, criterion=’gini’, max_depth=None, bootstrap=True, random_state=None, min_samples_split=2)
- 随机森林分类器
- n_estimators:integer,optional(default = 10)森林里的树木数量120,200,300,500,800,1200(可以网格搜索)
- criteria:string,可选(default =“gini”)分割特征的测量方法
- max_depth:integer或None,可选(默认=无)树的最大深度 5,8,15,25,30
- max_features="auto”,每个决策树的最大特征数量
- If "auto", then
max_features=sqrt(n_features)
.- If "sqrt", then
max_features=sqrt(n_features)
(same as "auto").- If "log2", then
max_features=log2(n_features)
.- If None, then
max_features=n_features
.- bootstrap:boolean,optional(default = True)是否在构建树时使用放回抽样
- min_samples_split:节点划分最少样本数
- min_samples_leaf:叶子节点的最小样本数
- 超参数:n_estimator, max_depth, min_samples_split,min_samples_leaf
随机森林优点:
- 准确率非常高
- 能够有效运行在大数据集上,处理具有高维特征的输入样本
- 能够评估各个特征在分类上的重要性
回归与聚类算法
线性模型
原理
线性回归(Linear regression)是利用回归方程(函数)对一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方式。
![](https://i-blog.csdnimg.cn/blog_migrate/afc8e1694d582b8e0d7ae311e602fbe3.png)
线性回归当中的关系有两种,一种是线性关系(自变量一次方),另一种是非线性关系(参数一次方)。
![](https://i-blog.csdnimg.cn/blog_migrate/0dd3d9fb0b0491212e51c1f8edf50068.png)
![](https://i-blog.csdnimg.cn/blog_migrate/81a0ea7ed3167ce60c948919dd1ee340.png)
![](https://i-blog.csdnimg.cn/blog_migrate/96dfac78c0d44ffa8f81925482ed064f.png)
线性回归的损失和优化原理
损失函数
![](https://i-blog.csdnimg.cn/blog_migrate/3219a138f0e25f4991fef9faa8324870.png)
- y_i为第i个训练样本的真实值
- h(x_i)为第i个训练样本特征值组合预测函数
- 又称最小二乘法
优化损失的方法:正规方程、 梯度下降
正规方程
正规方程可以直接求到最佳解
![](https://i-blog.csdnimg.cn/blog_migrate/1f8027f48c41d93b57d22e7d629cc99e.png)
理解:X为特征值矩阵,y为目标值矩阵。直接求到最好的结果
缺点:当特征过多过复杂时,求解速度太慢并且得不到结果
梯度下降
- 理解:α为学习速率,需要手动指定(超参数),α旁边的整体表示方向
- 往梯度下降最快的方向下降,最后就能找到山谷的最低点,然后更新W值
- 应用:面对训练数据规模十分庞大的任务 ,能够找到较好的结果
API
sklearn.linear_model.LinearRegression(fit_intercept=True)
- 通过正规方程优化
- fit_intercept:是否计算截距
- LinearRegression.coef_:回归系数
- LinearRegression.intercept_:偏置
sklearn.linear_model.SGDRegressor(loss="squared_loss", fit_intercept=True, learning_rate ='invscaling', eta0=0.01,max_iter=10000)
- SGDRegressor类实现了随机梯度下降学习,它支持不同的loss函数和正则化惩罚项来拟合线性回归模型。
- loss:损失类型
- loss=”squared_loss”: 普通最小二乘法
- fit_intercept:是否计算截距
- learning_rate : string, optional
- 学习率填充
- 'constant': eta = eta0
- 'optimal': eta = 1.0 / (alpha * (t + t0)) [default]
- 'invscaling': eta = eta0 / pow(t, power_t)
- power_t=0.25:存在父类当中
- 对于一个常数值的学习率来说,可以使用learning_rate=’constant’ ,并使用eta0来指定学习率。
- max_iter : 迭代次数
- SGDRegressor.coef_:回归系数
- SGDRegressor.intercept_:截距
回归性能评估
均方误差公式:
![](https://i-blog.csdnimg.cn/blog_migrate/dba8dd5756d78f49fde141e55367d7f5.png)
越小越好
sklearn.metrics.mean_squared_error(y_true, y_pred)
- 均方误差回归损失
- y_true:真实值
- y_pred:预测值
- return:浮点数结果
案例代码
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression,SGDRegressor
from sklearn.metrics import mean_squared_error
def linear1():
# 1.获取数据
boston = load_boston()
# 2.划分数据集
x_train, x_test, y_train, y_test = train_test_split(boston.data,boston.target,random_state=22)
# 3.标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 4.预估器
estimator = LinearRegression()
estimator.fit(x_train,y_train)
# 5.得出模型
print('正规方程系数为:\n',estimator.coef_)
print('正规方程截距为:\n',estimator.intercept_)
# 6.模型评估
y_predict = estimator.predict(x_test)
print('预测房价:\n',y_predict)
error = mean_squared_error(y_test,y_predict)
print('正规方程-均方误差为:\n',error)
def linear2():
# 1.获取数据
boston = load_boston()
# 2.划分数据集
x_train, x_test, y_train, y_test = train_test_split(boston.data,boston.target,random_state=22)
# 3.标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 4.预估器
estimator = SGDRegressor()
estimator.fit(x_train,y_train)
# 5.得出模型
print('梯度下降系数为:\n',estimator.coef_)
print('梯度下降截距为:\n',estimator.intercept_)
# 6.模型评估
y_predict = estimator.predict(x_test)
print('预测房价:\n',y_predict)
error = mean_squared_error(y_test,y_predict)
print('梯度下降-均方误差为:\n',error)
if __name__=='__main__':
linear1()
linear2()
欠拟合与过拟合
定义
过拟合:一个假设在训练数据上能够获得比其他假设更好的拟合, 但是在测试数据集上却不能很好地拟合数据,此时认为这个假设出现了过拟合的现象。(模型过于复杂)
欠拟合:一个假设在训练数据上不能获得更好的拟合,并且在测试数据集上也不能很好地拟合数据,此时认为这个假设出现了欠拟合的现象。(模型过于简单)
欠拟合原因以及解决办法
- 原因:学习到数据的特征过少
- 解决办法:增加数据的特征数量
过拟合原因以及解决办法
- 原因:原始特征过多,存在一些嘈杂特征, 模型过于复杂是因为模型尝试去兼顾各个测试数据点
- 解决办法:尽量减少高次项特征的影响
- 正则化
正则化
- L2正则化
- 作用:可以使得其中一些W的都很小,都接近于0,削弱某个特征的影响
- 优点:越小的参数说明模型越简单,越简单的模型则越不容易产生过拟合现象
- Ridge回归(岭回归)
![](https://i-blog.csdnimg.cn/blog_migrate/693ccd33bc9bed71c66749728b29c81e.png)
惩罚项的加入:使得在满足损失函数最小的前提下,w的高次项很小
- L1正则化
- 作用:可以使得其中一些W的值直接为0,删除这个特征的影响
- LASSO回归
岭回归Ridge
岭回归,是一种改进版的线性回归。只不过在算法建立回归方程时候,加上L2正则化的限制,从而达到解决过拟合的效果。
(这个可以做岭回归)
sklearn.linear_model.Ridge(alpha=1.0, fit_intercept=True,solver="auto", normalize=False)
- 具有l2正则化的线性回归
- alpha:正则化力度,也叫λ,即惩罚项的系数
- λ取值:0~1 1~10
- solver:会根据数据自动选择优化方法
- sag:如果数据集、特征都比较大,选择随机梯度下降优化
- normalize:数据是否进行标准化
- normalize=False:可以在fit之前调用preprocessing.StandardScaler标准化数据
Ridge.coef_: 回归系数
Ridge.intercept_: 回归截距
Ridge方法相当于SGDRegressor(penalty='l2', loss="squared_loss"),只不过SGDRegressor实现了一个普通的随机梯度下降学习,推荐使用Ridge(实现了SAG)
(这个也可以做岭回归)
sklearn.linear_model.RidgeCV(_BaseRidgeCV, RegressorMixin)
- 具有l2正则化的线性回归,可以进行交叉验证
- coef_:回归系数
- 正则化力度越大,权重系数会越小
- 正则化力度越小,权重系数会越大
![](https://i-blog.csdnimg.cn/blog_migrate/0a0d91d2f74d3848a3c06ec0ce162f00.png)
from sklearn.linear_model import Ridge
def linear3():
# 1.获取数据
boston = load_boston()
# 2.划分数据集
x_train, x_test, y_train, y_test = train_test_split(boston.data,boston.target,random_state=22)
# 3.标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 4.预估器
estimator = Ridge()
estimator.fit(x_train,y_train)
# 5.得出模型
print('岭回归系数为:\n',estimator.coef_)
print('岭回归截距为:\n',estimator.intercept_)
# 6.模型评估
y_predict = estimator.predict(x_test)
print('预测房价:\n',y_predict)
error = mean_squared_error(y_test,y_predict)
print('岭回归-均方误差为:\n',error)
if __name__=='__main__':
linear3()
逻辑回归
原理
逻辑回归(Logistic Regression)是一种分类算法,名字中带有回归,因为它与回归之间有一定的联系。由于算法的简单和高效,在实际中应用非常广泛。
逻辑回归是解决二分类问题的利器
逻辑回归的输入就是一个线性回归的结果
激活函数-sigmoid函数
- 回归的结果输入到sigmoid函数当中
- 输出结果:[0, 1]区间中的一个概率值,默认为0.5为阈值
sigmoid函数
1 / ( 1 + e^(-x) )
sigmoid函数得到概率值来判断更可能属于哪个分类
损失及优化
逻辑回归的损失,称之为对数似然损失
![](https://i-blog.csdnimg.cn/blog_migrate/592afd2264177628229b788234f956a3.png)
![](https://i-blog.csdnimg.cn/blog_migrate/c39325fda43c1d5fac76dbb7a1ec0507.png)
综合完整损失函数:
例子:(重要理解)
代码案例
sklearn.linear_model.LogisticRegression(solver='liblinear', penalty=‘l2’, C = 1.0)
- solver: 优化求解方式(默认开源的liblinear库实现,内部使用了坐标轴下降法来迭代优化损失函数)
- sag:根据数据集自动选择,随机平均梯度下降
- penalty:正则化的种类
- C:正则化力度
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
# 1.读取数据
column_name = ['Sample code number', 'Clump Thickness', 'Uniformity of Cell Size', 'Uniformity of Cell Shape',
'Marginal Adhesion', 'Single Epithelial Cell Size', 'Bare Nuclei', 'Bland Chromatin',
'Normal Nucleoli', 'Mitoses', 'Class']
data = pd.read_csv('breast-cancer-wisconsin.data',names=column_name)
# 2.缺失值处理
# 将问号值替换成NaN
data = data.replace(to_replace='?', value=np.nan)
# 删除缺失样本
data.dropna(inplace=True)
# 3.划分数据集
# 筛选目标值和特征值
x = data.iloc[:, 1:-1]
y = data['Class']
# 划分
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3)
# 4.特征工程:标准化
transfer = StandardScaler()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
# 5.逻辑回归
estimator = LogisticRegression()
estimator.fit(x_train,y_train)
print(estimator.coef_)
print(estimator.intercept_)
# 6.模型评估
#方法1:直接对比真实值和预测值
y_predict = estimator.predict(x_test)
print('y_predict:\n', y_predict)
print('对比真实值和预测值\n', y_test == y_predict)
#方法2:计算准确率
score = estimator.score(x_test, y_test)
print('准确率为:\n', score)
分类的评估方法
精确率与召回率
![](https://i-blog.csdnimg.cn/blog_migrate/6dcc7752e052b2d1630a8364727e22c9.png)
- 精确率:预测结果为正例样本中真实为正例的比例(了解)
- 召回率:真实为正例的样本中预测结果为正例的比例(查的全,对正样本的区分能力)
癌症良性恶性的分类预测:恶性为正例,患癌症能被查出来的概率即为召回率
- F1-score,反映了模型的稳健型
sklearn.metrics.classification_report(y_true, y_pred, labels=[], target_names=None )
- y_true:真实目标值
- y_pred:估计器预测目标值
- labels: 目标值,即类别所代表的数值
- target_names:目标类别名称
- return:每个类别精确率与召回率
接上一个cancer案例:
from sklearn.metrics import classification_report
# 查看精确率、召回率、F1-score
report = classification_report(y_test, y_predict, labels=[2,4], target_names=['良性','恶性'])
print(report)
![](https://i-blog.csdnimg.cn/blog_migrate/b114f7d107674a5072d45f3abb7aa6f7.png)
以上结果最关注的是:恶性肿瘤的召回率,即0.97
然而,当正例太多,反例太少的情况下,会出现样本不均衡的问题,会得出无意义的高的精确率和召回率和F1-score,效果很差,所以需要衡量样本不均衡的评估方法:
ROC曲线和AUC指标
TPR是正例的召回率,FPR是反例的召回率
ROC曲线的横轴就是FPRate,纵轴就是TPRate,当二者相等时,表示的意义则是:对于不论真实类别是1还是0的样本,分类器预测为1的概率是相等的,此时AUC为0.5
- AUC的概率意义是随机取一对正负样本,正样本得分大于负样本的概率
- AUC的最小值为0.5,最大值为1,取值越高越好
- AUC=1,完美分类器,采用这个预测模型时,不管设定什么阈值都能得出完美预测。绝大多数预测的场合,不存在完美分类器。
- 0.5<AUC<1,优于随机猜测。这个分类器(模型)妥善设定阈值的话,能有预测价值。
最终AUC的范围在[0.5, 1]之间,并且越接近1越好
代码
from sklearn.metrics import roc_auc_score
sklearn.metrics.roc_auc_score(y_true, y_predict, y_score)
- 计算ROC曲线面积,即AUC值
- y_true:每个样本的真实类别,必须为0(反例),1(正例)标记
- y_predict: 不需要为0和1
- y_score:每个样本预测的概率值
接上题cancer案例
from sklearn.metrics import roc_auc_score
# y_true:每个样本的真实类别,必须为0(反例),1(正例)标记
# cancer的目标值Class是2和4
# 所以要将y_test转换为0和1
y_true = np.where(y_test==4, 1, 0)
auc = roc_auc_score(y_true, y_predict)
print('auc指标为:\n',auc)
- AUC只能用来评价二分类
- AUC非常适合评价样本不平衡中的分类器性能
模型保存和加载
import joblib
joblib.dump(预估器, '保存路径/文件名.pkl')
- 保存
estimator = joblib.load('加载路径/文件名.pkl')
- 加载
无监督学习 K-means算法
原理
无监督学习包含算法:聚类-K-means(K均值聚类)、降维-PCA
K-means聚类步骤
- 1、随机设置K个特征空间内的点作为初始的聚类中心
- 根据需求设k值,需要分成几类?
- 网格搜索寻找最佳k值
- 2、对于其他每个点,分别计算到K个中心的距离,该未知的点选择最近的一个聚类中心点归类为同一类别
- 3、接着对分类完成的k个类别,重新计算出每个聚类的新中心点(平均值)
- 4、如果计算得出的新中心点与原中心点一样,那么结束,否则重新进行第二步过程
如何求聚类的中心点:
from sklearn.cluster import Kmeans
sklearn.cluster.KMeans(n_clusters=8, init=‘k-means++’)
- n_clusters: 开始的聚类中心数量
- init: 初始化方法,默认为'k-means ++’
- .labels_: 默认标记的类型,可以和真实值比较(不是值比较)
案例代码
将用户根据他们的偏好进行聚类
from sklearn.cluster import Kmeans
cust = data[:500]
km = KMeans(n_clusters=4)
km.fit(cust)
pre = km.predict(cust)
Kmeans性能评估-轮廓系数
原理
![](https://i-blog.csdnimg.cn/blog_migrate/d49e30eae451d34d317a30f4cf78e366.png)
- 注:对于每个点i 为已聚类数据中的样本 ,b_i 为i 到其它族群的所有样本的距离最小值,a_i 为i 到本身簇的距离平均值。最终计算出所有的样本点的轮廓系数平均值
![](https://i-blog.csdnimg.cn/blog_migrate/dc47ffcd04198b3bb4bf6ec6819c9b63.png)
分析过程(我们以一个蓝1点为例):
-
1、计算出蓝1离本身族群所有点的距离的平均值a_i
-
2、蓝1到其它两个族群的距离计算出平均值红平均,绿平均,取最小的那个距离作为b_i
- 根据公式:极端值考虑:如果b_i >>a_i: 那么公式结果趋近于1;如果a_i>>>b_i: 那么公式结果趋近于-1
结论:
如果b_i>>a_i:趋近于1效果越好, b_i<<a_i:趋近于-1,效果不好。轮廓系数的值是介于 [-1,1] ,越趋近于1代表内聚度和分离度都相对较优。
代码
from sklearn.metrics import silhouette_score
sklearn.metrics.silhouette_score(X, labels)
- 计算所有样本的平均轮廓系数
- X:特征值
- labels:被聚类标记后的目标值
from sklearn.metrics import silhouette_score
silhouette_score(cust, pre)
- 特点分析:采用迭代式算法,直观易懂并且非常实用
- 缺点:容易收敛到局部最优解(多次聚类取不同聚类中心来解决)
- 应用场景:没有目标值