特征工程
写在前面
以下算法实例均取自sklearn库,使用python编写
可使用以下指令快速安装sklearn
下文有时会使用./SelfTools/Tool.py
中的内容
def separate (self=None ): print ("---------------------------------------------------------------------------------------------------" * 2 ) return None
常用算法
字典特征值抽取
从原始数据中提取有意义的特征,然后创建一个字典来存储提取的特征,再将数据转换为字典形式,以便可以方便地进行分析或输入到机器学习模型中(向量化?),最后从提取的特征中选择最有用的特征,以提高模型的性能。有时还需要对特征进行标准化处理,以确保它们在相同的尺度上,避免大数”吞噬“小数。
demo
from sklearn.feature_extraction import DictVectorizerfrom SelfTools import Tooldef dict_demo (flag=True ): """ 字典特征值抽取,抽取为one-hot编码 :return: """ data = [{'city' : 'Beijing' , 'temperature' : 100 }, {'city' : 'Shanghai' , 'temperature' : 60 }, {'city' : 'Shenzhen' , 'temperature' : 30 }] transfer = DictVectorizer(sparse=flag) data_new = transfer.fit_transform(data) print ("data_new: \n" , data_new) print ("feature_names: \n" , transfer.get_feature_names()) return None if __name__ == "__main__" : dict_demo() Tool.separate() dict_demo(False )
特征降维
目的是去除冗余数据,这里的维数应当指的是特征的种类,有时我们并不需要一个数据的全部维度,比如西瓜瓜皮颜色,对于大部分数据都具有相同的值,属于冗余特征。
一般采用低方差特征过滤法 ,其原理为:某个特征的方差小,意味着大部分样本该特征的值比较相近,为冗余数据,无需考虑。
demo
from sklearn.feature_selection import VarianceThresholdimport pandas as pdfrom SelfTools import Tool""" VarianceThreshold(threshold=0.0) 删除所有低方差特征 Variance.fit_transform(X) X: numpy array格式的数据 [n_samples, n_features] return: 训练集差异小于等于threshold的特征被删除。默认值是保存所有非零方差特征(即threshold = 0.0), 即删除所有具有相同值的特征 """ """ 卡方检验(Pearsonr检验):高中知识,反应相关性 r, r -> [-1, 1]; |r|越接近 1,相关性越强,大于0正相关 """ from scipy.stats import pearsonr""" 从scipy中引进pearsonr卡方检验 pearsonr(x, y) x: (N,) array_like y: (N,) array_like return: Pearson's correlation coefficient(statistic), p-value(pvalue) p-value衡量 r 的有效性,越小越可靠 """ def variance_demo (std=0.0 ): data = pd.read_csv("factor_returns.csv" ) print ("data: \n" , data) Tool.separate() data = data.iloc[:, 2 :] print ("data: \n" , data) Tool.separate() transfer = VarianceThreshold(std) data_new = transfer.fit_transform(data) print ("data_new: \n" , data_new) print ("shape of data_new: \n" , data_new.shape) Tool.separate() r = pearsonr(data["Open" ], data["Close" ]) print ("相关系数: \n" , r) Tool.separate() return None if __name__ == "__main__" : variance_demo() variance_demo(13 ) variance_demo(14 )
特征值归一化
为防止一些很大的特征值在进行机器学习时对整个结果起支配作用,从而使计算机无法学习到其他特征值较小的特征。
对特征值 x 作归一化: step1: X' = (x - min) / (max - min) step2: X'' = x' * (mx - mi) + mi 注:mx, mi分别为指定区间值(标准化后值的范围,例如归一化一般采用(0, 1)),默认mx = 1, mi = 0 feature_ range = (mi, mx) X''为归一化后的 x
*缺点:*依赖于最大值与最小值,一旦最大值或最小值中出现异常值,归一化就会失效,只适合传统精确小数据场景
demo
from sklearn.preprocessing import MinMaxScalerimport pandas as pdfrom SelfTools import Tool""" MinMaxScaler(feature_range=(0,1)...) MinMaxScaler.fit_transform(X) X: numpy array格式的数据[n_samples, n_features] (二维数组,行数为样本数,列数为特征的个数) return: 转换后的形状相同的array """ def minmax_scaler (): """ 归一化 :return: """ data = pd.read_csv("dating.txt" ) print ("data: \n" , data) Tool.separate() data = data.iloc[:, 0 :3 ] print ("data: \n" , data) Tool.separate() transfer = MinMaxScaler() data_new = transfer.fit_transform(data) print ("data_new: \n" , data_new) Tool.separate() return None if __name__ == "__main__" : minmax_scaler()
特征值标准化
解决归一化的不足 ,通过对原始数据进行变换,把数据变换到均值为 0,标准差为 1 的范围内
对 x 标准化: X' = (x - mean) / std mean: 均值 std: 标准差
关于异常值,标准化对于异常值的敏感度低于归一化;对于大量的大数据而言,少量异常点对于均值和标准差的影响都不会很大。
demo
from sklearn.preprocessing import StandardScalerimport pandas as pdfrom SelfTools import Tool""" StandardScaler() 处理之后,对每列来说,所有数据都聚集在均值 0 附近,标准差为 1 StandardScaler.fit_transform(X) X: numpy array格式的数据 [n_samples, n_features] (同样为二维数组,行数为样本数,列数为特征的个数) return: 转换后形状相同的array """ def std_scaler (): """ 标准化 :return: """ data = pd.read_csv("dating.txt" ) data = data.iloc[:, :3 ] print ("dara: \n" , data) Tool.separate() transfer = StandardScaler() data_new = transfer.fit_transform(data) print ("data_new: \n" , data_new) return None if __name__ == "__main__" : std_scaler()
主成分分析 PCA
又称PCA降维 ,是一种常用的数据降维技术,它通过将原始数据集中的特征线性组合,提取一组新的特征(称为主成分),这些新特征具有最大的方差,并且彼此正交。这样,我们就可以用尽可能少的主成分来保留原始数据集的大部分信息。
往往需要数据标准化,计算协方差矩阵,计算特征值和特征向量,选择主成分,降维…
万幸,python什么都有
demo
from sklearn.decomposition import PCAfrom SelfTools import Tool""" PCA(n_components=None) 将数据分解为较低维数空间 n_components: 小数:表示保留百分之多少的信息 整数:减少到多少特征 PCA.fit_transform(X) X: numpy array格式的数据 [n_samples, n_features] return: 转换后指定维度的array """ def pca_demo (): data = [[2 , 8 , 4 , 5 ], [6 , 3 , 0 , 8 ], [5 , 4 , 9 , 1 ]] transfer = PCA(n_components=0.95 ) data_new = transfer.fit_transform(data) print ("data_new:\n" , data_new) Tool.separate() return None if __name__ == "__main__" : pca_demo()
下面介绍一些和文本内容相关的数据分析算法
文本特征值提取
以单词
作为特征进行提取,sklearn提供了一个**CountVectorizer
**统计特征值出现的个数
demo
可能需要的指令,(如果import jieba
报错
from sklearn.feature_extraction.text import CountVectorizerimport jiebafrom SelfTools import Tooldef text_demo (): """ 文本特征抽取:CountVectorizer :return: """ text = ["life is short, i like like python" , "life is too long, i dislike python" ] transfer = CountVectorizer() txt_new = transfer.fit_transform(text) print ("features_names: \n" , transfer.get_feature_names_out()) print ("txt_new: \n" , txt_new) Tool.separate() print ("type of txt_new: \n" , type (txt_new)) Tool.separate() print ("array of txt_new: \n" , txt_new.toarray()) return None def chn_txt_demo (): """ 中文文本特征值抽取 :return: """ text = ["这些新特征具有最大的方差,并且彼此正交。这样,我们就可以用尽可能少的主成分来保留原始数据集的大部分信息。" , "牛魔大酬宾" ] transfer = CountVectorizer() txt_new = transfer.fit_transform(text) print ("features_names: \n" , transfer.get_feature_names_out()) print ("array of txt_new: \n" , txt_new.toarray()) return None def cut_words (text ): """ 对字符串进行中文分词 :param: text :return: " ".join(list(jieba.cut(text))) """ tokenizer = jieba.cut(text) l_token = list (tokenizer) text = " " .join(l_token) return text def chn_txt_sep (): """ 中文特征值抽取,自动分词 :return: """ text = ["我会在本学期认真自学课程内容,并按时上交课程作业" , "参加每一次课程考试。" , "如因未随堂上课迟交或错过提交作业、参加测试等影响本课程成绩,本人自行承担一切后果。" ] txt_new = [] for i in range (0 , len (text)): txt_new.append(cut_words(text[i])) transfer = CountVectorizer(stop_words=["本人" , "我会" ]) txt_new = transfer.fit_transform(txt_new) print ("features_names: \n" , transfer.get_feature_names_out()) print ("array of txt_new: \n" , txt_new.toarray()) return None if __name__ == "__main__" : chn_txt_sep()
TF-IDF
tf: text frequency 词频 = 某单词出现次数 / 总单词数目 idf: inverse document frequency 逆向文档频率 = lg (总文档数目 / 包含某单词的文档数目) tf-idf = tf * idf tf-idf的值越高,代表该单词的重要性越高,作为关键词区分不同类型文章的价值越高 关键词:在某一个类别的文章中出现次数很多,而在其它类别的文章中出现次数较少
demo
from sklearn.feature_extraction.text import TfidfVectorizerimport jiebadef cut_words (text ): """ 对字符串进行中文分词 :param: text :return: " ".join(list(jieba.cut(text))) """ tokenizer = jieba.cut(text) l_token = list (tokenizer) text = " " .join(l_token) return text def tfidf_demo (): """ 用tf-idf方法进行文本特征抽取 :return: """ text = ["我会在本学期认真自学课程内容,并按时上交课程作业" , "参加每一次课程考试。" , "如因未随堂上课迟交或错过提交作业、参加测试等影响本课程成绩,本人自行承担一切后果。" ] txt_new = [] for i in range (0 , len (text)): txt_new.append(cut_words(text[i])) transfer = TfidfVectorizer(stop_words=["本人" , "我会" ]) txt_new = transfer.fit_transform(txt_new) print ("feature_names: \n" , transfer.get_feature_names()) print ("txt_new: \n" , txt_new.toarray()) return None if __name__ == "__main__" : tfidf_demo()
综合运用实践
一个简单的数据集训练过程
from sklearn.datasets import load_irisfrom sklearn.model_selection import train_test_splitdef separate (): print ("<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<分隔符>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" ) def datasets_demo (): iris = load_iris() print (iris) separate() print (iris["DESCR" ]) separate() print (iris.feature_names) separate() print ("特征值: \n" , iris.data, "\n特征值维数: " , iris.data.shape) separate() x_train, x_test, y_train, y_test = train_test_split(iris.data, iris.target, test_size=0.2 , random_state=22 ) print ("训练集的特征值: \n" , x_train, "\n大小: " , x_train.shape) separate() return None if __name__ == "__main__" : datasets_demo()
(•‿•)