引言
目前,遥感图像在模式识别、图像分割、地面参数反演研究中有着广泛的应用。遥感图像一般具有多个波段,每个波段均反映了地物的不同波谱特性。相对于图像分类而言,不同的波长位置的波谱反射可能存在较多的信息重叠,一旦信息重叠度达到一定阈值就会降低分类精度和分类器效率(特别是具有几百个波段的高光谱图像)。
因此,本文章将从特征筛选的角度介绍遥感图像特征的降维方法。本文所使用的特征筛选方法是卡方检验特征筛选,该方法建立于自变量之间相互独立的假设,因此该算法只能每次抽取一个特征喂入卡方检验中进行估计和筛选,代码调用的仍是python内部的sklearn库内的相关封装函数,以Cart分类器作为特征筛选函数的超参数,寻求最优的特征K,在本文中,K值为最优特征的列位置(大家注意不是列数,列位置+1=列数,因为列位置是从0开始的)。
主要方法原理
卡方检验是一种用途很广的计数资料的假设检验方法。它属于非参数检验的范畴,主要是比较两个及两个以上样本率( 构成比)以及两个分类变量的关联性分析。其根本思想就是在于比较理论频数和实际频数的吻合程度或拟合优度问题。它在分类统计推断中的应用,包括:两个率或两个构成比比较的卡方检验;多个率或多个构成比比较的卡方检验以及分类资料的相关分析等。
卡方检验的公式为:其中,A为实际值,T为理论值。
用于衡量实际值与理论值的差异程度(也就是卡方检验的核心思想),包含了以下两个信息:
1. 实际值与理论值偏差的绝对大小(由于平方的存在,差异是被放大的)。
2. 差异程度与理论值的相对大小。
数据介绍
文章基于一副5波段无人机多光谱图像,分析了其不同的GLCM纹理特征,在Arcmap中建立两类地物的采样点,提取特征值到采样点后,并截取一部分转为txt文本格式,并将其作为本实验所需的原始数据,数据维度为(行数:1298,列数:28)。由于代码也可改为csv文件下运行,因此文章提供了txt和csv两个版本的数据下载链接供大家实验:
data_shift.txt
306K ·
百度网盘
data_shift.csv
306K ·
百度网盘
python代码实现(一)
import pandas as pd
import time
from sklearn.model_selection import train_test_split
import numpy as np
from sklearn.tree import DecisionTreeClassifier
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
from sklearn.model_selection import cross_val_score
#开始时间戳
T1 = time.time()
def time_transform(time_now):
time1 = time.localtime(time_now)
time2 = time.strftime("%Y-%m-%d %H:%M:%S",time1)
return time2
print("程序开始时间:", time_transform(T1))
#Step2. 缺失特征值填充+数据分类(验证集和测试集)
FilePath = r"E:\yync\try\edata\data_shift.txt"
data1 = pd.read_csv(FilePath)
#Note:数据分类,以0.25比例选测试集
label = data1['status']
feature = data1.drop(['status'], axis=1)
feature_train, feature_test, label_train, label_test = train_test_split(feature, label, test_size=0.25, random_state=1)
#Note:填充NA或NAN值(指定列)
feature["RGB_mean_2j"].fillna(feature["RGB_mean_2j"].mean(), inplace=True)
feature.fillna('UNKNOWN', inplace=True)
precision = []
#Step3. 定义分类器,进行卡方筛选,十折交叉验证寻最优K
classer_CART = DecisionTreeClassifier(criterion = "gini", random_state = 1)
K = range(1, 28)
for i in K:
CHI_shif = SelectKBest(score_func=chi2, k=i)
X = CHI_shif.fit_transform(feature_train, label_train)
scores = cross_val_score(classer_CART, X, label_train, cv=10, scoring='accuracy')
precision = np.append(precision, scores.mean())
#Note:打印每次筛选后的精度
print(precision)
#Step4. 寻找精度最高时所对应的K值
result = np.where(precision == precision.max())[0][0]
print("最优K值为%d"%result)
#结束时间戳,打印程序运行时间
T2 = time.time()
print("程序运行时间为:", time_transform(T2))
代码关键点说明:
1.在Step3中,分类器可以选用其他的,比如SVM、RF、Knn等,根据自身需要即可;
2.另外,筛选自己的数据集K参数也是需要更改的;
3.交叉验证函数中,scoring的评价指标我选用了适于解决分类问题的总体精度,若为回归问题或者想选其他指标的读者可参照该表:3.3. Metrics and scoring: quantifying the quality of predictionsscikit-learn.org
4.若使用决策树或者随机森林分类器作为超参数,随机种子的参数一定要定义,否则会出现每次运行K值不统一的状况。
python代码实现(二)
import pandas as pd
from sklearn.feature_selection import SelectKBest
from sklearn.feature_selection import chi2
#Step1. 读取数据
FilePath = r"E:\yync\try\edata\data_shift.txt"
data1 = pd.read_csv(FilePath)
label = data1['status']
feature = data1.drop(['status'], axis=1)
#Note:填充NA或NAN值(指定列)
feature["RGB_mean_2j"].fillna(feature["RGB_mean_2j"].mean(), inplace=True)
feature.fillna('UNKNOWN', inplace=True)
#Step2. 使用最优K进行特征筛选
#Note:设置卡方检验,选择k=27个特征
test = SelectKBest(score_func=chi2, k=27)
#Note:检验
fit = test.fit(feature, label)
#Note:打印卡方检验值和筛选所得特征的第一行特征值
print(fit.scores_)
features = fit.transform(feature)
print(features[0:1,:])
处理结果
1.python代码实现(一)运行结果讲解这是K=27时,十折交叉验证输出的精度,我截取的是K=27时,输出的结果精度最优K为19,对应的是上图的第20个数,AC=0.93010604
基于上述结果,我们找到数据列表中第20个特征的名称:近红外的对比度纹理特征
2.python代码实现(二)运行结果讲解蓝色区域为第20个特征的卡方值,微微高于第25个特征。这主要是因为代码二没有划分训练集与验证集每个特征中第一个特征值
虽然从表面上看,代码二似乎提供了另外一种特征筛选的方法,但是它和代码二的原理都是相同的,虽然评价指标各不相同但是筛选机制不变,不过需要注意的一点是,评选指标不同,最后筛选出来的特征也会存在差异,例如变异系数和相对差异度均可以作为特征筛选指标,但基于两种特征筛选指标所得到的特征又是各异的。另外笔者并没有在代码二里区分训练集和测试集。所以大家可以自己尝试更改,便于论文写作时将卡方值带入分析。
参考文献特征选择--卡方检验(使用Python sklearn进行实现)blog.csdn.net特征选择-卡方检验用于特征选择_python_ldcadai的博客-CSDN博客blog.csdn.net使用sklearn的cross_val_score进行交叉验证_人工智能_昆兰.沃斯 的博客-CSDN博客blog.csdn.net
感言
最近代码敲的太肝了,接下来要做做实验室的任务,改改自己的论文了,发了几篇科普文章之后发现这种形式的学习对于我来说真的很不错。希望自己能够坚持下去,考博时能用上,哈哈。论文得改,报告得写,但python学习不能停,有想法我会随时更新的,也欢迎大家交流经验!