监督学习算法
K近邻: 适用于小型数据集,可作为基准模型,易于理解。
线性模型: 适用于大型数据集、高维数据集。
朴素贝叶斯: 只适用于分类问题。比线性模型速度快,适用于非常大的数据集和高维数据,但精度通常低于线性模型。
决策树: 速度快,不需要缩放数据,可视化显示,易于理解。
随机森林: 鲁棒性好很好,不需要缩放数据,不适用于高维数据。
梯度提升决策树: 精度比随机森林略高,训练速度稍慢但预测速度快,需要的内存也更少,比随机森林需要更多的参数。
支持向量机: 对于特征含义相似的中等大小的数据集很强大,需要缩放数据,对参数敏感。
神经网络: 对数据缩放敏感,对参数选取敏感,大型网络需要很长的训练时间。
K近邻
算法思想:找最近的邻居,出现次数更多的类别作为预测结果。
K-NN 分类
from sklearn.neighbors import KNeighbotsClassifier
'''
实现步骤:
1.实例化类(设置邻居个数)
2.利用训练集对分类器进行拟合
3.对测试集数据进行预测
4.评估模型的泛化能力
'''
clf = KNeighbotsClassifier(n_neighbors = 3)
clf.fit(X_train, y_train)
print("Test set predictions: {}".format(clf.predict(X_test)))
print("Test set accuracy: {:.2f}".format(clf.score(X_test, y_test)))
分析 KNeighbotsClassifier
决策边界: 算法对类别0和类别1的分界线。
随着邻居个数的增多,决策边界将趋于平滑,而更平滑的边界对应更简单的模型。
例如邻居个数为1~10之间:单一邻居时的测试机精度比使用更多邻居时要低,因为模型过于复杂;当考虑10个邻居时,模型又过于简单,性能或许会变差。最佳性能在中间的某处。
K_NN 回归
from Sklearn.neighbors import KNeighborsRegressor
'''
实现步骤:
1.实例化类(设置邻居个数)
2.利用训练集对分类器进行拟合
3.对测试集数据进行预测
4.评估模型的泛化能力
'''
clf = KNeighbotsClassifier(n_neighbors = 3)
clf.fit(X_train, y_train)
print("Test set predictions: {}".format(clf.predict(X_test)))
print("Test set R^2: {:.2f}".format(clf.score(X_test, y_test)))
注:对于分类问题,score方法返回的是R^2
分数。R^2
分数也叫做决定系数,是回归模型的优度度量,位于0~1之间。R^2
等于1对应完美预测,R^2
等于0对应常数模型,即总是预测训练集响应的平均数。
分析 KNeighborsRegressor
使用单一邻居,预测结果的图像结果所有的数据点,这导致预测结果非常不稳定。
考虑更多的邻居之后,预测结果变得更加平滑,但对训练数据的拟合会不好。
优缺点、参数
参数:
KNeighbors 分类器有两个重要参数:邻居个数、数据之间距离的度量方法
合理选择邻居个数(3~5)可以得到比较好的结果
数据之间距离的度量方法默认使用欧氏距离
优点:
- 容易理解,调节方便
- 是一种很好的基准方法
- 模型构建速度快(普通数据集)
缺点:
- 对于有很多特征的数据集效果往往不好
- 对于大多数取值都为0的特征的数据集(稀疏矩阵),效果尤其不好
K近邻实现
简单KNN分类器
对于分类未知的观察值,基于邻居的分类来预测它的分类。
n_jobs:控制可以使用多少个CPU内核
from sklearn.neighbors import KNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
iris = load_iris()
features = iris.data
target = iris.target
# 特征标准化
standardizer = StandardScaler()
features_std = standardizer.fit_transform(features)
# 实例化KNN分类器,邻居个数为5
knn = KNeighborsClassifier(n_neighbors=5, n_jobs=-1).fit(features_std, target)
# 创建两个观测值,并预测
new_data = [[0.75, 0.75, 0.75, 0.75],
[1, 1, 1, 1]]
knn.predict(new_data)
OUT:
array([1, 2])
基于半径的KNN分类器
对于分类未知的观测值,根据一定距离范围内所有观测值的分类来确定其分类。
from sklearn.neighbors import RadiusNeighborsClassifier
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
iris = load_iris()
features = iris.data
target = iris.target
# 特征标准化
standardizer = StandardScaler()
features_std = standardizer.fit_transform(features)
# 实例化一个基于半径的KNN分类器
rnn = RadiusNeighborsClassifier(n_neighbors=5, n_jobs=-1).fit(features_std, target)
# 创建两个观测值,并预测
new_data = [[1, 1, 1, 1]]
knn.predict(new_data)
OUT:
array([2])
线性模型
线性模型利用输入特征的线性函数(linear function)进行预测。
用于回归的线性模型
对于回归问题,线性模型预测的一般公式如下:
y
^
=
w
[
0
]
∗
x
[
0
]
∗
+
w
[
1
]
∗
x
[
1
]
∗
+
⋯
+
w
[
p
]
∗
x
[
p
]
∗
+
b
\hat y = w[0]^*x[0]^*+w[1]^*x[1]^*+\cdots+w[p]^*x[p]^*+b
y^=w[0]∗x[0]∗+w[1]∗x[1]∗+⋯+w[p]∗x[p]∗+b
x[0]~x[p] 表示的单个数据点的特征(特征个数为 p+1),w 和 b 是学习模型的参数,y 是模型的预测结果。
类比于高中数学的直线方程,这里 w[0] 是斜率,b 是y轴偏移。
对于具有更多特征的数据集,w包含沿每个特征坐标轴的斜率(权重)。
回归的线性模型:对于单一特征的预测结果是一条直线;两个特征时是一个平面;更高维时是一个超平面。
许多不同的线性回归模型,它们的区别在于如何从训练数据种学习参数 w 和 b ,以及如何控制模型复杂度。
常见的线性回归模型有:线性回归、岭回归、lasso。
线性回归
线性回归,又名普通最小二乘法(ordinary least squares,OLS)。
线性回归寻找参数 w 和 b ,使得对训练集和预测值与真实的回归目标值 y 之间的均方误差最小。均方误差(mean squares error)是预测值与真实值之差的平方和除以样本数。
from sklearn.linear_model import LinearRegression
'''
w 与 b:
1.w,也叫做权重或系数,被保存在 conef_ 属性中
2.b,也叫做偏移或截距,被保存在 intercept_ 属性中
3.intercept_ 是一个浮点数,而 conef_ 是一个Numpy数组,因为只有一个输入特征,所以 conef_ 只有一个元素
'''
print("lr.coef_: {}".format(lr.coef_))
print("lr.intercept_: {}".format(lr.intercept_))
'''
评估模型的泛化能力:
1.对训练集评估
2.对测试集评估
'''
print("Training set score: {:.2f}".format(lr.score(X_train, y_train)))
print("Test set score: {:.2f}".format(lr.score(X_test, y_test)))
注:score方法返回值为R^2分
数。
训练集和测试集上的分数非常接近,说明可能存在欠拟合。
训练集和测试集之间的性能差异是过拟合的明显标志。
线性模型没有参数,因此无法控制模型复杂度。标准线性回归最常用的替代方法之一就是岭回归(Ridge Regression)。
岭回归
岭回归是一种用于回归的线性模型,预测公式与普通最小二乘法相同。岭回归用到L2正则化。
from sklearn.linear_model import Ridge
ridge = Ridge().fit(X_train, y_train)
'''
评估模型的泛化能力:
1.对训练集评估
2.对测试集评估
'''
print("Training set score: {:.2f}".format(ridge.score(X_train, y_train)))
print("Test set score: {:.2f}".format(ridge.score(X_test, y_test)))
岭回归: 实质上是一种改良的最小二乘估计法,通过放弃最小二乘法的无偏性,以损失部分信息、降低精度为代价获得回归系数更为符合实际、更可靠的回归方法,对病态数据的拟合要强于最小二乘法。
正则化: 正则化是对模型做显式约束。就是在原来的loss function的基础上,加上了一些正则化项或者称为模型复杂度惩罚项,以便防止过拟合和提高模型泛化性能的一类方法的统称。(通过惩罚复杂模型来减小方差)。
L1正则化和L2正则化:
L1正则化和L2正则化可以看做是损失函数的惩罚项。所谓惩罚是指对损失函数中的某些参数做一些限制。对于线性回归模型,使用L1正则化的模型叫做Lasso回归,使用L2正则化的模型叫做Ridge回归(岭回归)。
L1正则化就是在loss function后边所加正则项为L1范数,加上L1范数容易得到稀疏解(0比较多)。L2正则化就是loss function后边所加正则项为L2范数的平方,加上L2正则相比于L1正则来说,得到的解比较平滑(不是稀疏),但是同样能够保证解中接近于0(但不是等于0,所以相对平滑)的维度比较多,降低模型的复杂度。
线性模型对数据存在过拟合,Ridge是一种约束更强的模型,所以更不容易过拟合。复杂度更小的模型意味着在训练集上的性能更差,但泛化性能更好。
**参数调节:**Ridge模型在模型的简单性(系数都趋于0)与训练集性能之间做出权衡。简单性和训练集性能对于模型的重要程度可由设置alpha
参数指定。alpha
默认参数为1.0,增大alpha会使得系数更加趋于0(约束增强),从而降低训练集性能,但可能会提高泛化性能。
注意:如果有足够多的训练数据,正则化变得不那么重要,并且岭回归和线性回归将具有相同的性能。如果添加更多的数据,模型将更难以过拟合或记住所有的数据。
lasso
与岭回归相同,使用lasso也是约束系数使其接近于0,lasso使用L1正则化。
L1正则化的结果是,使用lasso时,某些系数刚好为0(即为特征忽略),可看作是自动化的特征选择,可以呈现模型最重要的特征。
from sklearn.linear_model import Lasso
lasso = Lasso().fit(X_train, y_train)
'''
评估模型的泛化能力:
1.对训练集评估
2.对测试集评估
'''
print("Training set score: {:.2f}".format(ridge.score(X_train, y_train)))
print("Test set score: {:.2f}".format(ridge.score(X_test, y_test)))
# 查看所用特征的数量
print("Number of features used: {}".format(np.sum(lasso.coef_ != 0)))
Lasso的正则化参数alpha
,可以控制系数趋近于0的程度,默认值为1.0,为了降低欠拟合程度,可以减小alpha
,这么做的同时还需要加大 max_iter
的值(运行迭代最大次数)。如果把alpha
设的太小,就会消除正则化的效果。
alpha=0.1的Ridge模型和预测性能与alpha=0.01的Lasso模型类似。
总结
实践中,一般首选岭回归,但如果特征多且大多不重要,那么选择Lasso可能更好。
如果想要一个简单解释的模型,选择Lasso,因为它只选择了一部分输入特征。
sklearn
还提供了ElasticNet
类,结合了Lasso和Ridge的惩罚项,在实践中这种结合效果最好,但需要调节两个参数,分别用于L1和L2正则化。
用于二分类的线性模型
对于二分类问题,可以利用以下公式进行预测:
y
^
=
w
[
0
]
∗
x
[
0
]
∗
+
w
[
1
]
∗
x
[
1
]
∗
+
⋅
⋅
+
w
[
p
]
∗
x
[
p
]
∗
+
b
>
0
\hat y = w[0]^*x[0]^*+w[1]^*x[1]^*+··+w[p]^*x[p]^*+b>0
y^=w[0]∗x[0]∗+w[1]∗x[1]∗+⋅⋅+w[p]∗x[p]∗+b>0
对预测值设置了阈值(0),如果函数值小于0,就预测类别-1,如果函数值大于0,就预测类别+1。
用于回归的线性模型,输出 y 是特征的线性函数,是直线、平面或超平面。对于用于分类的线性模型,决策边界是输入的线性函数。也就是说,对于二分类问题,分类器是利用直线、平面或超平面俩分开两个类别的分类器。
线性模型的不同算法区别在于:
- 系数和截距的特定组合对训练集拟合好坏的度量方法
- 是否使用正则化,以及使用哪种正则化
最成功的两种线性分类算法是 Logistic回归(Logistic Regression)和 线性支持向量机(Linear Support Vector Machine,线性SVM)。两个模型默认使用L2正则化。
from sklearn.linear_model import LogisticRegression
from sklearn.svm import LinearSVC
# 调节正则化选项
lr_L1 = LogisticRegression(pennalty="l1")
lr_L2 = LogisticRegression(pennalty="l2")
C值: 对于这两个模型,决定正则化强度的权衡参数叫作C,默认为1。C值越大,对应的正则化越弱。(如果C值较大,那么模型尽可能将训练集拟合到最好;反之,模型更强调系数向量 w 接近于0)。
较小的C值可以让算法适应更多的数据点,而较小的C值更强调每个数据点都分类正确的重要性。
用于多分类的线性模型
将二分类算法推广到多分类算法的常见方法是”一对其余“方法。(多分类Logistic回归思想稍有不同,预测方法相同)。
每个类别都对应一个二分类器,这样每个类别都有一个系数向量和一个截距。
如下为分类置信方程,其结果中最大值对应的类别即为预测的类别标签:
w
[
0
]
∗
x
[
0
]
∗
+
w
[
1
]
∗
x
[
1
]
∗
+
⋅
⋅
+
w
[
p
]
∗
x
[
p
]
∗
+
b
w[0]^*x[0]^*+w[1]^*x[1]^*+··+w[p]^*x[p]^*+b
w[0]∗x[0]∗+w[1]∗x[1]∗+⋅⋅+w[p]∗x[p]∗+b
优缺点、参数
参数:
线性模型的最要参数是正则化参数,在回归模型中叫作 alpha ,在LinearSVC和Logistic中叫作 C
alpha 值较大或 C 值较小,说明模型简单(调参对于回归模型更为重要)
L1/L2选择:如果只有部分特征重要或解释性更重要,选择L1,否则默认使用L2
优点:
- 线性模型的训练速度快,预测也快
- 易于推广到大型数据集,对稀疏数据也很有效
- 10W以上的数据集,可考虑使用LogisticRegression和Ridge模型的
solver='sag'
选型 - 如果特征数量大于样本数量,线性模型的表现通常很好
- 扩展性更强的版本:SGDClassifier类和SGDRegressor类
缺点:
- 若数据集中包含高度相关的特征,可能弄不清楚参数为什么是这样的,很难对系数做出解释
- 在更低位的空间中,其他的模型的泛化性能可能会更好
线性回归实现
拟合模型
训练一个能表示特征和目标向量之间的线性模型。
# 加载库、数据集
from sklearn.linear_model import LinearRegression
from sklearn.datasets import load_boston
# 加载数据
boston = load_boston()
features = boston.data[:,0:2]
target = boston.target
# 模型实例化
regression = LinearRegression()
# 拟合线性回归模型
model = regression.fit(features, target)
处理特征间的影响
由于特征对目标变量的影响取决于另一个特征,需对该影响进行处理。
# 加载库
from sklearn.preprocessing import PolynomialFeatures
# 创建交互特征
polynomial = PolynomialFeatures(degree=3, include_bias=False, interaction_only=True)
feautre_polynomial = polynomial.fit_transform(features)
# 拟合线性回归模型
model = regression.fit(feautre_polynomial, target)
PolynomialFeatures:生成一个新的特征矩阵,该矩阵由度数小于或等于指定度数的特征的所有多项式组合组成。
通过正则化减小方差
线性回归用到正则化的模型:岭回归(L2)、Lasso(L1)。
减小线性回归模型的方差:
from sklearn.linear_model import Ridge
from sklearn.preprocessing import StandardScaler
# 特征标准化
scaler = StandardScaler()
features_standardized = scaler.fit_transform(features)
# 岭回归模型实例化,并指定alpha
ridge = Ridge(alpha=0.5)
# 拟合岭回归模型
model = ridge.fit(features_standardized, target)
使用Lasso回归减小特征
通过减小特征的数量来简化线性回归模型:
from sklearn.linear_model import Lasso
# Lasso模型实例化,并指定alpha
lasso = Lasso(alpha=0.5)
# 拟合Lasso回归模型
model = lasso.fit(features_standardized, target)
逻辑回归实现(Logistic)
二元分类器
若数据集过大,实例化回归对象时可设置参数:
solver="sag"
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
iris = load_iris()
features = iris.data[:100,:]
target = iris.target[:100]
# 标准化特征
standardizer = StandardScaler()
features_std = standardizer.fit_transform(features)
# 实例化一个回归对象
logistic_regression = LogisticRegression(random_state=0)
# 拟合模型
model = logistic_regression.fit(features_std, target)
多元分类器
逻辑回归的两种技巧:
一对多(One-vs-Rest,OVR)
多元逻辑回归(Multinomial Logistic Regression,MLR)
参数设置分别为:
multi_class="ovr"
、multi_class="multinomial"
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
iris = load_iris()
features = iris.data[:100,:]
target = iris.target[:100]
# 标准化特征
standardizer = StandardScaler()
features_std = standardizer.fit_transform(features)
# 实例化一个一对多的回归对象
logistic_regression = LogisticRegression(random_state=0, multi_class="ovr")
# 拟合模型
model = logistic_regression.fit(features_std, target)
通过正则化减小方差
调校正则化强度超参数C可适当减小逻辑回归模型的方差:
Cs:接受两类值,一类是用来搜索C的取值范围(浮点数列表),另一类是整型数值
from sklearn.linear_model import LogisticRegressionCV
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
iris = load_iris()
features = iris.data[:100,:]
target = iris.target[:100]
# 标准化特征
standardizer = StandardScaler()
features_std = standardizer.fit_transform(features)
# 实例化一个一对多的回归对象
logistic_regression = LogisticRegressionCV(random_state=0, n_jobs=-1, penalty='l2', Cs=10)
# 拟合模型
model = logistic_regression.fit(features_std, target)
处理不均衡的分类
class_weight:设置该参数可纠正不均衡分类的问题
balanced选项通常更有用,它根据各个分类在数据中出现的频率的倒数自动计算权重值 w j = n k n j w_j=\frac{n}{kn_j} wj=knjn
from sklearn.linear_model import LogisticRegression
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
import numpy as np
iris = load_iris()
features = iris.data
target = iris.target
# 删除前40个样本以获得高度不均匀的数据
features = features[40:,:]
target = target[40:]
# 创建目标向量表明分类为0还是1
target = np.where((target == 0), 0, 1)
# 标准化特征
standardizer = StandardScaler()
features_std = standardizer.fit_transform(features)
# 实例化一个回归对象
logistic_regression = LogisticRegression(random_state=0, class_weight="balanced")
# 拟合模型
model = logistic_regression.fit(features_std, target)
支持向量机实现(SVC)
线性分类器
用支持向量分类器(Support Vector Classifier,SVC)来寻找最大化分类之间的超平面:
from sklearn.svm import LinearSVC
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
import numpy as np
iris = load_iris()
features = iris.data[:100,:]
target = iris.target[:100]
# 标准化特征
standardizer = StandardScaler()
features_std = standardizer.fit_transform(features)
# 实例化一个支持向量机分类器
svc = LinearSVC(C=1.0)
# 拟合模型
model = logistic_regression.fit(features_std, target)
非线性分类器
使用核函数训练支持向量机的一个扩展,创建非线性决策边界:
kernel:选择核函数,一旦设置一个核函数,就要为核函数确定合适的参数,比如多项式核函数中的d(通过degree设置)、径向基核函数中的 γ \gamma γ(通过gamma设置)
查看预测分类的概率:
实例化分类器时,设置参数probability=True
,模型训练完后可使用predict_proba
方法输出观测值为每个类别的预测概率
识别支持向量:
support_vectors_
:该方法用来输出模型中观测值特征的
support_
:该方法可查看支持向量在观测值中的索引值
n_support_
:该函数可查看每个分类有几个支持向量
from sklearn.svm import SVC
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
import numpy as np
np.random.seed(0)
# 生成两个特征
features = np.random.randn(200, 2)
# 使用异或门创建线性不可分的数据
target_xor = np.logical_xor(features[:,0]>0, features[:,1]>0,)
target = np.where(target_xor, 0, 1)
# 实例化一个有径向基核函数的支持向量机
svc = SVC(C=1, random_state=0, kernel='rbf', gamma=1)
# 拟合模型
model = svc.fit(features, target)
处理不均衡分类
svc = SVC(class_weight="balanced")
朴素贝叶斯分类器
朴素贝叶斯分类器与线性模型非常相似,但它的训练速度往往更快。高效率的代价是,该分类器的泛化能力要比线性分类器(如LogisticRegression和LinearSVC)稍差。该模型高效原因在于:通过单独查看每个特征来学习参数,并从每个特征中收集简单的类别统计数据。
三种分类器
sklearn中实现了三种朴素贝叶斯分类器:
- GaussianNB:可用于任意连续数据,该分类器会保存每个类别中每个特征的平均值和标准差
- BernoulliNB:假定输入数据为二分类数据,该分类器计算每个类别中每个特征不为0的元素个数
- MultinomialNB:假定输入数据为计数数据,该分类器计算每个类别中每个特征的平均值
BernoulliNB 和 MultinomialNB 主要用于文本数据分析。这两个分类器的预测公式与线性模型完全相同,朴素贝叶斯模型的coef_
的含义与线性模型稍有不同,因为其不同于 w。
想要做出预测,需要数据点与每个类别的统计数据进行比较,并将最匹配的类别作为预测结果。
优缺点、参数
参数:
BernoulliNB 和 MultinomialNB 的参数 alpha,用于控制模型复杂度。alpha
越大,平滑化越强,模型复杂度就越低。算法性能对alpha
的鲁棒性相对较好,也就是说alpha
值对模型性能并不重要,但调整这个参数通常会使精度略有提高。
alpha的工作原理:
算法向数据中添加alpha这么多的虚拟数据点,这些点对所有特征都取正值。这可以将统计数据”平滑化“。
优点:
-
GaussianNB 主要用于高维数据,而另外两个广泛应用稀疏计数数据,比如文本
-
MultinomialNB 的性能优于 BernoulliNB ,特别是在包含很多非零特征的数据集(即大型文本)上
-
朴素贝叶斯模型对高维稀疏数据的效果很好,对参数的鲁棒性也相对较好
-
朴素贝叶斯模型是很好的基准模型,常用于非常大的数据集(费时间)
朴素贝叶斯分类器实现
BernoulliNB 分类器
数据的特征是连续的(非离散值):
from sklearn.naive_bayes import GaussianNB
from sklearn.datasets import load_iris
iris = load_iris()
features = iris.data
target = iris.target
# 实例化分类器
classifier = GaussianNB()
# 拟合模型
model = classifier.fit(features, target)
MultinomialNB 分类器
给定离散数据或者计数数据:
实例化时如果没有指定
class_prior
,模型会从数据中学习而得到先验概率,但如果想要用均匀分布计算先验概率的话,可以设置fit_prior=False
from sklearn.naive_bayes import MultinomialNB
from sklearn.feature_extraction.text import CountVectorizer
import numpy as np
# 创建文本
text_data = np.array(['I love Brazil. Brazil!', 'Brazil is best', 'Germany beats both'])
# 创建词袋
count = CountVectorizer()
bag_of_words = count.fit_transform(text_data)
# 创建特征矩阵
features = bag_of_words.toarray()
# 创建目标向量
target = np.array([0,0,1])
# 给定每个分类的先验概率,实例化一个分类器
classifier = MultinomialNB(class_prior=[0.25, 0.5])
# 拟合模型
model = classifier.fit(features, target)
BernoulliNB 分类器
训练具有二元特征的数据:
from sklearn.naive_bayes import BernoulliNB
import numpy as np
# 创建三个二元特征
features = np.random.randint(2, size=(100, 3))
# 创建一个二元目标向量
target = np.random.randint(2, size=(100,1)).ravel()
# 给定每个分类的先验概率,实例化一个分类器
classifier = BernoulliNB(class_prior=[0.25, 0.5])
# 拟合模型
model = classifier.fit(features, target)
校准预测概率
校准由朴素贝叶斯分类器的出预测概率,它们可以被解释:
校准(calibration):
创建经由k折交叉验证调教过的预测概率,训练集被用来训练模型,测试集被用来校准预测概率,返回的预测概率是k折的平均值
from sklearn.naive_bayes import GaussianNB
from sklearn.calibration import CalibratedClassifierCV
from sklearn.datasets import load_iris
iris = load_iris()
features = iris.data
target = iris.target
# 实例化分类器
classifier = GaussianNB()
# 创建使用sigmoid校准调校过的交叉验证模型
classifier_sigmoid = CalibratedClassifierCV(classifier, cv=2, method='sigmoid')
# 校准概率
classifier_sigmoid.fit(features, target)
# 创建新的观察值
new_data = [[2.6, 2.6, 2.6, 0.4]]
# 查看校准后的概率
classifier_sigmoid.predict_proba(new_data)
决策树
本质上,它是一出场的 if/else
问题中进行学习,并得出结论。
构造决策树
为了构造决策树,算法搜遍所有可能的测试,找出对目标变量来说信息量最大的那一个。
决策时可以用于回归任务,预测方法是:基于每个节点的测试对数进行遍历,最终找到新数据点所属的叶节点。这一数据点的输出即为此叶节点中左右训练点的平均目标值。
from sklearn.tree import DecisionTreeClassifier
from sklearn.tree import DecisionTreeRegression
tree_dtc = DecisionTreeClassifier(random_state = 0)
tree_dtr = DecisionTreeRegression(random_state = 0)
控制决策树的复杂度
通常来说,构造决策树知道所有叶节点都是纯的叶节点,这导致模型非常复杂,并且对训练数据高度过拟合,对新数据的泛化性能不佳。
防止过拟合的方法有:预剪枝、后剪枝。
- 预剪枝:及早停止树的生长,限制条件可能包括限制树的最大深度、限制叶节点的最大数目或规定一个节点中数据点的最小数目
- 后剪枝:先构造树,随后删除或折叠信息量很少的节点
注:sklearn只实现了预剪枝,没有实现后剪枝
构造决策树时,设置参数 max_depth
可控制树的深度。这会降低训练集的精度,但可以提高测试集的精度。
分析决策树
可以利用 tree
模块的 export_graphviz
函数来将树可视化,这个函数会生成一个 .dot
格式的文件,这是一种用于保存图形的文本文件格式。
from sklearn.tree import export_graphviz
export_graphviz(tree, out_file='tree.dot', class_names=["malignant","bengin"],
feature_names=data.feature_names, impurity=False, filled=True)
# 利用graphviz模块读取整个文件并可视化
import graphviz
with open("tree.dot") as f:
dot_graph = f.read()
graphviz.Source(dot_graph)
树特征的重要性
特征重要性(Feature Importance):它为每个特征对树的决策的重要性进行排序,值为0~1。
print("Feature Importance: {}".format(tree.feature_importances_))
注:如果某个特征的feature_importances_
很小,说明该特征没有被树选中,可能因为另一个特征包含了同样的信息。
与线性模型不同,特征重要性始终为正数,不能说明该特征对应哪个类别。
回归树
回归树的用法与分类树非常相似,回归树不能外推,也不能在训练数据范围之外进行预测。
优缺点、参数
参数:
预剪枝策略(设置 max_depth
、max_leaf_nodes
、min_samples_leaf
)
优点:
- 得到的模型易于可视化,易于理解
- 算法完全不接受数据缩放的影响(即为无影响)
- 特征的尺度完全不一致时或二元特征和连续特征同时存在时,决策树效果很好
缺点:
- 即便做了预剪枝,也经常会过拟合,泛化性能差
树的实现
决策分类器
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
iris = load_iris()
features = iris.data
target = iris.target
# 决策树分类器实例化
decisiontree = DecisionTreeClassifier(random_state=0)
# 拟合决策树分类器
model = decisiontree.fit(features, target)
决策树回归
from sklearn.tree import DecisionTreeRegressor
from sklearn.datasets import load_boston
boston = load_boston()
features = boston.data[:,0:2]
target = boston.target
# 决策树回归模型实例化
decisiontree = DecisionTreeRegressor(random_state=0)
# 拟合决策树回归模型
model = decisiontree.fit(features, target)
可视化决策树模型
方法一:
import pydotplus
from sklearn.tree import DecisionTreeRegressor
from sklearn import tree
from IPython.display import Image
from sklearn.datasets import load_iris
iris = load_iris()
features = iris.data
target = iris.target
decisiontree = DecisionTreeRegressor(random_state=0)
model = decisiontree.fit(features, target)
# 创建DOT数据
dot_data = tree.export_graphviz(decisiontree,out_file=None,
feature_names=iris.feature_names,
class_names=iris.target_names)
# 绘制图形
graph = pydotplus.graph_from_dot_data(dot_data)
# 显示图形
Image(graph.create_png())
方法二:
from sklearn.tree import export_graphviz
from sklearn.tree import DecisionTreeRegressor
decisiontree = DecisionTreeRegressor(random_state=0)
model = decisiontree.fit(features, target)
export_graphviz(decisiontree,out_file="tree.dot", feature_names=iris.feature_names,
class_names=iris.target_names,impurity=False, filled=True)
import graphviz
with open("tree.dot") as f:
dot_graph = f.read()
graphviz.Source(dot_graph)
控制决策树的规模
max_depth:树的最大深度
min_samples_split:在该节点分裂之前,节点上最小的样本数
min_samples_leaf:叶子节点需要的最小样本数
max_leaf_nodes:最大叶子节点数
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import load_iris
iris = load_iris()
features = iris.data
target = iris.target
# 决策树分类器实例化
decisiontree = DecisionTreeClassifier(random_state=0, max_depth=None, min_samples_split=2,
min_samples_leaf=1, min_weight_fraction_leaf=0,
max_leaf_nodes=None, min_impurity_decrease=0)
# 拟合决策树分类器
model = decisiontree.fit(features, target)
决策树集成
集成(Ensemble)是合并多个机器学习模型来构建更强大模型的方法。俱已证明,有两种集成模型对大量分类和回归都是有效的,二者都是以决策树为基础,分别是随机森林(Random Forest)和梯度提升决策树(Gradient Boosted Decision Tree)。
随机森林
决策树的主要缺点在于过拟合,随机森林就是解决这一问题的方法。
随机森林本质上是许多决策树的集合,并且每棵树的预测都很好,但都以不同的方式过拟合,那么我们可以对这些树的结果取平均值来降低过拟合。
随机森林中树的优化方法有两种:
- 通过选择用于构造树的数据点
- 通过选择每次划分测试的特征
构造随机森林
构造过程: 采用自助采样的方法创建新的数据集来构造决策树。在每一个节点处,算法随机选择特征的一个子集,并只对其中一个特征寻找最佳测试。选择特征的个数由 max_features
参数来控制(每棵树的随机性大小)。每个节点中特征子集的选择是相互独立的,这样树的每个节点可以使用特征的不同子集来做出决策。
自助采样(Bootstrap sample):从 n_samples 个数据点中有放回的重复抽取一个样本,共抽取 n_samples 次。这样会创建一个与原数据集大小相等的数据集,但有些数据点会消失(大约1/3),有些会重复。
from sklearn.ensemble import RandomForestClassifier
forest = RandomForestCalssifier(n_estimators=5, random_state=2)
注:n_estimators
为数的个数
由于使用了自助采样,随机森林中构造每颗决策树的数据集是略有不同的,由于每个节点的特征选择,每棵树中的划分都是基于特征的不同子集,这两种方法共同保证随机森林所有树都不同。
若利用随机森林进行预测,算法首先对每棵树进行预测。对于回归问题,对结果取平均作为最终预测;对于分类问题,则用”软投票“策略,即对所有树预测概率取均值,将概率最大的类别作为预测结果。
分析随机森林
随机森林比单独每一棵树的过拟合都要小,给出的决策边界也更符合直觉。
随机森林也可以给出特征重要性,计算方法是将森林中所有数的特征重要性求和取平均。
由于构造随机森林过程中的随机性,算法需要考虑多种可能的解释,结果就是随机森林比单棵树更能从总体把握数据的特征。
优缺点、参数
参数:
n_estimators
:总是越大越好,对更多的树取平均可以降低过拟合,从而得到鲁棒性更好的集成(更耗内存)max_features
:较小的值可以降低过拟合,可使用默认值。对于分类,默认值是sqrt(n_features)
;对于回归,默认值是n_features
- 可能包括预剪枝选项(如
max_depth
)
增大 max_features
或 max_leaf_nodes
有时也可以提高性能,它还可以大大降低用于训练和预测的时间和空间要求。
优点:
- 本质上是随机的,设置不同的随即状态(random_state)可以改变构建的模型
- 数越多,它对随机状态选择的鲁棒性越好
- 即使非常大的数据集,随机森林的表现通常也很好
缺点:
- 对于位数非常高的稀疏矩阵(比如文本),随机森林往往表现不好
- 消耗内存,训练和预测速度较慢
梯度提升回归树
通过合并决策树来构建一个更加强大的模型,该模型可用于回归和分类。
与随机森林不同,梯度提升采用连续的方式构造树,每棵树都试图纠正前一棵树的错误。
默认情况下,梯度提升回归树没有随机化,而是用到了强预剪枝,深度通常1~5之间,先内存少,预测速度更快。
**梯度提升的主要思想:**合并许多简单的模型(弱学习器),比如深度较小的树。每棵树只能对部分数据做出好的预测,因此,添加的树越多,可以不断迭代提高性能。
构造梯度提升回归树
from sklearm.ensemble import GradientBoostingClassifier
gbrt = GradientBoostingClassifier(random_state=0)
分析梯度提升回归树
为了降低过拟合,可以限制最大深度来加强预剪枝或降低学习率。降低模型复杂度的方法都降低了训练集精度。减小树的最大深度显著提升了模型性能,二降低学习率仅稍稍提高了泛化性能。
在特征重要性方面,梯度提升可能会完全忽略某些属性。
优缺点、参数
参数:
n_estimators
:值增大会导致模型更加复杂,进而可能导致过拟合learn_rate
:用于控制每棵树对前一棵树错误二点纠正强度,值降低,会需要更多的树来构建具有相似复杂度的模型max_depth
(或max_leaf_nodes
):用于降低每棵树的复杂度,梯度提升模型的max_depth
通常很小(一般不超过5)
n_en_stimators
与 learn_rate
高度相关。通常做法是根据时间可内存的预算选择合适的 n_en_stimators
,然后对不同的 learn_rate
进行遍历
优点:
- 不需要对数据缩放就可以表现很好
- 也适用于二元特征与连续特征同时存在的数据集
缺点:
- 需要仔细调参,而且训练时间可能比较长
- 与其他基于树的模型相同,通常不适用于高维稀疏矩阵
模型选择
由于梯度提升和随机森林两种方法在类似的数据上表现的都很好,因此一种常用的方法就是先尝试随机森林,它的鲁棒性很好。如果随机森林效果很好,但预测时间太长,或者机器学习模型精度小数点后第二位的提高也很重要,那么切换成梯度提升通常会有用。
决策树集成实现
训练随机森林分类器
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
iris = load_iris()
features = iris.data
target = iris.target
# 随机森林分类器实例化
randomforest = RandomForestClassifier(random_state=0, n_jobs=-1)
# 拟合随机森林分类器
model = randomforest.fit(features, target)
训练随机森林回归
from sklearn.ensemble import RandomForestRegressor
from sklearn.datasets import load_boston
boston = load_boston()
features = boston.data[:,0:2]
target = boston.target
# 决策树回归模型实例化
randomforest = RandomForestRegressor(random_state=0, n_jobs=-1)
# 拟合决策树回归模型
model = randomforest.fit(features, target)
选择随机森林中的重要特征
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_selection import SelectFromModel
from sklearn.datasets import load_iris
iris = load_iris()
features = iris.data
target = iris.target
randomforest = RandomForestClassifier(random_state=0, n_jobs=-1)
# 实例化对象,选择重要性大于或等于阈值的特征
selector = SelectFromModel(randomforest, threshold=0.3)
# 使用选择器创建新的特征矩阵
features_important = selector.fit_transform(features, target)
# 拟合随机森林分类器
model = randomforest.fit(features_important, target)
处理不均衡的分类
randomforest = RandomForestClassifier(class_weight='balanced')
通过boosting提高性能
使用AdaBoostClassifier或AdaBoostRegressor训练一个boosting模型:
boosting算法: 有一种形式的boosting算法叫作AdaBoost,它迭代地训练一系列弱模型,每次迭代都会为前一个模型预测错的样本分配更大的权重。
AdaBoost: 重要的参数是base_estimators、n_estimators、learning_rate
base_estimators:表示训练弱模型的学习算法,默认值为决策树
n_estimators:需要迭代训练的模型数量
learning_rate:每个弱模型的权重变化率,默认值为1
loss:是AdaBoostRegressor独有的参数,它设置了在更新权重时所有的损失函数,默认值为线性损失函数
from sklearn.ensemble import AdaBoostClassifier
from sklearn.datasets import load_iris
iris = load_iris()
features = iris.data
target = iris.target
# 随机森林分类器实例化
adaboost = AdaBoostClassifier(random_state=0)
# 拟合随机森林分类器
model = adaboost.fit(features, target)
使用袋外误差评估随机森林模型
袋外误差(Out-of-Bag Error):
在随机森林中,每个决策树使用自举的样本子集进行训练,因此对每棵树而言都有未参与训练的样本子集,这些样本子集被称为袋外(Out-of-Bag,OOB)样本。袋外样本可作为测试集来评估随机森林的性能。OOB评估法可作为交叉验证的替代方案。
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_iris
iris = load_iris()
features = iris.data
target = iris.target
# 随机森林分类器实例化
randomforest = RandomForestClassifier(random_state=0, n_jobs=-1,
n_estimators=1000, oob_score=True)
# 拟合随机森林分类器
model = randomforest.fit(features, target)
# 查看袋外误差
randomforest.oob_score_
核支持向量机
线性支持向量机用于分类任务,核支持向量机(Kernelized Support Vector Machine,SVM)是可以推广到更复杂模型的扩展,这些模型无法被输入空间的超平面定义。
虽然支持向量机可以同时用于分类和回归,但以下只谈分类情况。支持向量分类实现在SVC中;支持向量回归实现在SVR中。
from sklearn.svm import SVC
form sklearn.svm import SVR
svc = SVC()
svr = SVR()
线性模型与非线性特征
线性模型在低维空间中受限,因为线和平面的灵活性有限。添加更多的特征(升维)可让线性模型更加灵活,例如添加输入特征的交互项或多项式。
向数据表示中添加非线性特征,可以让线性模型变得更强大。
核技巧
核技巧(Kernel Trick):它的原理是直接计算扩展特征表示中数据点之间的距离(内积),而不是实际对扩展进行计算。
对于支持向量机,将数据映射到更高维空间中由两种常见的方法:多核项式、径向基函数核。
- 多核项式:在一定阶数内计算原始特征所有可能的多项式(比如
feature1**2*feature2**5
) - 径向基函数(Radial Basis Function,RBF)核,也叫高斯核。
高斯核有点难解释,因为它对应无限维的特征空间。一种对高斯核的解释是它考虑所有阶数的所有可能的多项式,但阶数越高,特征的重要性越小。
理解SVM
在训练过程中,SVM学习每个训练数据点对与表示两个类别之间的决策边界的重要性。
通常只有一部分训练数据点对于定义决策边界来说很重要:位于类别之间边界上的那些点。
这些点叫作支持向量(Support Vector),支持向量机由此得名。
预测新数据,需要测量它与每个支持向量之间的距离。分类决策是基于它与支持向量之间的距离以及在训练过程中学到的支持向量重要性(保存在SVR的 dual_coef_
属性中)来做出的。数据点之间的距离由高斯核给出:
k
r
b
f
(
x
1
,
x
2
)
=
e
x
p
(
−
γ
∣
∣
x
1
−
x
2
∣
∣
2
)
k_{rbf}(x_1, x_2) = exp(-\gamma ||x_1-x_2||^2)
krbf(x1,x2)=exp(−γ∣∣x1−x2∣∣2)
x_1、x_2是数据点,||x_1-x_2||表示欧氏距离,γ(gamma)是控制高斯核宽度的参数。
SVM调参
gamma 参数用于控制高斯核的宽度,它决定了点与点之间”靠近“是指多大的距离。小的 gamma 值表示决策边界变化很慢,生成的是复杂度较低的模型,而大的 gamma 值则会生成更为复杂的模型。
C 参数是正则化参数,与线性模型中用到的相似,它限制每个点的重要性(每个点的 dual_coef_
)。与线性模型相同,C 值很小,说明模型非常受限,每个数据点的影响范围都有限;增大 C 值,数据点对模型的影响变大,使得决策边界发生弯曲来将数据点正确分类。
SVM对参数的设定核数据的缩放非常敏感,它要求所有特征有相似的变化范围,因此需要数据预处理。
为SVM预处理数据
解决上面的问题的一种方法是特征缩放,使其大致位于同一范围。核SVM常用的缩放方法是将所有特征缩放到0~1之间。
优缺点、参数
参数:
核SVM的重要参数是正则化参数C、核的选择以及核的相关参数。RBF核只有一个参数 gamma ,它是高斯核宽度的倒数。gamma 和 C 控制的都是模型复杂度,较大的值都对应更为复杂的模型,因此这两个强度相关的参数需要同时调节。
优点:
- SVM允许决策编辑很复杂,即使特征只有几个
- 它在低维数据和高维数据上的表现都很好
- 在多达1w个样本的数据数据上运行SVM可能表现很好
缺点:
- 对样本的缩放表现不好
- 预处理和调参都要非常小心
- SVM模型很难检查,很难解释
- 如果数量达到10w甚至更大,在运行时间和内存使用方面可能会面临挑战
神经网络
多层感知机(Multilayer Perceptron,MLP),可以作为研究更复杂的深度学习方法的起点,MLP也被称为前馈神经网络,有时也简称为神经网络。(MLP可被视为广义的线性模型)
神经网络模型
神经网络包含三个部分:输入层(Input Layer)、隐藏层(Hidden Layer)、输出层(Output Layer)。
权重: 表示相邻两层不同神经元连接的强度,权重决定了输入对输出影响的大小。
激活函数
激活函数: 给神经元中引入非线性函数以避免线性模型输出,激活函数包含Sigmoid、Tanh、ReLU等。
Sigmoid
Sigmoid又叫做Logistic激活函数,该函数的输出范围是(0,1),相当于对每个神经元的输出进行了归一化处理。
函数表达式:
S
i
g
m
o
i
d
(
x
)
=
σ
(
x
)
=
1
1
+
e
−
x
Sigmoid(x)=\sigma(x)=\frac{1}{1+e^{-x}}
Sigmoid(x)=σ(x)=1+e−x1
x = np.linspace(-10,10)
y_sigmoid = 1/(1+np.exp(-x))
plt.plot(x,y_sigmoid)
plt.legend(["Sigmoid"])
特点:
- 函数可微分
- 预测值为0~1之间,单调连续,优化稳定
- 归一化
缺点:
- 梯度消失:Sigmoid函数由于饱和性,容易产生梯度消失
- 函数输出不以0为中心:输出值始终大于0,这会降低权重跟新的效率,从而影响收敛速度
- 梯度爆炸:输入值趋于0时,将造成梯度爆炸
- 计算成本高、运算速度慢
Tanh
Tanh(Hyperbolic Tangent,双曲正切)函数与Sigmoid较为相似,但更具优势,它解决了Sigmoid中的 zero-centered 问题,该函数的输出范围是(-1,1)。
函数表达式:
T
a
n
h
(
x
)
=
t
a
n
h
(
x
)
=
e
x
−
e
−
x
e
x
+
e
−
x
Tanh(x)=tanh(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}}
Tanh(x)=tanh(x)=ex+e−xex−e−x
x = np.linspace(-10,10)
y_tanh = (np.exp(x)-np.exp(-x))/(np.exp(x)+np.exp(-x))
plt.plot(x,y_tanh)
plt.legend(["Tanh"])
优点:
- Tanh函数的输出以0为中心
- Tanh函数比Sigmoid函数收敛更快
缺点:
- 梯度消失
- 梯度爆炸
ReLU
ReLU函数又叫做“修正线性单元”或“线性整流函数”,该函数的输出范围是[0, + ∞ +\infty +∞)。
函数表达式:
R
e
L
U
(
x
)
=
(
x
)
+
=
m
a
x
(
0
,
x
)
ReLU(x)=(x)^+=max(0,x)
ReLU(x)=(x)+=max(0,x)
x = np.linspace(-10,10)
y_relu = np.array([0*item if item<0 else item for item in x ])
plt.plot(x,y_relu)
plt.legend(["Relu"])
优点:
- 当输入为正时,不存在梯度饱和的问题
- 计算速度快,只需要判断是否大于0
- 因为函数中只存在线性关系,收敛速度比Sigmoid和Tanh更快
缺点:
- 输入为负时,ReLU函数完全失效
- 反向传播过程中,梯度为0,权重无法更新,网络不能学习
神经网络实现
import torch
from torch.autograd import Variable
import torch.nn.functional as F
import matplotlib.pyplot as plt
'''
x:
1.首先创建一个一维张量,值为Tensor
2.unsqueeze方法返回一个新张量,在指定位置插入尺寸为1的张量。(即为升高一维)。
3.dim为要插入单元素维度的索引
y:
1.x.pow(2),二次方
2.0.2*torch.randn(x.size()),添加噪点
'''
x = torch.unsqueeze(torch.linspace(-1,1,100), dim=1)
y = x.pow(2) + 0.1*torch.randn(x.size())
x, y = Variable(x), Variable(y)
# plt.scatter(x.data.numpy(), y.data.numpy())
# plt.show
'''
搭建神经网络
__init__:
1.输入层神经元、隐藏层神经元、输出层神经元的个数
2.继承父类的方法
3.搭建一个隐藏层,隐藏层包含输入和输出,输入为输入层神经元个数,输出为隐藏层神经元个数
4.搭建一个输出层,输入为隐藏层神经元个数,输出为输出神经元个数
forward:
1. 使用激活函数激活隐藏层加工后的信息
2.利用输出层预测并输出
(输出层不需要激励函数,避免被截断数值)
'''
class Net(torch.nn.Module):
def __init__(self, n_feature, n_hidden, n_output):
super(Net, self).__init__()
self.hidden = torch.nn.Linear(n_feature, n_hidden)
self.predict = torch.nn.Linear(n_hidden, n_output)
def forward(self, x):
x = F.relu(self.hidden(x))
x = self.predict(x)
return x
# 实例化一个神经网络
net = Net(1, 10, 1)
print(net)
'''
optimier(优化器):
1.SGD(梯度下降):优化神经网络所有参数(net.parameters())
2.lr(learning_rate):学习效率
loss_func(计算误差):
1.MSELoss():均方差,用于回归问题
'''
optimizer = torch.optim.SGD(net.parameters(), lr=0.5)
loss_func = torch.nn.MSELoss()
# 实时打印
plt.ion()
plt.show()
'''
训练模型:
1.训练100步
2.计算预测值与真实值的对比
3.优化步骤
4.可视化:每5步打印一次
'''
for t in range(100):
prediction = net(x)
loss = loss_func(prediction, y)
optimizer.zero_grad() # 将多有参数的梯度降维0
loss.backward() # 反向传递过程,计算结点的梯度
optimizer.step() # 优化梯度,学习效率为0.5
if t % 2 == 0:
plt.cla()
plt.scatter(x.data.numpy(), y.data.numpy()) # 原始数据
plt.plot(x.data.numpy(), prediction.data.numpy(), 'r-', lw=5) # 学习的数据
plt.text(0.5, 0, 'Loss= %.4f' % loss.item(), fontdict={'size':20, 'color':'red'})
plt.pause(0.1)
plt.ioff()
plt.show()
优缺点、参数
参数:
通常是创建一个大到过拟合的网络,以确保可以对任务进行学习,而后缩小网络。增大alpha可增强正则化,能够提高泛化性能。估计神经网络的复杂度,重要的参数是层数和每层的隐单元个数,隐层和逐渐增大,隐层的节点个数通常与输入特征个数接近。
优点:
能过全面的获得数据中包含的信息,并构建无比复杂的模型。
缺点:
-
训练时间长
-
需要数据预处理
forward:
- 使用激活函数激活隐藏层加工后的信息
2.利用输出层预测并输出
(输出层不需要激励函数,避免被截断数值)
‘’’
- 使用激活函数激活隐藏层加工后的信息
class Net(torch.nn.Module):
def init(self, n_feature, n_hidden, n_output):
super(Net, self).init()
self.hidden = torch.nn.Linear(n_feature, n_hidden)
self.predict = torch.nn.Linear(n_hidden, n_output)
def forward(self, x):
x = F.relu(self.hidden(x))
x = self.predict(x)
return x
```python
# 实例化一个神经网络
net = Net(1, 10, 1)
print(net)
'''
optimier(优化器):
1.SGD(梯度下降):优化神经网络所有参数(net.parameters())
2.lr(learning_rate):学习效率
loss_func(计算误差):
1.MSELoss():均方差,用于回归问题
'''
optimizer = torch.optim.SGD(net.parameters(), lr=0.5)
loss_func = torch.nn.MSELoss()
# 实时打印
plt.ion()
plt.show()
'''
训练模型:
1.训练100步
2.计算预测值与真实值的对比
3.优化步骤
4.可视化:每5步打印一次
'''
for t in range(100):
prediction = net(x)
loss = loss_func(prediction, y)
optimizer.zero_grad() # 将多有参数的梯度降维0
loss.backward() # 反向传递过程,计算结点的梯度
optimizer.step() # 优化梯度,学习效率为0.5
if t % 2 == 0:
plt.cla()
plt.scatter(x.data.numpy(), y.data.numpy()) # 原始数据
plt.plot(x.data.numpy(), prediction.data.numpy(), 'r-', lw=5) # 学习的数据
plt.text(0.5, 0, 'Loss= %.4f' % loss.item(), fontdict={'size':20, 'color':'red'})
plt.pause(0.1)
plt.ioff()
plt.show()
优缺点、参数
参数:
通常是创建一个大到过拟合的网络,以确保可以对任务进行学习,而后缩小网络。增大alpha可增强正则化,能够提高泛化性能。估计神经网络的复杂度,重要的参数是层数和每层的隐单元个数,隐层和逐渐增大,隐层的节点个数通常与输入特征个数接近。
优点:
能过全面的获得数据中包含的信息,并构建无比复杂的模型。
缺点:
- 训练时间长
- 需要数据预处理