机器学习笔记

机器学习笔记

利用寒假时间重新学习机器学习,做一些简单的笔记。留个痕迹,证明自己学过。哈哈~~~~

1 特征工程

对于某些应用来说,如何找到最佳数据表示,这个问题被称为特征工程。通常,其对模型的准确性影响甚大。

1.1 One-Hot编码

我们知道,在使用相关模型对给定数据进行拟合时,使用的是由浮点数组成的数值型数据。而在分类特征,通常并非是数值型。而One-Hot编码(也叫虚拟变量)是目前表示分类变量最常用的法。虚拟变量背后的思想是将一个分类变量替换成一个或多个新特征,新特征的取值为0或1。具体演变如下:
原始数据如下
未使用One-Hot编码前的数据
经过One-Hot编码后的数据如下
One-Hot编码后的数据
功能的实现使用了pandas库的get_dummies函数。实现代码如下:

import pandas as pd

#读取数据
data_frame = pd.read_excel('演示数据.xlsx', sheet_name='演示表格', index_col=0)
#对数据进行One-Hot编码
data_dummies = pd.get_dummies(data_frame)
#保存数据
writer = pd.ExcelWriter('处理后的数据.xlsx')
data_dummies.to_excel(writer, sheet_name='处理完的表格', index=True)
writer.save()

get_dummies函数的参数如下:

data : array-like, Series, or DataFrame
输入的数据
prefix : string, list of strings, or dict of strings, default None
get_dummies转换后,列名的前缀
columns : list-like, default None
指定需要实现类别转换的列名
dummy_na : bool, default False
增加一列表示空缺值,如果False就忽略空缺值
drop_first : bool, default False
获得k中的k-1个类别值,去除第一个

值得注意的是,我们需要对同时包含训练数据和测试数据的数据框调用get_dummies函数。以便确保训练集和测试集中分类变量的表达方式相同。
分类特征通常用整数进行编码,在实际处理数据的过程中,有一种情况。即数字并不意味着它们必须被视为连续特征。比如在做收入调查时,选择数字0被视为低收入,选择1被视为中收入,2被视为高收入。显然,在这里的0,1,2并不能被视为连续特征,它们代表的是不同的状态,不应该使用连续变量来建模。此时,需要使用get_dummies函数的columns参数来指定需要编码的列。
处理结果如下
添加column参数处理后的数据
代码如下:

import pandas as pd

#读取数据
data_frame = pd.read_excel('演示数据.xlsx', sheet_name='演示表格', index_col=0)
data_frame['T2'] = data_frame['T2'].astype(str)
#对数据进行One-Hot编码
data_dummies = pd.get_dummies(data_frame, columns=['T1', 'T2'])
#保存数据
writer = pd.ExcelWriter('处理后的数据.xlsx')
data_dummies.to_excel(writer, sheet_name='处理完的表格', index=True)
writer.save()

补充:scikit-learn的OneHotEncoder方法也可实现该功能,但是其目前只适用于值为整数的分类。其在模块sklearn.preprocessing中。介绍如下:

OneHotEncoder(*, categories=‘auto’, drop=None, sparse=True, dtype=<class ‘numpy.float64’>, handle_unknown=‘error’)

categories=’auto’ 表示每个特征使用几维的数值由数据集自动推断,即几种类别就使用几位来表示。
drop=None用于从每个特征中舍去特定的分类,默认为None,且不能与categories、n_values同用。
dtype=np.float64表示编码数值格式,默认是浮点型。
sparse=True表示编码的格式,默认为 True,即为稀疏的格式。
handle_unknown=’error’其值可以指定为 “error” 或者 “ignore”,即如果碰到未知的类别,是返回一个错误还是忽略它。

2 文本数据的处理

文本数据通常被表示为由字符串组成的字符串。在处理文本时,同样需要先对数据进行处理。

2.1 词袋与tf-idf

词袋是机器学习中文本表示的一种最简单也是最有效最常用的方法。这种方法舍弃了输入文本中的大部分结构,如章节、段落、句子和格式,只计算每个单词在文本中的出现频次。词袋表示由3个步骤:
第一步:分词。为每个文档划分为出现在其中的单词,比如按空格和标点划分。
第二步:构建词表,收集一个此表,里面包含在任意文档中的所有词,并对它们进行编码。
第三步:编码,对每个文档计算词表中每个文档在该文档中出现的频次。

from sklearn.feature_extraction.text import CountVectorizer

bads_words = ['Aa Aa Ba Ca Ca Ca Da Da Da Da Da Da Da Da Da Ea', 
    'Aa Ba Ba Ba Ba Ba Ca Ca Da Da Da Da Da Da Da Da Da Da']

#将文本中的词语转化为词频矩阵,矩阵元素a[i][j]表示词j在i类文本下的词频
vect = CountVectorizer()
vect.fit(bads_words)
#通过vocabulary_来访问训练后的词袋
print('Vocabulary size:{}'.format(len(vect.vocabulary_)))
print('Vocabulary content:{}'.format(vect.vocabulary_))

bag_of_words = vect.transform(bads_words)
#使用toarray方法查看稀疏矩阵
print('词频矩阵:\n{}'.format(bag_of_words.toarray()))

输出结果如下

Vocabulary size:5
Vocabulary content:{‘aa’: 0, ‘ba’: 1, ‘ca’: 2, ‘da’: 3, ‘ea’: 4}
词频矩阵:
[[ 2 1 3 9 1]
[ 1 5 2 10 0]]

在scikit-learn中,使用CountVectorizer实现词袋,其在sklearn.feature_extraction.text模块中。

class sklearn.feature_extraction.text.CountVectorizer(*, input=‘content’, encoding=‘utf-8’, decode_error=‘strict’, strip_accents=None, lowercase=True, preprocessor=None, tokenizer=None, stop_words=None, token_pattern=’(?u)\b\w\w+\b’, ngram_range=(1, 1), analyzer=‘word’, max_df=1.0, min_df=1, max_features=None, vocabulary=None, binary=False, dtype=<class ‘numpy.int64’>)

参数作用
input一般使用默认即可,可以设置为"filename’或’file’
encodeing使用默认的utf-8即可,分析器将会以utf-8解码raw document
decode_error默认为strict,遇到不能解码的字符将报UnicodeDecodeError错误,设为ignore将会忽略解码错误,还可以设为replace,作用尚不明确
strip_accents默认为None,可设为ascii或unicode,将使用ascii或unicode编码在预处理步骤去除raw document中的重音符号
analyzer一般使用默认,可设置为string类型,如’word’, ‘char’, ‘char_wb’,还可设置为callable类型,比如函数是一个callable类型
preprocessor设为None或callable类型
tokenizer设为None或callable类型
ngram_range词组切分的长度范围
stop_words设置停用词,设为english将使用内置的英语停用词,设为一个list可自定义停用词,设为None不使用停用词,设为None且max_df∈[0.7, 1.0)将自动根据当前的语料库建立停用词表
lowercase将所有字符变成小写
token_pattern过滤规则,表示token的正则表达式,需要设置analyzer == ‘word’,默认的正则表达式选择2个及以上的字母或数字作为token,标点符号默认当作token分隔符,而不会被当作token
max_df可以设置为范围在[0.0 1.0]的float,也可以设置为没有范围限制的int,默认为1.0。这个参数的作用是作为一个阈值,当构造语料库的关键词集的时候,如果某个词的document frequence大于max_df,这个词不会被当作关键词。如果这个参数是float,则表示词出现的次数与语料库文档数的百分比,如果是int,则表示词出现的次数。如果参数中已经给定了vocabulary,则这个参数无效
min_df类似于max_df,不同之处在于如果某个词的document frequence小于min_df,则这个词不会被当作关键词
max_features默认为None,可设为int,对所有关键词的term frequency进行降序排序,只取前max_features个作为关键词集
vocabulary默认为None,自动从输入文档中构建关键词集,也可以是一个字典或可迭代对象
binary默认为False,一个关键词在一篇文档中可能出现n次,如果binary=True,非零的n将全部置为1,这对需要布尔值输入的离散概率模型是有用的
dtype使用CountVectorizer类的fit_transform()或transform()将得到一个文档词频矩阵,dtype可以设置这个矩阵的数值类型
属性表作用
vocabulary_词汇表;字典型
get_feature_names()所有文本的词汇;列表型
vocabulary_返回停用词表

在处理文本时,通常利用停用词来舍弃那些我们认为不重要的特征。还用一种方法是tf-idf(词频-逆向文档频率)。其思想是词条的重要性与其在文件中出现的次数成正比,在全语料库中出现的次数成反比。即如果某个词条在某个特定文档中经常出现,但在许多文档中并不常出现,那么词条很可能是对文档类容的很好描述。
单词w在文档d中的tf-idf分数在scikit-learn中的计算公式如下
tf-idf公式
在进行计算后,还运用了L2范式进行缩放。

from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer

bads_words = ['Aa Aa Ba Ca Ca Ca Da Da Da Da Da Da Da Da Da Ea', 
    'Aa Ba Ba Ba Ba Ba Ca Ca Da Da Da Da Da Da Da Da Da Da']

#将文本中的词语转化为词频矩阵,矩阵元素a[i][j]表示词j在i类文本下的词频
vect = CountVectorizer()
vect.fit(bads_words)
#通过vocabulary_来访问训练后的词袋
print('Vocabulary size:{}'.format(len(vect.vocabulary_)))
print('Vocabulary content:{}'.format(vect.vocabulary_))

bag_of_words = vect.transform(bads_words)
#使用toarray方法查看稀疏矩阵
print('词频矩阵:\n{}'.format(bag_of_words.toarray()))

#统计每个词条的tf-idf权值
tfidftransformer = TfidfTransformer()
bag_of_words = tfidftransformer.fit_transform(bag_of_words)
print('tf-idf权重矩阵:\n{}'.format(bag_of_words.toarray()))

输出结果如下

Vocabulary size:5
Vocabulary content:{‘aa’: 0, ‘ba’: 1, ‘ca’: 2, ‘da’: 3, ‘ea’: 4}
词频矩阵:
[[ 2 1 3 9 1]
[ 1 5 2 10 0]]
tf-idf权重矩阵:
[[0.20309506 0.10154753 0.30464259 0.91392777 0.14272151]
[0.0877058 0.43852901 0.1754116 0.87705802 0. ]]

在scikit-learn中,实现tf-idf的方法有TfidfTransformer和TfidfVectorizer。前者接受CountVectorizer生成的稀疏矩阵并将其转化,后者接受文本数据并完成词袋特征提取与tf-idf变换。

class sklearn.feature_extraction.text.TfidfTransformer(*, norm=‘l2’, use_idf=True, smooth_idf=True, sublinear_tf=False)

class sklearn.feature_extraction.text.TfidfVectorizer(*, input=‘content’, encoding=‘utf-8’, decode_error=‘strict’, strip_accents=None, lowercase=True, preprocessor=None, tokenizer=None, analyzer=‘word’, stop_words=None, token_pattern=’(?u)\b\w\w+\b’, ngram_range=(1, 1), max_df=1.0, min_df=1, max_features=None, vocabulary=None, binary=False, dtype=<class ‘numpy.float64’>, norm=‘l2’, use_idf=True, smooth_idf=True, sublinear_tf=False)

参数详解:
input:string{‘filename’, ‘file’, ‘content’}

如果是'filename',序列作为参数传递给拟合器,预计为文件名列表,这需要读取原始内容进行分析

如果是'file',序列项目必须有一个”read“的方法(类似文件的对象),被调用作为获取内存中的字节数

否则,输入预计为序列串,或字节数据项都预计可直接进行分析。

encoding:string, ‘utf-8’by default

如果给出要解析的字节或文件,此编码将用于解码

decode_error: {‘strict’, ‘ignore’, ‘replace’}

如果一个给出的字节序列包含的字符不是给定的编码,指示应该如何去做。默认情况下,它是'strict',这意味着的UnicodeDecodeError将提高,其他值是'ignore'和'replace'

strip_accents: {‘ascii’, ‘unicode’, None}

在预处理步骤中去除编码规则(accents),”ASCII码“是一种快速的方法,仅适用于有一个直接的ASCII字符映射,"unicode"是一个稍慢一些的方法,None(默认)什么都不做

analyzer:string,{‘word’, ‘char’} or callable

定义特征为词(word)或n-gram字符,如果传递给它的调用被用于抽取未处理输入源文件的特征序列

preprocessor:callable or None(default)

当保留令牌和”n-gram“生成步骤时,覆盖预处理(字符串变换)的阶段

tokenizer:callable or None(default)

当保留预处理和n-gram生成步骤时,覆盖字符串令牌步骤

ngram_range: tuple(min_n, max_n)

要提取的n-gram的n-values的下限和上限范围,在min_n <= n <= max_n区间的n的全部值

stop_words:string {‘english’}, list, or None(default)

如果未english,用于英语内建的停用词列表

如果未list,该列表被假定为包含停用词,列表中的所有词都将从令牌中删除

如果None,不使用停用词。max_df可以被设置为范围[0.7, 1.0)的值,基于内部预料词频来自动检测和过滤停用词

lowercase:boolean, default True

在令牌标记前转换所有的字符为小写

token_pattern:string

正则表达式显示了”token“的构成,仅当analyzer == ‘word’时才被使用。两个或多个字母数字字符的正则表达式(标点符号完全被忽略,始终被视为一个标记分隔符)。

max_df: float in range [0.0, 1.0] or int, optional, 1.0 by default

当构建词汇表时,严格忽略高于给出阈值的文档频率的词条,语料指定的停用词。如果是浮点值,该参数代表文档的比例,整型绝对计数值,如果词汇表不为None,此参数被忽略。

min_df:float in range [0.0, 1.0] or int, optional, 1.0 by default

当构建词汇表时,严格忽略低于给出阈值的文档频率的词条,语料指定的停用词。如果是浮点值,该参数代表文档的比例,整型绝对计数值,如果词汇表不为None,此参数被忽略。

max_features: optional, None by default

如果不为None,构建一个词汇表,仅考虑max_features--按语料词频排序,如果词汇表不为None,这个参数被忽略

vocabulary:Mapping or iterable, optional

也是一个映射(Map)(例如,字典),其中键是词条而值是在特征矩阵中索引,或词条中的迭代器。如果没有给出,词汇表被确定来自输入文件。在映射中索引不能有重复,并且不能在0到最大索引值之间有间断。

binary:boolean, False by default

如果未True,所有非零计数被设置为1,这对于离散概率模型是有用的,建立二元事件模型,而不是整型计数

dtype:type, optional

通过fit_transform()或transform()返回矩阵的类型

norm:‘l1’, ‘l2’, or None,optional

范数用于标准化词条向量。None为不归一化

use_idf:boolean, optional

启动inverse-document-frequency重新计算权重

smooth_idf:boolean,optional

通过加1到文档频率平滑idf权重,为防止除零,加入一个额外的文档

sublinear_tf:boolean, optional

应用线性缩放TF,例如,使用1+log(tf)覆盖tf

我们可以看到

TfidfVectorizer=TfidfTransformer +CountVectorizer

需要注意的是tf-idf衡量词条重要性的指标。其本质是一种无监督技术。

3 评估指标

机器学习中有许多用于评价模型性能的指标。在评价模型的时候,需要我们根据自己的目标选择合适的指标。

3.1 二分类指标

二分类是实践中最常见的机器学习应用,也是概念最简单的应用。

3.1.1 混肴矩阵及相关指标

对于二分类问题,我们通常会说正类(positive class)和反类(negative)而正类是我们要寻找的类。在预测过程中,如果模型将反类认为是正类,则称为假正例(false positive),也叫第一类错误。如果模型将正类认为是反类,则称为假反例(false negative),也称为第二类错误。预测对的就称为真正例(ture positive)与真反例(ture negative).
基于上面的概念产生了一种表示方法,称为混肴矩阵(confusion matrix),表示如下:
混肴矩阵
混肴矩阵在scikit-learn中使用confusion_metrix函数实现。在sklearn.metrics模块中实现。

sklearn.metrics.confusion_matrix(y_true, y_pred, *, labels=None, sample_weight=None, normalize=None)

参数说明:
y_true:真实因变量值
y_pred:预测因变量值
labels:矩阵的标签列表索引顺序
sample_weight:样本权重
normalize:{‘true’,‘pred’,‘all’},是否归一化,默认为None

有几种可以总结混肴矩阵的方法,即计算精度(accuracy),准确率(precision),召回率(recall),f-度量(f-measure)。
其中,计算精度(accuracy)为正确预测的数量与所有样本数量的比例。准确率(precision)度量的是被预测为正例的样本中有多少时真正例。召回率(recall)度量的时正类样本中有多少被预测为正类。f-度量(f-measure)为准确率与召回率的调和平均。
相关公式
scikit-learn中,sklearn.metrics模块中的classification_report函数可以是想上述指标的计算。其返回结果为每个类别生成一行,分别以该类别作为正类计算上述指标,最后一列为在每个类别中真是样本的数量。报告的最后一行为对应指标的加权平均。

sklearn.metrics.classification_report(y_true, y_pred, *, labels=None, target_names=None, sample_weight=None, digits=2, output_dict=False, zero_division=‘warn’)

 y_true:  类别的真实标签值,类标签的列表
 y_pred:  预测值的标签,类标签的列表

 labels:   报告中要包含的标签索引的可选列表;这个参数一般不需要设置(如果要设置,比如200个类别,那么就应该如此设置:lable= range(200);  然后在sklearn.metrics.classification_report中将labels=label),可是有的时候不设置就会出错,之所以会出错是因为:比如你总共的类别为200个类,但是,你的测试集中真实标签包含的类别只有199个,有一个类别缺失数据,如果不设置这个参数就会报错;

 target_name:  与标签匹配的名称,就是一个字符串列表,在报告中显示;也即是显示与labels对应的名称

 sample_weight:设置权重的参数,一般不用,需要就可以用;

 digits:这个参数是用来设置你要输出的格式位数,就是几位有效数字吧,大概就是这个意思,即指定输出格式的精确度;

 output_dict:如果为True,则将输出作为dict返回

依据自己想要的结果,根据分类报告进行阈值的设定。需要注意的是,不要再训练集上设置阈值,否则可能得到过于乐观的结果。

3.1.2 准确率-召回率曲线

对于阈值的设定,可以借助准确率-召回率曲线。这里需要借助
sklearn.metrics模块中的precision_recall_curve函数,其返回按顺序排序的所有可能阈值对应的准确率和召回率。

sklearn.metrics.precision_recall_curve(y_true, probas_pred, *, pos_label=None, sample_weight=None)

注意一点,y_ture中如果不是{-1,1}也不是{0,1},则应该明确给出pos_label=1。

还需要进行学习的有平均准确率,即准确率-召回率曲线下的积分或面积,使用sklearn.metrics模块中的average_precision_score函数来计算。

sklearn.metrics.average_precision_score(y_true, y_score, *, average=‘macro’, pos_label=1, sample_weight=None)

3.1.3 ROC曲线和AUC

还有一种常用的工具可以分析不同阈值的分类器行为:受试者工作特征曲线(ROC曲线)。与准确率-召回率曲线类似,ROC曲线考虑了给定的分类器所有可能阈值,但它显示的是假正例率(FPR)和真正例率(TPR)。真正例率是找汇率的一个名称,假正例率则是假正例数占所有反类样本的比例。
假正例率
使用sklearn.metrics模块中的roc_curve函数来计算,用法与准确率-召回率曲线类似。

sklearn.metrics.roc_curve(y_true, y_score, *, pos_label=None, sample_weight=None, drop_intermediate=True)

其中drop_intermediate bool,默认为True。是否降低一些不会出现在绘制的ROC曲线上的非最佳阈值。这对于创建较浅的ROC曲线很有用。

相对于准确率召回率曲线,我们希望两者都保持很高的值。ROC曲线,我们希望召回率很高,假正例率保持很低的水平。
我们同样需要一个数字来总结ROC曲线,即曲线下的面积(通常被称为AUC),使用sklearn.metrics模块中的roc_auc_score函数来计算。

sklearn.metrics.roc_auc_score(y_true, y_score, *, average=‘macro’, sample_weight=None, max_fpr=None, multi_class=‘raise’, labels=None)

4 学习模型

4.1 算法原理的简单介绍

4.1.1 以最小二乘法为例

求导过程
注意:不做说明的向量默认为列向量。由上述过程可知,求参数过程,难点是求矩阵的逆。

4.1.2 简单介绍相关矩阵的求导

矩阵求导的本质是:若两个矩阵A,B,B对A求导,则是B中的每个元数对A中的每个元素求导。
依据两个规则:
1,标量不变矩阵变。
2,上方横向拉伸,下方纵向拉伸。

依据上面所述的内容,对常见的矩阵形式进行求导
矩阵求导的简单演示

4.1.3 相关模型的选择

可以根据实际问题参照模型选择的知道进行相关模型的选择。
模型选择参考

总结

对机器学习先前不是很了解的部分,包括一些数学知识进行了重新的学习。还有一部分不是很难理解,希望通过实际案例,在项目中中进行再次跟进。,

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值