PCA降维实例[GridSearchCV求最优参]

降维概念

       机器学习领域中所谓的降维就是指采用某种映射方法,将原高维空间中的数据点映射到低维度的空间中。降维的本质是学习一个映射函数 f : x->y,其中x是原始数据点的表达,目前最多使用向量表达形式。 y是数据点映射后的低维向量表达,通常y的维度小于x的维度(当然提高维度也是可以的)。f可能是显式的或隐式的、线性的或非线性的。

       目前大部分降维算法处理向量表达的数据,也有一些降维算法处理高阶张量表达的数据。之所以使用降维后的数据表示是因为在原始的高维空间中,包含有冗余信息以及噪音信息,在实际应用例如图像识别中造成了误差,降低了准确率;而通过降维,我们希望减少冗余信息所造成的误差,提高识别(或其他应用)的精度。又或者希望通过降维算法来寻找数据内部的本质结构特征。

       在很多算法中,降维算法成为了数据预处理的一部分,如PCA。事实上,有一些算法如果没有降维预处理,其实是很难得到很好的效果的。

对原始数据采取降维的原因通常有两个:① 缓解“维度灾难”  ② 对数据进行可视化。

  降维的好坏没有一个直接的标准(包括上面提到的重构误差也只能作为一个中性的指标)。通常通过对数据进行降维,然后用降维后的数据进行学习,再根据学习的效果选择一个恰当的降维方式和一个合适的降维模型参数。 

sklearn.decomposition.PCA(n_components=None, copy=True, whiten=False) 

一、关于参数

n_components:  

意义:PCA算法中所要保留的主成分个数n,也即保留下来的特征个数n

类型:int 或者 string,缺省时默认为None,所有成分被保留。          

赋值为int,比如n_components=1,将把原始数据降到一个维度。          

赋值为string,比如n_components='mle',将自动选取特征个数n,使得满足所要求的方差百分比。

copy: 类型:bool,True或者False,缺省时默认为True。

意义:表示是否在运行算法时,将原始训练数据复制一份。若为True,则运行PCA算法后,原始训练数据的值不会有任何改变,因为是在原始数据的副本上进行运算;若为False,则运行PCA算法后,原始训练数据的值会改,因为是在原始数据上进行降维计算。

whiten: 类型:bool,缺省时默认为False ;     意义:白化。

二、PCA对象属性

components_:返回具有最大方差的成分。

explained_variance_ratio_:返回 所保留的n个成分各自的方差百分比。 n_components_:返回所保留的成分个数n。

mean_

noise_variance_

三、PCA对象属性

fit(X,y=None)

  • fit()可以说是scikit-learn中通用的方法,每个需要训练的算法都会有fit()方法,它其实就是算法中的“训练”这一步骤。因为PCA是无监督学习算法,此处y自然等于None。
  • fit(X):表示用数据X来训练PCA模型。
  • 函数返回值:调用fit方法的对象本身。比如pca.fit(X),表示用X对pca这个对象进行训练。

fit_transform(X)

  • 用X来训练PCA模型,同时返回降维后的数据。
  • newX=pca.fit_transform(X),newX就是降维后的数据。

inverse_transform()

  • 将降维后的数据转换成原始数据,
  • X=pca.inverse_transform(newX)

transform(X)

  • 将数据X转换成降维后的数据。当模型训练好后,对于新输入的数据,都可以用transform方法来降维。

此外,还有get_covariance()、get_precision()、get_params(deep=True)、score(X, y=None)等方法,以后用到再补充吧。

(转至 https://blog.csdn.net/u012102306/article/details/52294726

流程

拟合数据并降维——n_components对应要将的维度 

'''拟合数据'''
K=1 # 要降的维度
model = pca.PCA(n_components=K).fit(x_train)   # 拟合数据,n_components定义要降的维度
Z = model.transform(x_train)    # transform就会执行降维操作

数据恢复

model.components_会得到降维使用的U矩阵

'''数据恢复并作图''' 
Ureduce = model.components_ # 得到降维用的

Ureduce x_rec = np.dot(Z,Ureduce) # 数据恢复

手写数字识别

  • 导包,使用SVM
  • datasets读取数据
  • 分割训练和预测数据train_test_split(可以放多个要分割的数据)
  • 绘制前100个图片
  • 创建SVC模型gamma =0.001
  • 训练数据
  • 预测数据,可视化

导包

import pandas as pd
from pandas import Series,DataFrame
import numpy as np

import matplotlib.pyplot as plt
%matplotlib inline

'''PCA'''
from sklearn.decomposition import PCA

'''SVC算法'''
from sklearn.svm import SVC
'''使用GridSearchCV搜索最优参数'''
from sklearn.model_selection import GridSearchCV

数据集

data = pd.read_csv('./data/digits.csv')
data.shape
Out:(42000, 785)
# 28*28=784

显示数据

  • # 属性的不同的,导致了图片数字显示不同
  • # 属性差别导致,形状差别
image = data.loc[3][1:].values.reshape(28,28)
plt.figure(figsize=(1,1))
plt.imshow(image)

# piexel0这一列对数据的分类,一点用都没有
data['pixel0'].sum()
Out:0

data['pixel5'].sum()
Out:0

data['pixel783'].sum()
Out:0

降维

  • # 降维,数据784维,属性
  • # 没用数据属性去掉784维------>100维:提取100个关键的属性

白化的概念

- 白化是一种重要的预处理过程,其目的就是降低输入数据的冗余性,使得经过白化处理的输入数据具有如下性质:

  • (i)特征之间相关性较低;(ii)所有特征具有相同的方差。

  • 白化处理分PCA白化和ZCA白化,PCA白化保证数据各维度的方差为1,而ZCA白化保证数据各维度的方差相同。

  • PCA白化可以用于降维也可以去相关性,而ZCA白化主要用于去相关性,且尽量使白化后的数据接近原始输入数据。

- PCA白化和ZCA白化的区别

    PCA白化ZCA白化都降低了特征之间相关性较低,同时使得所有特征具有相同的方差。

  • PCA白化需要保证数据各维度的方差为1,ZCA白化只需保证方差相等。
  • PCA白化可进行降维也可以去相关性,而ZCA白化主要用于去相关性另外。
  • ZCA白化相比于PCA白化使得处理后的数据更加的接近原始数据。

参见:https://blog.csdn.net/u013146742/article/details/51798826

特征数据和目标数据

X = data.iloc[:,1:]
y = data['label']

降维操作

''' PCA(n_components=None【要降的维度】, copy=True, whiten=False
【(i)特征之间相关性较低;(ii)所有特征具有相同的方差。】, 
svd_solver='auto', tol=0.0, iterated_power='auto', random_state=None)'''

pca = PCA(n_components=100,whiten=True)
pca.fit(X)
Out: 
PCA(copy=True, iterated_power='auto', n_components=100, random_state=None,
  svd_solver='auto', tol=0.0, whiten=True)

X_pca = pca.transform(X)  # transform就会执行降维操作
# X_pca,使用这个数据效果更好
X_pca.shape
Out:(42000,100)

X_pca[0:5000].shape
OUt:
(5000, 100)

GridSearchCV 的参数说明:

1.estimator
选择使用的分类器,并且传入除需要确定最佳的参数之外的其他参数。
每一个分类器都需要一个scoring参数,或者score方法:
如estimator=RandomForestClassifier(
	min_samples_split=100,
	min_samples_leaf=20,
	max_depth=8,
	max_features='sqrt',
	random_state=10),
 
2.param_grid
需要最优化的参数的取值,值为字典或者列表,例如:
	param_grid =param_test1,
	param_test1 = {'n_estimators':range(10,71,10)}。
 
3. scoring=None
模型评价标准,默认None,这时需要使用score函数;或者如scoring='roc_auc',
根据所选模型不同,评价准则不同。字符串(函数名),或是可调用对象,
需要其函数签名形如:scorer(estimator, X, y);如果是None,则使用estimator的误差估计函数。
 
4.n_jobs=1
n_jobs: 并行数,int:个数,-1:跟CPU核数一致, 1:默认值
 
5.cv=None  
交叉验证参数,默认None,使用三折交叉验证。指定fold数量,默认为3,也可以是yield产生训练/测试数据的生成器。
 
6.verbose=0, scoring=None
verbose:日志冗长度,int:冗长度,0:不输出训练过程,1:偶尔输出,>1:对每个子模型都输出。
 
7.pre_dispatch=‘2*n_jobs’
指定总共分发的并行任务数。当n_jobs大于1时,数据将在每个运行点进行复制,这可能导致OOM,
而设置pre_dispatch参数,则可以预先划分总共的job数量,使数据最多被复制pre_dispatch次
 
8.return_train_score=’warn’
如果“False”,cv_results_属性将不包括训练分数。
 
9.refit :默认为True,程序将会以交叉验证训练集得到的最佳参数,重新对所有可用的训练集与开发集进行,
作为最终用于性能评估的最佳模型参数。即在搜索参数结束后,用最佳参数结果再次fit一遍全部数据集。
 
10.iid:默认True,为True时,默认为各个样本fold概率分布一致,误差估计为所有样本之和,而非各个fold的平均。
 
进行预测的常用方法和属性
grid.fit():运行网格搜索
grid_scores_:给出不同参数情况下的评价结果
best_params_:描述了已取得最佳结果的参数的组合
best_score_:成员提供优化过程期间观察到的最好的评分
-------------------------------------------------------
param_test1 ={'n_estimators':range(10,71,10)}  
gsearch1= GridSearchCV(
		estimator =RandomForestClassifier(
			min_samples_split=100,  
                        min_samples_leaf=20,max_depth=8,
			max_features='sqrt',
			random_state=10),   
                param_grid =param_test1,
		scoring='roc_auc',
		cv=5)  
gsearch1.fit(X,y)  
gsearch1.grid_scores_, 
gsearch1.best_params_, 
gsearch1.best_score_  
 
'''
输出结果如下:
([mean: 0.80681, std:0.02236, params: {'n_estimators': 10},
  mean: 0.81600, std: 0.03275, params:{'n_estimators': 20},
  mean: 0.81818, std: 0.03136, params:{'n_estimators': 30},
  mean: 0.81838, std: 0.03118, params:{'n_estimators': 40},
  mean: 0.82034, std: 0.03001, params:{'n_estimators': 50},
  mean: 0.82113, std: 0.02966, params:{'n_estimators': 60},
  mean: 0.81992, std: 0.02836, params:{'n_estimators': 70}],
{'n_estimators': 60},
0.8211334476626017)
'''
如果有transform,使用Pipeline简化系统搭建流程,将transform与分类器串联起来(Pipelineof transforms with a final estimator)
 
pipeline= Pipeline([("features", combined_features), ("svm", svm)])  
param_grid= dict(features__pca__n_components=[1, 2, 3],  
                  features__univ_select__k=[1,2],  
                  svm__C=[0.1, 1, 10])  
   
grid_search= GridSearchCV(pipeline, param_grid=param_grid, verbose=10)  
grid_search.fit(X,y)  
print(grid_search.best_estimator_)  
# 转:https://blog.csdn.net/WxyangID/article/details/80397185

使用SVC算法

'''C惩罚系数默认值是1  -->[0.1,0.5,1,2,3,5]
 gamma是kernel系数默认值是1/n_features = 0.01 -->[0.0001,0.001,0.01,0.05,0.1,0.5]
'''
svc = SVC()
# 定义参数取值
params = {'C':[1,3],'gamma':[0.001,0.05]}

'''GridSearchCV(estimator, param_grid, scoring=None, fit_params=None, n_jobs=1,
iid=True, refit=True, cv=None, verbose=0, pre_dispatch='2*n_jobs', 
error_score='raise', return_train_score='warn')'''

# 使用GridSearchCV网格搜索出最优参数
gcv = GridSearchCV(svc,param_grid=params)

使用前5000个数据训练,后500个数据做测试:

X_train = X_pca[0:5000]

X_test = X_pca[-500:]

y_train = y[:5000]

y_test = y[-500:]

使用gcv训练数据,找出最优解

# 认为for遍历参数,寻找最优的参数
gcv.fit(X_train,y_train)
Out:
GridSearchCV(cv=None, error_score='raise',
       estimator=SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape='ovr', degree=3, gamma='auto', kernel='rbf',
  max_iter=-1, probability=False, random_state=None, shrinking=True,
  tol=0.001, verbose=False),
       fit_params=None, iid=True, n_jobs=1,
       param_grid={'C': [1, 3], 'gamma': [0.001, 0.05]},
       pre_dispatch='2*n_jobs', refit=True, return_train_score='warn',
       scoring=None, verbose=0)

'''最优解:C=3,gamma=0.001'''
svc_best = gcv.best_estimator_
svc_best
Out:
SVC(C=3, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape='ovr', degree=3, gamma=0.001, kernel='rbf',
  max_iter=-1, probability=False, random_state=None, shrinking=True,
  tol=0.001, verbose=False)

gcv.best_score_
Out: 0.9106

svc_best.score(X_test,y_test)
Out: 0.926

若不进行降维,速度慢,准确度低

# 如果不进行降维
X_train1 = X[:5000]
y_train1 = y[:5000]

X_test1 = X[-500:]
y_test1 = y[-500:]


print(time.time())
svc_best.fit(X_train1,y_train1)
print(time.time())
Out:
1532486494.0555701
1532486563.2417252

# 准确率,不会太高,非常低,不能接受
# 对数据处理,降维好处显而易见
'''svc_best是使用已经经过网格搜索出最优参数的svc模型'''
svc_best.score(X_test1,y_test1)
Out: 0.142

猜你喜欢

转载自blog.csdn.net/Dorisi_H_n_q/article/details/82813436