升维与降维介绍以及代码实现

升维的目的:

升维的目的是去解决欠拟合的问题,以提高模型的准确率为目的。

研究一个因变量与一个或多个自变量间多项式的回归分析方法,称为多项式回归(Polynomial Regression)。如果自变量只有一个时,称为一元多项式回归;如果自变量有多个时,称为多元多项式回归。在一元回归分析中,如果依变量y与自变量x的关系为非线性的,但是又找不到适当的函数曲线来拟合,则可以采用一元多项式回归。

一元m次多项式回归方程为:

二元二次多项式回归方程为:

当数据X,y呈现一种非线性(X是二次方甚至更高阶)的关系时候,即y不是随着X线性变换的时候,我们有两种选择

一:用非线性的算法(回归树,神经网络)拟合非线性的数据。

二:用线性算法,但是需要将数据进行升维。

例二阶多项式升维:

\hat{y} = W0 + W1X1 + W2X2

X1、X2扩展成X_{1},X_{2},X{_{1}}^{2},X{_{2}}^{2},X_{1}X_{2}

升维后多计算三个维度

\hat{y} = W_{0} + W_{1}X_{1} + W_{2}X_{2} + W_{3}X_{1}^{2} + W_{4}X_{2}^{2} + W_{5}X_{1}X_{2}

import matplotlib.pyplot as plt
import numpy as np
import matplotlib.pyplot as ply
from sklearn.preprocessing import PolynomialFeatures
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error

np.random.seed(42)
m = 100
X = 6*np.random.rand(m, 1) - 3
y = 0.5*X**2 + X + 2 + np.random.randn(m, 1)
plt.plot(X, y, 'b.')
plt.show()


X_train = X[:80]
y_train = y[:80]
X_test = X[80:]
y_test = X[80:]

d = {1: 'g-', 2:'r+', 10:'y*'}
for i in d:
    # degree升到几维,include_bias是否要截距项
    # interaction_only()是否只生成交互项,默认是False,我们可以设置True可以一定程度上避免数据共线性。
    poly_features = PolynomialFeatures(degree=i, include_bias=True)
    X_poly_train = poly_features.fit_transform(X_train)
    X_poly_test = poly_features.fit_transform(X_test)
    print(X_train[0])
    print(X_poly_train[0])
    print(X_train.shape)
    print(X_poly_train.shape)

C:\ProgramData\Anaconda3\python.exe C:/Users/10509/Desktop/AIStudy/多项式回归(升维).py
[-0.75275929]
[ 1.         -0.75275929]
(80, 1)
(80, 2)
[-0.75275929]
[ 1.         -0.75275929  0.56664654]
(80, 1)
(80, 3)
[-0.75275929]
[ 1.         -0.75275929  0.56664654 -0.42654845  0.32108831 -0.2417022
  0.18194358 -0.13695972  0.1030977  -0.07760775  0.05841996]
(80, 1)
(80, 11)

Process finished with exit code 0

降维的目的

在准备数据的过程中,我们有可能要筛选一些不必要的特征。

1.手动的选择

2.不适合手动选择的有两种方式

Filter(过滤式)

Embedded(嵌入式)

方差过滤

过滤式是对方差进行过滤,方差为0说明这一列的数据是一样的。

那我们进行刷选的时候,就可以将方差为0或者方差比较小的特征删除掉。

sklearn代码

from sklearn.feature_selection import VarianceThreshold

# sklearn特征选择,删除低方差的特征
def var():
    # 删除特征为0的的数据
    va = VarianceThreshold(threshold=0)
    data = va.fit_transform([[80, 79, 1, 14], [80, 111, 33, 754], [80, 234, 11, 23]])
    print(data)

# 获取这列数据的方差
np.median(X.var().values())
 

这种降维方法直接减少数据的特征,对于KNN一类的算法,能明显提高算法速度(因为KNN遍历所有的特征进行距离计算)。

但是对于树类的算法,减少特征维度并不能显著提高效果,因为像随机森林这类的算法每次计算只会选择固定数目的特征维度进行计算。

当然对于单颗决策树,减少特征维度的方法可以提高速度,因为对于单颗决策树而言,也需要抽取大量的特征才能得到准确的效果。

但是决策树并不需要保证每颗决策树都要很满意的效果,多以对于随机森林中的单颗决策树,只要抽取部分特征,使其有一些准确率就可以了。

一般我们先使用方差过滤直接过滤掉方差为0或者方差很小的特征(因为使用方差过滤的模型消耗的时间真的很长例如KNN),先把比较明显的噪音过滤掉,在使用其他降维方法进行筛选

主成分分析(PCA降维)

目的:

是数据维数压缩,尽可能降低原数据的维数(复杂度)。

1.让数据减少特征维度的前提下依然能保留原数据的大部分信息

2.减少噪声。

在现实中我们拿到的数据都是有噪音的,那么我们就可以拿到的原数据带有噪音的数据进行PCA降维,降维后再还原就可以得到降噪的数据。

一般特征数量达到上百个的时候,就要考虑要不要考虑简化特征。使用PCA会使得数据进行降维,但是数据也会去改变。(如果特征值有几个或者十几个,就没有必要用PCA 。)

PCA降维在简化数据集的时候会把损失简化到最小。

(使用PCA降维如果留下的维度过多,就达不到降维的效果,如果留下的特征太少,那么新特征就可能无法容纳原始数据集中的信息。)

 代码:

from sklearn.decomposition import PCA

def pca():
    # 主成分分析进行降维,PCA参数不填返回最小的维度,例如原数据(1294,463),返回463
    pca = PCA(n_components=0.95)
    data = pca.fit_transform([[80, 79, 1, 14], [80, 111, 33, 754], [80, 234, 11, 23]])
    print(data)
    
    # 将降维后的数据进行逆转,转会降维前的维数,但是因为中见经过降维所以特征信息会有丢失,不可能百分百的恢复到降维前的数据信息。   
    # 通过inverse_transform还原后的数据就是减少噪声后的数据。
    X_inverse = pca.inverse_transform(data)

    # 查看降维后每个新特征上所带的信息量大小,大部分有效特征都会集中在第一个特征上
    print(pca.explained_variance_)
    # [4.22824171 0.24267075]

    # 查看降维后新特征向量信息量所占原始数据信息量百分比(可解释性方差比)
    print(pca.explained_variance_ratio_.sum())
    # [0.92461872 0.05306648]这两个数据加和就是原有数据保留的信息占比

    # 对所有特征数据进行PCA降维, mle让sklearn自己选择最好的取值(但是计算量太大,如果数据量态度,有可能崩掉)
    pca = PCA(n_components='mle')
    X_pca = pca.fit_transform(X)

    # 直接设置保留多少百分比的信息量
    pca_f = PCA(n_components=0.97, svd_solver='full')
    pca_f.fit_transform(X)

    # 直接设置减少的维度
    pca = PCA(n_components=0.95)

 

Embedded嵌入法

嵌入法是一种让算法自己决定使用哪些特征的方法,即特征选择和算法同时进行。

在使用嵌入法时,会使用某些机器学习的算法和模型进行训练,得到各个特征的权值系数,根据权值大小选择特征,权值数往往代表了特征对模型的某种贡献或者重要性。

比如决策树和随机森林集成模型中的feature_importances_。

(通过算法评估完成特征子集的选择,每次选择会使用全部特征。)

from sklearn.feature_selection import SelectFromModel

import matplotlib.pyplot as plt
from sklearn.feature_selection import SelectFromModel
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
import numpy as np
from sklearn.model_selection import cross_val_score

lbc_data = load_breast_cancer()
X = lbc_data.data
y = lbc_data.target

rfc = RandomForestClassifier(n_estimators=100, random_state=10)
"""
# data = SelectFromModel(rfc, threshold=0.02).fit_transform(lbc_data.data, lbc_data.target)
# score = cross_val_score(rfc, data, y, cv=5).mean()
# print(score)

# threshold是根据每个值的重要程度进行选择,这个threshold如何取值?
# 画出学习曲线

max_feature = (rfc.fit(X, y).feature_importances_).max()
line_data = np.linspace(0, max_feature, 20)
print(line_data)
"""

"""
scores = []

for i in line_data:
    data = SelectFromModel(rfc, threshold=i).fit_transform(X, y)
    score = cross_val_score(rfc, data, y, cv=5).mean()
    scores.append(score)

plt.figure(figsize=(15, 5))
plt.plot(line_data, scores, color='black', label='学习曲线')
plt.show()
"""

# 根据学习曲线返现最高值在0.01到0.027之间,那么我们在这个数段之间选取20个数,以帮助我们寻找最大值
"""
thirdhold = np.linspace(0.01, 0.027, 20)

score_ = []
for i in thirdhold:
    data = SelectFromModel(rfc, threshold=i).fit_transform(X, y)
    score = cross_val_score(rfc, data, y, cv=5).mean()
    score_.append(score)
print(max(score_))
plt.figure(figsize=(15, 5))
plt.plot(thirdhold, score_)
plt.show()
"""

# 经过学习曲线进一步验证,我们发现分数最高值是0.9578326346840551,在图像上显示大概在0.016附近,那么我们就拿0.016做thirdhold参数进行训练
data = SelectFromModel(rfc, threshold=0.016).fit_transform(X, y)
score = cross_val_score(rfc, data, y, cv=5).mean()
print(score)
# 0.9578326346840551结果正好是最好的结果


# 我们已经将threshold调到最好了,那么我们可以在试着调试一下随机森林n_estimators,我们发现n_estimators从10调到100后,准去率直接达到0.9631113181183046

  • 0
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值