文章目录
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/6b95b5ead0080a89b3bbfbd49bddc959.png#pic_center)
特征工程
特征工程:(就是把文本,字典什么的 转化为 数字,也就是特征值化)
字典形式特征抽取:
对字典数据进行特征值化
sklearn.feature_extraction.DictVectorizer
- X:字典或者包含字典的迭代器 返回值:返回sparse矩阵
from sklearn.feature_extraction import DictVectorizer
def dictvec():
"""字典数据抽取
return:None
"""
# 实例化
dict = DictVectorizer()
#调用fit_transform
data = dict.fit_transform([{'city': '北京','temperature': 100}, {'city': '上海','temperature':60}, {'city': '深圳','temperature': 30}])
print(dict.get_feature_names())
print(dict.inverse_transform(data))
print(data)
return None
if __name__ == '__main__':
dictvec()
文本特征抽取:
sklearn.feature_extraction.text.CountVectorizer
- 统计所有文章当中所有的词,重复的只看做一次
- 对每篇文章,再次的列表里面进行统计没个词出现的次数
- 单个字母不统计
from sklearn.feature_extraction.text import CountVectorizer
import jieba
def cutword():
#jieba.cut() 返回值:词语生成器
con1 = jieba.cut("今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。")
con2 = jieba.cut("我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去。")
con3 = jieba.cut("如果只用一种方式了解某样事物,你就不会真正了解它。了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。")
# 转换成列表
content1 = list(con1)
content2 = list(con2)
content3 = list(con3)
# 列表转换为字符串
c1 = ''.join(content1)
c2 = ''.join(content2)
c3 = ''.join(content3)
return c1,c2,c3
def hazivec():
c1,c2,c3 = cutword()
print(c1,c2,c3)
cv = CountVectorizer()
data = cv.fit_transform([c1, c2, c3])
print(cv.get_feature_names())
print(data.toarray)
return None
if __name__ == '__main__':
countvec()
TF-IDF作用:用以评估一字词对于一个文件集或一个语料库中的其中一份文件的重要程度。
sklearn.feature_extraction.text.TfidfVectorizer
tf:term frequency词的频率
idf:inverce document frequency逆文档频率 log(总文档数/该次出现的文档数量)
tf*idf(重要性程度)
特征预处理:通过特定的统计方法(数学方法)将数据转换成算法要求的数据
数值型数据:标准缩放1. 归一化 2. 标准化
归一化:sklearn.preprocessing.MinMaxScaler 把原始数据通过变换投放到0-1之间
当三个特征同等重要的时候,需要进行归一化
目的:是的某一个特征对结果不会造成更大影响
如果数据中异常点较多,会有什么影响?
缺点:受异常点影响太大(仅适用于精确小数据)(所以一般很少使用)
标准化 :sklearn.preprocessing.StandardScaler
因为数据量巨大,所以少量的异常点对平均值无影响(所以使用较多)
from sklearn.preprocessing import MinMaxScaler, StandardScaler, Imputer
def stand():
std = StandardScaler()
data = std.fit_transform([[90,2,10,40],[60,4,15,45],[75,3,13,46]])
print(data)
return None
if __name__ == '__main__':
stand()
缺失值处理方法:
- 删除(不建议)or插补(一般插中位数)(应该就是插值法)
- sklearn缺失值API:sklearn.processing.imputer(missing_values=‘NaN’, strategy=‘mean’, axis=0)
from sklearn.preprocessing import MinMaxScaler, StandardScaler, Imputer
import numpy as np
def im():
im = Imputer(missing_values='NaN',strategy='mean',axis=0)
data = im.fit_transform([[1,2],[np.nan,3],[7,6]])
print(data)
return None
if __name__ == '__main__':
im()
特征选择
原因:
- 冗余:部分特征的相关度高,容易消耗计算性能
- 噪声:部分特征对预测结果有负影响
维度:数组的难度
降维:特征的数量
特征选择
filter(过滤式)(从发差大小考虑):sklearn.feature_selection.VarianceThreshold
from sklearn.feature_selection import VarianceThreshold
def var():
"""
特征选择-删除低方差的特征
:return: None
"""
var = VarianceThreshold(threshold=1.0)
data = var.fit_transform([[0, 2, 0, 3], [0, 1, 4, 3], [0, 1, 1, 3]])
print(data)
return None
embedded(嵌入式)
PCA(主成分分析):特征数量上百的时候,考虑数据的简化
目的:是数据维数压缩,尽可能降低原数据的维数(复杂度),损失少量信息。
作用:可以削减回归分析或者聚类分析中特征的数量
from sklearn.decomposition import PCA
def pca():
"""
主成分分析进行特征降维
:return: None
"""
pca = PCA(n_components=0.9)
data = pca.fit_transform([[2,8,4,5],[6,3,0,8],[5,4,9,1]])
print(data)
return None
if __name__ == "__main__":
pca()
机器学习算法
机器学习开发流程
监督学习:(特征值+目标值)
- 分类 (离散型) k-近邻算法、贝叶斯分类、决策树与随机森林、逻辑回归、神经网络
- 回归 (连续型) 线性回归、岭回归
无监督学习:(只有特征值)
- 聚类 k-means
数据集划分
机器学习一般的数据集会划分为两个部分:
训练数据:用于训练,构建模型
测试数据:在模型检验时使用,用于评估模型是否有效
sklearn 数据集划分:sklearn.model_selection.train_test_split
from sklearn.datasets import load_iris, fetch_20newsgroups, load_boston
from sklearn.model_selection import train_test_split, GridSearchCV
li = load_iris()
print("获取特征值")
print(li.data)
print("目标值")
print(li.target)
print(li.DESCR)
#注意返回值, 训练集 train x_train, y_train 测试集 test x_test, y_test
x_train, x_test, y_train, y_test = train_test_split(li.data, li.target, test_size=0.25)
print("训练集特征值和目标值:", x_train, y_train)
print("测试集特征值和目标值:", x_test, y_test)
转换器
fit_transform()输入数据直接转换
fit()输入数据
transform()进行数据转换
估计器estimator
流程:算法是核心,数据和计算是基础
- 原始数据 , 根据数据类型明确问题,建立模型
- 数据基本处理
- 特征工程
- 照合理的算法你进行预测 模型:数据+算法
- 模型评估,判定效果
- 成功-上线。 没成功-加特征,换算法,重新来一遍
监督学习
分类算法
分类算法-k近邻算法
定义:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。
计算距离公式:
两个样本的距离可以通过如下公式计算,又叫欧式距离,比如说,a(a1,a2,a3),b(b1,b2,b3)
K近邻算法:需要标准化
sklearn.neighbors.KNeighborsClassifier(n_neighbors=5,algorithm=‘auto’)
k-近邻算法优缺点
优点:简单,易于理解,易于实现,无需估计参数,无需训练
缺点:懒惰算法,对测试样本分类时的计算量大,内存开销大,必须指定K值,K值选择不当则分类精度不能保证
使用场景:小数据场景,几千~几万样本,具体场景具体业务
去测试
混淆矩阵
精确率:预测结果为正例样本中真实为正例的比例(查得准)
召回率:真实为正例的样本中预测结果为正例的比例(查的全,对正样本的区分能力)
分类模型评估API
sklearn.metrics.classification_report(y_true, y_pred, target_names=None)
- y_true:真实目标值
- y_pred:估计器预测目标值
- target_names:目标类别名称
- return:每个类别精确率与召回率
联合概率:包含多个条件,且所有条件同时成立的概率
记作:𝑃(𝐴,𝐵)
条件概率:就是事件A在另外一个事件B已经发生条件下的发生概率
记作:𝑃(𝐴|𝐵)
特性:P(A1,A2|B) = P(A1|B)P(A2|B)
注意:此条件概率的成立,是由于A1,A2相互独立的结果
分类算法-朴素贝叶斯
sklearn.naive_bayes.MultinomialNB(alpha = 1.0)
- 朴素贝叶斯分类 alpha:拉普拉斯平滑系数
优点:
- 朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率。
- 对缺失数据不太敏感,算法也比较简单,常用于文本分类。
- 分类准确度高,速度快
缺点:
- 需要知道先验概率P(F1,F2,…|C),因此在某些时候会由于假设的先验
- 模型的原因导致预测效果不佳。
模型的选择与调优
- 交叉验证
- 网格搜索
超参数搜索-网格搜索API
sklearn.model_selection.GridSearchCV(estimator, param_grid=None,cv=None)
对估计器的指定参数值进行详尽搜索
- estimator:估计器对象
- param_grid:估计器参数(dict){“n_neighbors”:[1,3,5]}
- cv:指定几折交叉验证
- fit:输入训练数据 score:准确率
结果分析:
- best_score_:在交叉验证中测试的最好结果
- best_estimator_:最好的参数模型
- cv_results_:每次交叉验证后的测试集准确率结果和训练集准确率结果
分类算法-决策树、随机森林
决策树的划分依据之一-信息增益
信息增益;当得知一个特征条件之后,减少的信息熵的大小
特征A对训练数据集D的信息增益g(D,A),定义为集合D的信息熵H(D)与特征A给定条件下D的信息条件熵H(D|A)之差,即公式为:
信息增益的计算:
条件熵的计算:
理解:
sklearn决策树API:
class sklearn.tree.DecisionTreeClassifier(criterion=’gini’, max_depth=None,random_state=None)
决策树分类器
- criterion:默认是’gini’系数,也可以选择信息增益的熵’entropy’
- max_depth:树的深度大小
- random_state:随机数种子
- method:
- decision_path:返回决策树的路径
导出DOT格式:
tree.export_graphviz(estimator,out_file='tree.dot’,feature_names=[‘’,’’])
from sklearn.feature_extraction import DictVectorizer
from sklearn.tree import DecisionTreeClassifier, export_graphviz
from sklearn.ensemble import RandomForestClassifier
import pandas as pd
def decision():
"""
决策树对泰坦尼克号进行预测生死
:return: None
"""
# 获取数据
titan = pd.read_csv("http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt")
# 处理数据,找出特征值和目标值
x = titan[['pclass', 'age', 'sex']]
y = titan['survived']
print(x)
# 缺失值处理
x['age'].fillna(x['age'].mean(), inplace=True)
# 分割数据集到训练集合测试集
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.25)
# 进行处理(特征工程)特征-》类别-》one_hot编码
dict = DictVectorizer(sparse=False)
x_train = dict.fit_transform(x_train.to_dict(orient="records"))
print(dict.get_feature_names())
x_test = dict.transform(x_test.to_dict(orient="records"))
# print(x_train)
# 用决策树进行预测
# dec = DecisionTreeClassifier()
#
# dec.fit(x_train, y_train)
#
# # 预测准确率
# print("预测的准确率:", dec.score(x_test, y_test))
#
# # 导出决策树的结构
# export_graphviz(dec, out_file="./tree.dot", feature_names=['年龄', 'pclass=1st', 'pclass=2nd', 'pclass=3rd', '女性', '男性'])
# 随机森林进行预测 (超参数调优)
rf = RandomForestClassifier()
param = {"n_estimators": [120, 200, 300, 500, 800, 1200], "max_depth": [5, 8, 15, 25, 30]}
# 网格搜索与交叉验证
gc = GridSearchCV(rf, param_grid=param, cv=2)
gc.fit(x_train, y_train)
print("准确率:", gc.score(x_test, y_test))
print("查看选择的参数模型:", gc.best_params_)
return None
if __name__ == "__main__":
decision()
集成学习方法-随机森林
随机森林建立多个决策树的过程:
单个树建立过程:
- 随机在N个样本当中选择一个样本,重复N次 (样本有可能重复)
- 随机在M个特征当中选出m个特征
建立10棵决策树,样本,特征大多不一样 ,随机又放回的抽样bootstrap
集成学习通过建立几个模型组合的来解决单一预测问题。它的工作原理是生成多个分类器/模型,各自独立地学习和作出预测。这些预测最后结合成单预测,因此优于任何一个单分类的做出预测。
随机森林是一个包含多个决策树的分类器,并且其输出的类别是由个别树输出的类别的众数而定。
为什么要随机抽样训练集?
如果不进行随机抽样,每棵树的训练集都一样,那么最终训练出的树分类结果也是完全一样的
为什么要有放回地抽样?
如果不是有放回的抽样,那么每棵树的训练样本都是不同的,都是没有交集的,这样每棵树都是“有偏的”,都是绝对“片面的”(当然这样说可能不对),也就是说每棵树训练出来都是有很大的差异的;而随机森林最后分类取决于多棵树(弱分类器)的投票表决。
随机森林API
class sklearn.ensemble.RandomForestClassifier(n_estimators=10, criterion=’gini’,
max_depth=None, bootstrap=True, random_state=None)
- 随机森林分类器
- n_estimators:integer,optional(default = 10) 森林里的树木数量
- criteria:string,可选(default =“gini”)分割特征的测量方法
- max_depth:integer或None,可选(默认=无)树的最大深度
- bootstrap:boolean,optional(default = True)是否在构建树时使用放回抽样
(API)Application Programming Interface,应用程序编程接口
随机森林的优点:
- 在当前所有算法中,具有极好的准确率
- 能够有效地运行在大数据集上
- 能够处理具有高维特征的输入样本,而且不需要降维
- 能够评估各个特征在分类问题上的重要性 对于缺省值问题也能够获得很好得结果
分类算法-逻辑回归
将 线性回归作为输入
是处理二分类问题的
公式:
图像:
损失函数
回归算法
前提:连续型
回归算法-线性回归分析
算法:线性模型:
通过属性的线性组合来进行预测的函数:
策略:损失函数(误差大小):
误差平方和(最小二乘法):
优化:
正规方程 sklearn.linear_model.LinearRegression
梯度下降 sklearn.linear_model.SGDRegressor
理解:沿着这个函数下降的方向找,最后就能找到山谷的最低点,然后更新W值
使用:面对训练数据规模十分庞大的任务
from sklearn.datasets import load_boston
from sklearn.linear_model import LinearRegression, SGDRegressor, Ridge, LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, classification_report
from sklearn.externals import joblib
import pandas as pd
import numpy as np
def mylinear():
"""
线性回归直接预测房子价格
:return: None
"""
# 获取数据
lb = load_boston()
# 分割数据集到训练集和测试集
x_train, x_test, y_train, y_test = train_test_split(lb.data, lb.target, test_size=0.25)
print(y_train, y_test)
# 进行标准化处理(?) 目标值处理?
# 特征值和目标值是都必须进行标准化处理, 实例化两个标准化API
std_x = StandardScaler()
x_train = std_x.fit_transform(x_train)
x_test = std_x.transform(x_test)
# 目标值
std_y = StandardScaler()
y_train = std_y.fit_transform(y_train)
y_test = std_y.transform(y_test)
# 预测房价结果
model = joblib.load("./tmp/test.pkl")
y_predict = std_y.inverse_transform(model.predict(x_test))
print("保存的模型预测的结果:", y_predict)
estimator预测
正规方程求解方式预测结果
lr = LinearRegression()
lr.fit(x_train, y_train)
print(lr.coef_)
保存训练好的模型
joblib.dump(lr, "./tmp/test.pkl")
# 预测测试集的房子价格
y_lr_predict = std_y.inverse_transform(lr.predict(x_test))
print("正规方程测试集里面每个房子的预测价格:", y_lr_predict)
print("正规方程的均方误差:", mean_squared_error(std_y.inverse_transform(y_test), y_lr_predict))
# 梯度下降去进行房价预测
sgd = SGDRegressor()
sgd.fit(x_train, y_train)
print(sgd.coef_)
# 预测测试集的房子价格
y_sgd_predict = std_y.inverse_transform(sgd.predict(x_test))
print("梯度下降测试集里面每个房子的预测价格:", y_sgd_predict)
print("梯度下降的均方误差:", mean_squared_error(std_y.inverse_transform(y_test), y_sgd_predict))
# 岭回归去进行房价预测
rd = Ridge(alpha=1.0)
rd.fit(x_train, y_train)
print(rd.coef_)
# 预测测试集的房子价格
y_rd_predict = std_y.inverse_transform(rd.predict(x_test))
print("梯度下降测试集里面每个房子的预测价格:", y_rd_predict)
print("梯度下降的均方误差:", mean_squared_error(std_y.inverse_transform(y_test), y_rd_predict))
return None
skit-learn :
优点:封装好,建立模型简单,预测简单
缺点:算法中,有些参数都在内部优化,无法调整
tensorflow:封装还行,参数自己可以调
回归性能评估:
(均方误差(Mean Squared Error)MSE) 评价机制:
mean_squared_error(y_true, y_pred)
- 均方误差回归损失
- y_true:真实值
- y_pred:预测值
- return:浮点数结果
过拟合与欠拟合
过拟合:一个假设在训练数据上能够获得比其他假设更好的拟合, 但是在训练数据外的数据集上却不能很好地拟合数据,此时认为这个假设出现了过拟合的现象。(模型过于复杂)
原因:
原始特征过多,存在一些嘈杂特征,
模型过于复杂是因为模型尝试去兼顾
各个测试数据点
解决办法:
进行特征选择,消除关联性大的特征(很难做)
交叉验证(让所有数据都有过训练)
正则化(了解)
欠拟合:一个假设在训练数据上不能获得更好的拟合, 但是在训练数据外的数据集上也不能很好地拟合数据,此时认为这个假设出现了欠拟合的现象。(模型过于简单)
原因:学习到数据的特征过少
解决办法:增加数据的特征数量
岭回归:sklearn.linear_model.Ridge(alpha=1.0)
- 具有l2正则化的线性最小二乘法
- alpha:正则化力度
- coef_:回归系数
保存: joblib.dump( , )
加载:joblib.load()
非监督学习
k-means
聚类算法:
- 首先,随机设K个特征空间内的点作为初始的聚类中心。
- 然后,对于根据每个数据的特征向量,从K个聚类中心中寻找距离最近的一个,并且把该数据标记为这个聚类中心。
- 接着,在所有的数据都被标记过聚类中心之后,根据这些数据新分配的类簇,通过取分配给每个先前质心的所有样本的平均值来创建新的质心重,新对K个聚类中心做计算。
- 最后,计算旧和新质心之间的差异,如果所有的数据点从属的聚类中心与上一次的分配的类簇没有变化,那么迭代就可以停止,否则回到步骤2继续循环。
class sklearn.cluster.KMeans(n_clusters=8, init=‘k-means++’, n_init=10, max_iter=300, tol=0.0001, precompute_distances=‘auto’, verbose=0, random_state=None, copy_x=True, n_jobs=1, algorithm=‘auto’)
“”"
:param n_clusters:要形成的聚类数以及生成的质心数
:param init:初始化方法,默认为’k-means ++’,以智能方式选择k-均值聚类的初始聚类中心,以加速收敛;random,从初始质心数据中随机选择k个观察值(行
:param n_init:int,默认值:10使用不同质心种子运行k-means算法的时间。最终结果将是n_init连续运行在惯性方面的最佳输出。
:param n_jobs:int用于计算的作业数量。这可以通过并行计算每个运行的n_init。如果-1使用所有CPU。如果给出1,则不使用任何并行计算代码,这对调试很有用。对于-1以下的n_jobs,使用(n_cpus + 1 + n_jobs)。因此,对于n_jobs = -2,所有CPU都使用一个。
:param random_state:随机数种子,默认为全局numpy随机数生成器
“”"
方法
fit(X,y=None)
使用X作为训练数据拟合模型
kmeans.fit(X)
predict(X)
预测新的数据所在的类别
kmeans.predict([[0, 0], [4, 4]])
array([0, 1], dtype=int32)
轮廓系数
sklearn.metrics.
from sklearn.metrics import silhouette_score
from sklearn.cluster import KMeans
def kmeans():
"""
手写数字聚类过程
:return: None
"""
# 加载数据
ld = load_digits()
print(ld.target[:20])
# 聚类
km = KMeans(n_clusters=810)
km.fit_transform(ld.data)
print(km.labels_[:20])
print(silhouette_score(ld.data,km.labels_))
return None
if __name__=="__main__":
kmeans()