机器学习也可以称之为统计学习
机器学习的目的就是从大量数据中获取数据的规律
算法是核心、数据与计算是基础
监督学习:
无监督学习:
举例来说:
预测明天气温多少度?回归
明天天气阴晴还是雨?分类
人年龄预测?回归
人脸识别?分类
机器学习相关书籍:
机器学习——“西瓜书”——周志华
统计学习方法——李航
深度学习——“花书”
特征值+目标值
例如:
sklearn.datasets.load_*() #获取小规模数据集,从网络下载
sklearn.datasets.fetch_*(data_home=None) #获取大规模数据集,从本地加载。如果没有会从网络下载,有的话就从本地加载
返回的是datasets.base.Bunch对象,继承自字典。共有四个键:
业界广泛流传:数据和特征决定了机器学习的上线,而模型和算法只是逼近这个上限而已
哪怕是相同的算法,使用不同特征工程处理过的数据,最终的结果也可能大相径庭。
常用库:
运用数学工具,将一种数据(文本、图像等)转化为另一种数据(数字特征给你)的形式呈现
主要有三种信息的提取:
特征提取API
字典
#转换器类
sklearn.feature_extraction.DictVectorizer(sparse=True)
DictVectorizer.fit_transform(X)
#sparse默认为True, 返回稀疏矩阵。若要显示成one_hot编码,将其设定为False
#返回sparse(稀疏)矩阵
DictVectorizer.inverse_transform(X)
文本
以单词作为特征
transfer = sklearn.feature_extraction.text.CountVectorizer(stop_words=None)
transfer.fit_transform(X)
tf-idf文本特征抽取(见:NLP常见术语):某些词在本文档中出现概率高,并且在其他文章中很少出现,则认为此词或短语具有很好的类别区分能力
vectorizer = sklearn.feature_extraction.text.TfidfVectorizer(stop_words=None)
#返回词的权重矩阵
vectorizer.fit_transform(X)
#X:文本或者包含文本字符的可迭代对象
#返回:sparse矩阵
vectorizer.inverse_transform(X)
#X:array数组或者sparse矩阵
#返回原始数据格式
vectorizer.get_feature_names()
#返回:单词列表
特征的数量级差别较大,会难以获得数据的关系。预处理数据,使得机器学习算法容易学习到其特征。
数值型数据:
min_max_scaler = sklearn.preprocessing.MinMaxScaler(feature_range(0,1)...)
min_max_scaler.fit_transform(X)
#X:numpy array数据:[n_sample][n_features]——列为特征,行为每个特征的数据
#return:相同形状的numpy array
这种方法鲁棒性较差,只适合精确小数据情况。如果有异常值,会严重影响数据。
API:
scaler = sklearn.preprocessing.StandardScaler()
scaler.fit_transform(X)
#X:numpy array格式数据[n_sample][n_sample]
#返回值:相同形状的array
什么是维度?
0维:标量
1维:向量
2维:矩阵
3维、4维。。。
降低维度的对象主要是二维数组(几行就代表有几个样本,几列代表几个特征)的列数。比如下图,将信息从三维空间降维到了二维:
降维要求:特征与特征之间不相关,也就是去掉冗余信息。
降维有两种方式:
模块:
sklearn.feature_selection
API:
transfer= sklearn.feature_selection.VarianceThreshold(threshold=0.0)
transfer.fit_transform(X)
#删除所有低方差特征
#X:numpy array格式数据[n_sample][n_sample]
#返回:训练集方差低于threshold的特征将被删除。默认值是保留所有非零方差特征,即删除所有样本中具有相同值的特征
计算两个变量之间的相关性、密切程度
r = n ∑ x y − ∑ x ∑ y n ∑ x 2 − ( ∑ x ) 2 n ∑ y 2 − ( ∑ y ) 2 r=\frac{n \sum x y-\sum x \sum y}{\sqrt{n \sum x^{2}-\left(\sum x\right)^{2}} \sqrt{n \sum y^{2}-\left(\sum y\right)^{2}}} r=n∑x2−(∑x)2n∑y2−(∑y)2n∑xy−∑x∑y
比如,计算广告费投入和月销售额的关系:
API:
计算两特征之间相关系数:
from scipy.stats import pearsonr
r = pearsonr(X, Y)
#X、Y:numpy array
#return:X和Y的皮尔森相关系数
如果特征与特征之间相关性很高,那么怎么选择?
将高维数据转化为低维数据,尽可能降低元数据的复杂度,减少损失信息。
应用于回归分析、聚类分析中。
比如:如何最好的用二维图像展示一个立体物体?
此例子中,当然是最后一张图片最能展示茶壶的信息。
API:
transfer = sklearn.decomposition.PCA(n_components=None)
data_new = transfer.fit_transform(X)
#将数据分解为低维空间
#n_components:
# 小数:保留百分之多少的信息
# 整数:减少到多少特征
#X:numpy array格式数据
#return:降维后的数据
想一下之前做特征工程的步骤:
sklearn中,所有的估计算法都被封装了起来:
预估器工作流程:
K nearest neighbor,K个最近的邻居。
比如现在有以下电影数据,要确定?电影的分类:
计算与其他电影的距离,与之最近的4个电影中,三个都是爱情片,就可以判定这部电影是爱情片。
API:
classfier = sklearn.neighbors.KNeighborsClassifier(n_neighbors=5, algorithm='auto')
classfier.fit()
import sklearn
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn import neighbors
#获取数据
iris = datasets.load_iris()
#数据集划分
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=6)
#特征工程:标准化
std_transfer = StandardScaler()
x_train = std_transfer.fit_transform(x_train)
#用训练集的均值、标准差来transform测试集
x_test = transfer.transform(x_test)
#实例化预测模型对象
estimator = neighbors.KNeighborsClassifier(n_neighbors=3)
estimator.fit(x_train, y_train)
#开始预测
y_predict = estimator.predict(x_test)
print('y_predict\n', y_predict)
print('直接比对真实值、预测值\n', y_test==y_predict)
#计算准确率
score = estimator.score(x_test, y_test)
print('准确率:', score)
结果:
y_predict
[0 2 0 0 2 1 1 0 2 1 2 1 2 2 1 1 2 1 1 0 0 2 0 0 1 1 1 2 0 1 0 1 0 0 1 2 1
2]
直接比对真实值、预测值
[ True True True True True True False True True True True True
True True True False True True True True True True True True
True True True True True True True True True True False True
True True]
准确率: 0.9210526315789473
KNN分析:
将拿到的训练数据分为训练集和验证集。交叉验证的目的,是为了让训练的出的模型更加准确可信。
训练集划分的份数叫做折数,上方就是划分为4折。
一般来说,折数在10以内,根据数据量的大小选择合适的值。
通常,许多参数是需要手动指定的,比如KNN中的K值,但是手动调整过于繁杂,需要对模型预设集中产参数组合。每组超参数都用交叉验证来进行评估。
API:
gscv = sklearn.model_selection.GridSearchCV(estimator, param_grid=None, cv=None)
#对估计器的指定参数进行详尽搜索,遍历尝试参数,找到最佳参数。
#estimator:估计器对象
#param_grid:估计其参数(dict),比如KNN的estimator实例化的参数:{'n_neighbors':[1,3,5]}
#cv:指定几折交叉验证,
gscv.fit()#输入数据
gscv.score()#准确率
#结果分析:
#最佳参数:
estimator.best_params_
#最佳结果:
estimator.best_score_
#最佳估计器:
estimator.best_estimator_
#交叉验证结果:
estimator.cv_results_
import sklearn
from sklearn import datasets
from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split
from sklearn import neighbors
from sklearn.model_selection import GridSearchCV
#获取数据
iris = datasets.load_iris()
#数据集划分
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, random_state=6)
#特征工程:标准化
std_transfer = StandardScaler()
x_train = std_transfer.fit_transform(x_train)
#用训练集的均值、标准差来transform测试集
x_test = transfer.transform(x_test)
#实例化预测模型对象
estimator = neighbors.KNeighborsClassifier()
estimator = GridSearchCV(estimator=estimator, param_grid={'n_neighbors':[1,3,5,7,9,11]}, cv=10)
estimator.fit(x_train, y_train)
#最佳预测模型
print('最佳预测模型\n', estimator.best_estimator_)
#交叉验证结果
print('交叉验证结果\n', estimator.cv_results_)
#最佳参数
print('最佳参数\n',estimator.best_params_)
#最佳分数
print('最佳分数\n', estimator.best_score_)
结果:
最佳预测模型
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
metric_params=None, n_jobs=1, n_neighbors=5, p=2,
weights='uniform')
交叉验证结果
(省略)
最佳参数
{'n_neighbors': 5}
最佳分数
0.9732142857142857
P ( C ∣ W ) = P ( W ∣ C ) P ( C ) P ( W ) P(C | W)=\frac{P(W | C) P(C)}{P(W)} P(C∣W)=P(W)P(W∣C)P(C)
朴素贝叶斯的朴素,意味着所有特征相互独立。也就是朴素+贝叶斯。
应用场景:
拉普拉斯平滑系数:
P ( F 1 ∣ C ) = N i + α N + α m P(F 1 | C)=\frac{N i+\alpha}{N+\alpha m} P(F1∣C)=N+αmNi+α
API:
sklearn.naive_bayes.MultinomialNB(alpha=1.0)
#alpha:拉普拉斯平滑系数
import sklearn
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
news = datasets.fetch_20newsgroups(subset='all')
#划分数据集
x_train, x_test, y_train, y_test = train_test_split(news.data, news.target)
#实例化文本处理对象
tf_idf_vectorizer = TfidfVectorizer()
x_train = tf_idf_vectorizer.fit_transform(x_train)
x_test = tf_idf_vectorizer.transform(x_test)
#实例化朴素贝叶斯对象
nb_estimator = MultinomialNB()
nb_estimator.fit(x_train, y_train)
y_predict = nb_estimator.predict(x_test)
print("y_predict\n", y_predict)
print("直接和真实值比对\n", y_test == y_predict)
score = nb_estimator.score(x_test, y_test)
print("分数:", score)
结果:
y_predict
[ 0 14 8 ... 4 15 15]
直接和真实值比对
[False True True ... True True False]
分数: 0.8404074702886248
朴素贝叶斯算法总结:
如下图,已知某人年龄、工作、房子、信贷情况,来决定是否给予贷款:
观察可知:如果要贷款,首先考虑有没有房子,有的话,给予贷款;没有房子,如果有工作,给予贷款;没有房子且没有工作,不给予贷款。这样就可以进行高效的决策。
找到一种数学的方法,快速找到判断的先后顺序,才是高效的做法。这就涉及到信息论,需要了解信息论的相关知识:
什么是信息?小明说,他今年18岁。小明的这句话消除了我对小明年龄的未知,所以是信息。紧接着小华说,小明明年19岁。小华的这句话并没有消除任何未知,完全是废话,所以不是信息。
用上面的图来练习一下上面的公式:
共有15人,6人被拒绝,9人获得同意。那么总信息 H ( D ) = − ( 2 / 5 ∗ l o g ( 2 / 5 ) + 3 / 5 ∗ l o g ( 3 / 5 ) ) = 0.971 H(D)=-(2/5 *log(2/5)+3/5*log(3/5))=0.971 H(D)=−(2/5∗log(2/5)+3/5∗log(3/5))=0.971
现在要计算年龄的信息增益:
g ( D , 年 龄 ) = H ( D ) − H ( D ∣ 年 龄 ) = 0.971 − [ 1 / 3 ∗ H ( 青 年 ) + 1 / 3 ∗ H ( 中 年 ) + 1 / 3 ∗ H ( 老 年 ) ] H ( 青 年 ) = − ( 3 / 5 ∗ l o g ( 3 / 5 ) + 2 / 5 ∗ l o g ( 2 / 5 ) ) H ( 中 年 ) = − ( 3 / 5 ∗ l o g ( 3 / 5 ) + 2 / 5 ∗ l o g ( 2 / 5 ) ) H ( 老 年 ) = − ( 4 / 5 ∗ l o g ( 4 / 5 ) + 1 / 5 l o g ( 1 / 5 ) ) g(D,年龄)=H(D)-H(D|年龄)=0.971-[1/3*H(青年)+1/3*H(中年)+1/3*H(老年)]\\ H(青年)=-(3/5*log(3/5)+2/5*log(2/5))\\ H(中年)=-(3/5*log(3/5)+2/5*log(2/5))\\ H(老年)=-(4/5*log(4/5)+1/5log(1/5))\\ g(D,年龄)=H(D)−H(D∣年龄)=0.971−[1/3∗H(青年)+1/3∗H(中年)+1/3∗H(老年)]H(青年)=−(3/5∗log(3/5)+2/5∗log(2/5))H(中年)=−(3/5∗log(3/5)+2/5∗log(2/5))H(老年)=−(4/5∗log(4/5)+1/5log(1/5))
以A1,A2,A3,A4代表年龄、有工作、有房子、和贷款情况,最终计算结果:
g ( D , A 1 ) = 0.313 , g ( D , A 2 ) = 0.324 , g ( D , A 3 ) = 0.420 , g ( D , A 4 ) = 0.363 \mathrm{g}(\mathrm{D}, \mathrm{A} 1)=0.313, \mathrm{g}(\mathrm{D}, \mathrm{A} 2)=0.324, \mathrm{g}(\mathrm{D}, \mathrm{A} 3)=0.420, \mathrm{g}(\mathrm{D}, \mathrm{A} 4)=0.363 g(D,A1)=0.313,g(D,A2)=0.324,g(D,A3)=0.420,g(D,A4)=0.363
可以看出A3(是否有房子)对信息增益影响最大,所以选择A3作为划分的第一个特征,这样就可以慢慢建立一棵决策树。
决策树的划分依据:
API:
from sklearn.tree import DecisionTreeClassifier
DecisionTreeClassifier(criterion='gini', max_depth=None, random_state=None)
#criterion:默认是'gini'系数,也可以选择信息增益熵'entropy'
#max_depth:属的深度大小:树深度较高时可以精准分类,但也有可能造成过拟合
#random_state:随机数种子
import sklearn
from sklearn import datasets
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
iris = datasets.load_iris()
x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target)
estimator = DecisionTreeClassifier(criterion='entropy')
estimator.fit(x_train, y_train)
y_predict = estimator.predict(x_test)
print("y_predict\n", y_predict)
print("直接和真实值对比:\n", y_predict==y_test)
score = estimator.score(x_test, y_test)
print("准确率:", score)
结果:
y_predict
[0 1 1 0 0 0 0 1 0 2 1 0 0 1 0 0 1 2 1 1 2 0 1 0 1 2 2 2 2 0 1 1 1 1 0 1 0
2]
直接和真实值对比:
[ True False True True True True True True True True False True
True True True True True True True True True True True True
True True False True True True True True True True True True
True True]
准确率: 0.9210526315789473
from sklearn.tree import export_graphviz
export_graphviz(estimator, out_file='iris_tree.dot', feature_names=iris.feature_names)
#随后会生成一个iris_tree.dot的文本文件
生成的文本文件内容如图:
仅凭肉眼是看不出决策树的模样的,需要到WebGraphviz网站来看。
决策树总结:
数据在此:url。
import sklearn
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.feature_extraction import DictVectorizer
import pandas as pd
url = 'http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt'
titanic = pd.read_csv(url)
x = titanic[['pclass','age','sex']]
y = titanic[['survived']]
#age有缺失,缺失值用均值补充
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, random_state=23)
#字典特征抽取
transfer = DictVectorizer()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
estimator = DecisionTreeClassifier(criterion='entropy')
estimator.fit(x_train, y_train)
score = estimator.score(x_test, y_test)
print(score)
结果:
0.7933130699088146
通过建立几个模型组合的来解决单一预测问题。生成多个分类器,各自独立学习、做出预测。这些预测最后结合成组合预测,故优于任何一个但分类的预测。
随机森林是一个包含多个决策树的分类器,其输出的类别是由个别决策树的输出类别的众数决定。其实就是少数服从多数的道理。
随机包含两个方面:
使用BootStrap抽样的原因:
API:
from sklearn import ensemble
ensemble.RandomForestClassifier(n_estimators=10, criterion='gini', max_features='auto', max_depth=None, bootstrap=True, random_state=None, min_samples_split=None, min_samples_leaf=None)
#随机森林分类器
#n_estimators:森林里的树木数量,默认为10
#criterion:分类原则:默认为gini
#max_depth:树的最大深度
#max_features:每棵决策树的最大特征数量
# if 'auto': max_features = sqrt(n_features)
# if 'sqrt': max_features = sqrt(n_features)
# if 'log2': max_features = log2(n_features)
# if 'None': max_features = n_features
#bootstrap:是否用有放回抽样,默认为True
#min_samples_split:接电话分最少样本数
#min_samples_leaf:叶子节点最少样本数
#random_state:随机种子
import sklearn
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction import DictVectorizer
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV
import pandas as pd
url = 'http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt'
titanic = pd.read_csv(url)
x = titanic[['pclass','age','sex']]
y = titanic[['survived']]
y = y.iloc[:, 0]
#age有缺失,缺失值用均值补充
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, random_state=23)
#字典特征抽取
transfer = DictVectorizer()
x_train = transfer.fit_transform(x_train)
x_test = transfer.transform(x_test)
random_forest = RandomForestClassifier()
param_dict = {'n_estimators' : [120, 180, 250, 300, 350, 400], 'max_depth' : [3,5,7,9]}
estimator = GridSearchCV(random_forest, param_grid=param_dict, cv=4)
estimator.fit(x_train, y_train)
print(estimator.best_score_)
print(estimator.best_params_)
结果:
0.8282520325203252
{'max_depth': 5, 'n_estimators': 350}
随机森林总结:
h ( w ) = w 1 x 1 + w 2 x 2 + w 3 x 3 ⋯ + b h(w)=w_{1} x_{1}+w_{2} x_{2}+w_{3} x_{3} \dots+b h(w)=w1x1+w2x2+w3x3⋯+b
利用回归方程,对一个或多个自变量和因变量之间关系进行建模。
一般来说对多个特征进行建模,也就是多回归。
单变量回归是一条直线 | 双变量回归是一个面 | 非线性图像也可以是线性模型 |
---|---|---|
更高维度就不用想象图像了,掌握关系对应原理就好。
广义线性模型有两种情况:
如何判断模型是否合适?那就需要计算函数损失,根据损失来进一步优化模型。通过某种方法不断迭代参数,使得损失值不断缩小,就是优化的过程。
损失函数/目标函数可以定义为:
J ( θ ) = ∑ i = 1 m ( h w ( x i ) − y i ) 2 J(\theta)=\sum_{i=1}^{m}\left(h_{w}\left(x_{i}\right)-y_{i}\right)^{2} J(θ)=i=1∑m(hw(xi)−yi)2
不管函数预测值与真实值是大了还是小了,都是误差,所以可以用平方来衡量。
API:
from sklearn.linear_model import LinearRegression
lrg = LinearRegression(fit_intercept=True)
# 通过正规方程优化
# fit_intercept:是否计算偏置
from sklearn.linear_model import SGDRegressor
sgdrg = SGDRegressor(loss='squared_loss', fit_intercept=True, learning_rate='invscaling', eta0=0.01)
# 梯度下降学习,支持不同的loss函数和正则化惩罚项来拟合线性回归
# loss:损失类型
# loss='squared_loss',普通最小二乘法
# fit_intercept:是否计算偏置
# learning_rate:学习率
# 'constant':eta = eta0
# 'optimal':eta = 1.0 / (alpha*(t+t_0)) [default]
# 'invscaling':eta = eta0/(pow(t, power_t)), power_t=0.25存在于父类中.
# eta0:超参数,控制学习率
from sklearn.metrics import mean_squared_error
error = mean_squared_error(y_true, y_pred)
# return:error:浮点数结果
from sklearn import datasets
from sklearn.linear_model import LinearRegression
from sklearn.linear_model import SGDRegressor
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
#获取数据
bosbon = datasets.load_boston()
#划分数据集
x_train, x_test, y_train, y_test = train_test_split(bosbon.data, bosbon.target, random_state=22)
#特征工程
std_scaler = StandardScaler()
std_scaler.fit_transform(x_train)
std_scaler.transform(x_test)
#预估器模型
#梯度下降
sgdreg = SGDRegressor(eta0=0.1, max_iter=10000)
sgdreg.fit(x_train, y_train)
y_predict = sgdreg.predict(x_test)
#特征有几个权重就有几个
print('权重:',sgdreg.coef_)
print('偏置:',sgdreg.intercept_)
print('梯度下降均方误差:', mean_squared_error(y_test, y_predict))
#预估器模型
#正规方程
lineareg = LinearRegression()
lineareg.fit(x_train, y_train)
y_predict = lineareg.predict(x_test)
print('权重:',lineareg.coef_)
print('偏置:',lineareg.intercept_)
print('正规方程均方误差:', mean_squared_error(y_test, y_predict))
输出:
权重: [ 3.15402689e+11 8.27684781e+11 1.09914860e+12 1.82602770e+10
4.07394059e+11 9.10630915e+10 9.26332755e+11 -5.88931583e+11
-1.73986281e+11 6.18298546e+11 -1.58331608e+12 -8.88589463e+11
-5.52756684e+11]
偏置: [5.56449674e+11]
梯度下降均方误差: 2.6849301197678843e+28
权重: [-8.86229124e-02 4.77879655e-02 -8.25146050e-03 3.17672248e+00
-1.65243833e+01 3.85191254e+00 -2.67041629e-03 -1.51889177e+00
2.88438979e-01 -1.10740926e-02 -8.07483632e-01 9.44710495e-03
-5.37417688e-01]
偏置: 33.444926743477886
正规方程均方误差: 20.630254348290997
有可能是数据量过小,导致梯度下降法在此并不好用。
选择:
拓展 ——关于优化方法
- GD:Gradient Descent, 原始的梯度下降方法,计算量大.
- SGD:Stochastic Gradient Descent:随机梯度下降
- SGD优点:高效,易实现
- SGD缺点:需要许多超参数,迭代数,对特征标准化比较敏感
- SAG:Stochastic Average Gradient:随即平均梯度.sklearn的岭回归,逻辑回归中都有SAG优化
这一部分可以看我的另一篇博文:机器学习_基础概念二.
简单来说,欠拟合就是模型过于简单,过拟合就是模型过于复杂。如图:
为了让模型更简单,避免过拟合, 所以有了正则化:
岭回归就是自带L2正则化的回归。
API:
from sklearn.linear_model import Ridge
ridge = Ridge(alpha=1,0, fit_intercept=True, solver='auto', normalize=False)
#alpha:正则化力度,也叫λ,一般取值[0, 1],[1, 10]
#solver:
# auto:根据数据自动选择优化方法
# sag:如果数据集、特征都比较大,会选择随机梯度下降优化
#normalize:数据是否进行标准化
# False:可以用preprocessing.StandardScaler标准化数据
#Ride.coef_ :回归权重
#Ridge.intercept_ :回归偏置
Ridge方法相当于SGDRegressor(penalty=‘l2’, loss=‘squared_loss’),SGDRegressor实现了一个普通的随机梯度下降学习,推荐使用Ridge(实现了SAG)
当然也可以使用加上了交叉验证的岭回归
from sklearn.linear_model import RidgeCV
ridge_cv = RidgeCV(LinearModel, RegressorMixin)
在上方代码最后加上:
#岭回归
ridge = Ridge()
ridge.fit(x_train, y_train)
y_predict = ridge.predict(x_test)
print('权重:',ridge.coef_)
print('偏置:',ridge.intercept_)
print('梯度下降均方误差:', mean_squared_error(y_test, y_predict))
输出:
权重: [-0.08174617 0.0484571 -0.04470846 2.95906026 -9.01186447 3.90039909
-0.0093695 -1.40960782 0.2691074 -0.01156641 -0.72502168 0.00977589
-0.54637785]
偏置: 28.27731863972173
梯度下降均方误差: 21.042183141108147
逻辑回归应用场景:
就是判断是或者不是的问题,其实也就是二分类。
将线性函数的输出映射到激活函数上
h ( w ) = w 1 x 1 + w 2 x 2 + w 3 x 3 ⋯ + b h(w)=w_{1} x_{1}+w_{2} x_{2}+w_{3} x_{3} \dots+b h(w)=w1x1+w2x2+w3x3⋯+b
随后得到结果根据一定的阈值判断之后就是逻辑回归。
逻辑回归的结果只有正确或不正确,就不能像之前那样构建损失函数了:
cost ( h θ ( x ) , y ) = { − log ( h θ ( x ) ) if y = 1 − log ( 1 − h θ ( x ) ) if y = 0 \operatorname{cost}\left(h_{\theta}(x), y\right)=\left\{\begin{array}{ll}{-\log \left(h_{\theta}(x)\right)} & {\text { if } y=1} \\ {-\log \left(1-h_{\theta}(x)\right)} & {\text { if } y=0}\end{array}\right. cost(hθ(x),y)={−log(hθ(x))−log(1−hθ(x)) if y=1 if y=0
当真实值y为1的Loss函数 | 当真实值y为0的Loss函数 |
---|---|
对数损失函数的完整表达式
cost ( h θ ( x ) , y ) = ∑ i = 1 m − y i log ( h θ ( x ) ) − ( 1 − y i ) log ( 1 − h θ ( x ) ) \operatorname{cost}\left(h_{\theta}(x), y\right)=\sum_{i=1}^{m}-y_{i} \log \left(h_{\theta}(x)\right)-\left(1-y_{i}\right) \log \left(1-h_{\theta}(x)\right) cost(hθ(x),y)=i=1∑m−yilog(hθ(x))−(1−yi)log(1−hθ(x))
API:
sklearn.linear_model.LogisticRegression(solver='liblinear', penalty='l2', C=1.0)
#solver:优化求解方式,默认用开源的liblinear库实现,内部使用了坐标轴下降法来迭代优化损失函数;'sag':自动选择
#penalty:正则化种类
#C:正则化力度
默认将类别数量少的当作正例
LogisticRegression相当于sklearn.linear_model.SGDClassifier(loss=‘log’, penalty=’’)。后者实现了一个普通的随机梯度下降学习,也支持平均随机梯度下降法(ASGD),可以设置average=True。
分类评估报告API
sklearn.metrics.classification_report(y_true, y_pred, labelse=[], target_names=None)
#labels
#target_names
#return:每个类别的精确率、召回率
数据集下载在地址。
数据描述:
共有11列数据。第一列为检索id,后9列为相关医学特征,最后一些代表肿瘤类型数值。
有16个缺失值,用?
表示。
from sklearn import datasets
from sklearn.linear_model import LinearRegression
from sklearn.linear_model import SGDRegressor, Ridge
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error
from sklearn.metrics import classification_report
import pandas as pd
#获取数据
url = 'http://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data'
data = pd.read_csv(url)
#数据处理
data = data.replace(to_replace='?', value=np.nan)
data.dropna(inplace=True)
x = data.iloc[:, 1:-1]
y = data.iloc[:, -1]
#划分数据集
x_train, x_test, y_train, y_test = train_test_split(x, y)
#特征工程
std_scaler = StandardScaler()
std_scaler.fit_transform(x_train)
std_scaler.transform(x_test)
#逻辑回归
logic_reg = LogisticRegression()
logic_reg.fit(x_train, y_train)
y_predict = logic_reg.predict(x_test)
print(logic_reg.score(x_test, y_test))
#预测结果评估
report = classification_report(y_test, y_predict, labels=[2, 4], target_names=['良性','恶性'])
print(report)
输出:
0.9590643274853801
precision recall f1-score support
良性 0.96 0.97 0.97 103
恶性 0.96 0.94 0.95 68
avg / total 0.96 0.96 0.96 171
当样本不均衡的时候,比如100个样本,其中99个是癌症,1个非癌症。假如说全部预测为癌症,那么准确率就是99%。但是这样的模型显然是不符合要求的。所以在样本不均衡条件下,我们需要ROC曲线和AUC指标。
1 知道TPR和FPR
ROC曲线:
ROC曲线的横轴是FPR,纵轴是TPR。二者相等时,表示不论真实值是1还是0,分类器预测为1的概率是相同的。此时AUC为0.5。
AUC指标:
AUC计算API:
sklearn.metrics.roc_auc_score(y_true=, y_score=)
#计算ROC曲线面积,即AUC值
#y_true:样本的真实类别
#y_score:预测得分,可以是正类的估计概率,置信值或者分类器方法的返回值
#np矢量三元运算符:
y_ture = np.where(y_test > 3, 1, 0)
上方癌症预测练习,考虑AUC之后,得到的AUC的分数为:
from sklearn.metrics import roc_auc_score
y_true = np.where(y_test > 3, 1, 0)
print(roc_auc_score(y_true, y_predict))
结果倒还不错,很接近1了,说明样本比较准确。
0.9605263157894737
总结:如何评估样本的预测效果?
训练好模型后下次直接加载,进行预测,就不用再重新训练了。
API:
from sklearn.externals import joblib
#保存到本地:
joblib.dump(tf, 'test.pkl')
#从本地加载
estimator = joblib.load('test.pkl')
称之为无监督,是因为是从无标签的数据开始学习的。
之前做过的数据降维,也可以称之为无监督学习,因为并没有明确的的目标值。
K-means聚类步骤:
from sklearn.cluster import KMeans
kmeans = KMeans(n_clusters=, init='k-means++')
kmeans.fit(x)
pred = kmeans.predict(x)
#n_clusters:开始的聚类中心数量
#init:初始化方法,默认为'k-means++'
如何评估聚类的效果呢?
需要知道轮廓系数:
s c i = b i − a i max ( b i , a i ) s c_{i}=\frac{b_{i-} a_{i}}{\max \left(b_{i}, a_{i}\right)} sci=max(bi,ai)bi−ai
该算式中, b i b_i bi代表某个点到其他族群的距离最小值, a i a_i ai代表此点与本族群内部点的距离均值。
如果 s c i s c_{i} sci趋近于1( b i ≫ a i b_i\gg a_i bi≫ai)说明效果较好,如果 s c i s c_{i} sci趋近于-1 a i ≫ b i a_i\gg b_i ai≫bi说明效果较差。
轮廓系数API:
from sklearn.metrics import silhouette_score
silhouette_score(x_true, y_predict)
from sklearn import datasets
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
iris = datasets.load_iris()
x_true = iris.data
km = KMeans(n_clusters=3)
km.fit(x_true)
y_pred = km.predict(x_true)
score = silhouette_score(x_true, y_pred)
print(score)
总结K-means:
K-means一般在做分类之前使用