写在前面:新手小白刚上路,有些晦涩难懂,遂以个人博客的形式记录下来,主要用于巩固自己学到的知识以及便于后期查询,也欢迎处在同一学习阶段朋友的交流。老鸟勿喷,欢迎指正。
原视频教程:B站-黑马程序员-3天快速入门机器学习。
目录
一、关于机器学习的简单入门介绍
1.1 什么是机器学习?
机器学习是人工智能的一个实现途径;
深度学习是机器学习的一个方法发展而来。
机器学习就是用机器来模仿人类学习以及其它方面的智能。
机器学习定义:机器学习是从数据中自动分析获得模型,并利用模型对未知数据进行预测。
1.2 数据集的构成
数据集是用于机器学习的数据,数据集一般由特征值和目标值两方面构成。
但是,有些数据集可以没有目标值,依据数据本身的特征来分类。
也就是“有监督学习”(supervised learning)和“无监督学习”(unsupervised learning)的区别。
1.3 机器学习的算法分类
(1)类别的分类问题,目标值是离散型的数据。
例如,给出猫和狗的图片,识别一张图片是猫还是狗。
特征值是猫和狗的图片,目标值是猫和狗的类别。
代表算法:K-近邻算法、贝叶斯分类、决策树与随机森林、逻辑回归。
(2)数据的回归问题,目标值是连续型的数据。
例如,根据房屋的各个属性(如地段、朝向等)来预测房屋的价格,价格就是连续型的数据。
特征值是房屋的各个属性信息,目标值是房屋价格(连续型数据)。
代表算法:线性回归、岭回归。
(3)聚类问题。数据集构成提到有些数据集没有目标值,即无监督学习,输入特征没有标签,依据数据本身的特征来分类。
代表算法:K-means聚类。
1.4 机器学习的开发流程
(1)获取数据
(2)数据处理:处理数据比较嘈杂或者缺失值
(3)特征工程:也算数据处理,这一步将数据处理成更能直接被机器学习算法使用的数据
(4)机器学习算法训练得到模型
(5)模型评估
(6)模型应用
(可搜索相关教程,爬虫获取数据、数据分析处理数据、机器学习训练数据,更能深刻理解一整套的流程)
1.5 机器学习入门建议
(1)明确重点:算法是核心,数据和计算是基础。(一定要做好训练数据)
(2)应用入门:先掌握一些机器学习算法等技巧,从某个业务领域切入解决问题。
(3)分析问题:先明确使用机器学习算法的目的是想完成什么样的任务,用算法想干什么事。
(4)掌握算法:掌握算法基本思想,对某个问题的应用能想到用相应的、合适的算法去解决。
(5)经典书籍:如果看书的话,先看实战类的书籍。如果想深入了解某一块,专业类的经典书籍有:《机器学习》,也被称作“西瓜书”,作者周志华;《统计学习方法》,作者李航;《深度学习》,也被称作“花书”,作者Ian Goodfellow、Yoshua Bengio 和Aaron Courville;
(6)其它:学会利用库或框架解决问题。(机器学习算法sklearn,深度学习框架tensorflow(谷歌出的)、pytorch、caffe(这俩是facebook出的)等,tensorflow目前用的人最多)
(总之,就是先入门看看教程,大致有个了解;再想深入了解某一领域的应用,看一些实战类书籍;再想深入研究某一块,看高认可度的经典书籍。)
二、特征工程
2.1 数据集
2.1.1 sklearn数据集
(1)获取数据集API
获取小规模的数据集,直接自带
datasets.load_*()
例如,获取经典鸢尾花数据集
sklearn.datasets.load_iris()
获取大规模的数据集,要从网上下载
第一个参数data_home是数据集下载的目录,默认~/scikit_learn_data/
datasets.fetch_*(data_home=None)
例如,获取经典的新闻文本分类数据集
subset可以选“train”, "test", "all",就是获取训练集、测试集还是两者都要
sklearn.datasets.fetch_20newsgroups(data_home=None, subset='train')
(2)sklearn数据集的返回值:
load和fetch返回的数据类型datasets.base.Bunch(字典格式)
data:特征数据数组,是[n_samples * n_features]的二维numpy.ndarray数组
target:标签数组,是n_samples的一位numpy.ndarray数组
DESCR:数据描述
feature_names:特征名。新闻数据、手写数字、回归数据集没有
target_names:标签名
2.1.2 数据集的划分
(1)数据集一般被划分为训练集和测试集。
训练集:用于训练、构建模型;
测试集:在模型检验时使用,用于评估模型是否有效;
(2)数据集划分的API:
sklearn.model_selection.train_test_split(arrays, *options)
test_size:测试集的大小(如果不设置,默认0.25)
random_state:随机数种子,不同种子会造成不同的随机采样结果。
(3)示例如下:
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
def datasets_demo():
"""
sklearn数据集使用
:return:
"""
# 获取数据集
iris = load_iris()
print("鸢尾花数据集:\n", iris)
print("查看数据集描述:\n", iris["DESCR"])
print("查看特征值的名字:\n", iris.feature_names)
print("查看特征值:\n", iris.data, iris.data.shape)
# 数据集划分
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, x_train.shape)
return None
if __name__ == "__main__":
# 代码1:sklearn数据集使用
datasets_demo()
2.2 特征工程介绍
(1)为什么要做特征工程:数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限而已。
(2)什么是特征工程:处理数据是特征能在机器学习过程中发挥更好作用的过程,特征工程会直接影响机器学习的效果。
(3)数据处理的比较:sklearn做特征工程;pandas做数据清洗、数据处理。
(4)特征工程包含内容:特征抽取(特征提取)、特征预处理、特征降维。
以下内容如图所示,按需查看。
2.3 特征抽取
(1)什么是特征抽取:将任意数据(如文本或图像)转换为可用于机器学习的数字特征,也叫做特征值化。例如,将类别属性特征通过one_hot编码处理成数字的哑变量使其用于机器学习的识别。
(2)特征抽取方法:对不同原始数据也有不同的转换方法:字典就用字典特征提取(特征离散化);文本就用文本特征提取;图像就用图像特征提取(深度学习方法更好)。
2.3.1 字典特征抽取
(1)字典特征抽取的作用:将类别属性特征转为one-hot编码。
(2)字典特征抽取的API:
sklearn.feature_extraction.DictVectorizer(sparse=True, ...)
·DictVectorizer.fit_transform(X) X:字典或者包含字典的迭代器,返回值:返回sparse矩阵
·DictVectorizer.inverse_transform(X) X:array数组或者sparse矩阵,返回值:转换之前的数据格式
·DictVectorizer.get_feature_names() 返回值:类别名称
(sparse=True返回的就是稀疏矩阵,sparse=False返回的就是二维数组,两者等价)
(sparse矩阵的作用就是将非零值按位置表示出来,不表示零值,可以节省内存进而提高加载效率)
(3)示例如下:
from sklearn.feature_extraction import DictVectorizer
def dict_demo():
"""
字典特征抽取
:return:
"""
data = [{'city': '北京','temperature':100}, {'city': '上海','temperature':60}, {'city': '深圳','temperature':30}]
# 1、实例化一个转换器类
transfer = DictVectorizer(sparse=True)
# 2、调用fit_transform()
data_new = transfer.fit_transform(data) # fit是计算,transform是转换
print("data_new:\n", data_new, type(data_new))
print("特征名字:\n", transfer.get_feature_names())
return None
if __name__ == "__main__":
# 代码2:字典特征抽取
dict_demo()
2.3.2 文本特征提取
(1)文本特征抽取的作用:统计每个样本中特征词出现的次数
(2)文本特征提取的API:
sklearn.feature_extraction.text.CountVectorizer(stop_words=[]) 返回值:返回词频矩阵
(stop_words是停用词,在文本中不想被统计的没有什么意义的词,可以以列表的形式传给CountVectorizer,也可以借助专业NLP机构已经开发的停用词表)
·CountVectorizer.fit_transform(X) X:文本或者包含文本字符串的可迭代对象,返回值:返回sparse矩阵
·CountVectorizer.inverse_transform(X) X:array数组或者sparse矩阵,返回值:转换之前的数据格式
·CountVectorizer.get_feature_names() 返回值:单词列表
(3)示例如下:
from sklearn.feature_extraction.text import CountVectorizer
def count_demo():
"""
文本特征抽取:CountVecotrizer
:return:
"""
data = ["life is short,i like like python", "life is too long,i dislike python"]
# 1、实例化一个转换器类
transfer = CountVectorizer(stop_words=["is", "too"])
# 2、调用fit_transform
data_new = transfer.fit_transform(data) # fit是计算,transform是转换
print("data_new:\n", data_new)
print("特征名字:\n", transfer.get_feature_names())
return None
if __name__ == "__main__":
# 代码3:文本特征抽取:CountVecotrizer
count_demo()
(此时没有设置sparse=True或False,默认返回的是词频计数的稀疏矩阵,如果想返回值是二维数组,类似于上述“代码2”直接设置“sparse=False”是不可取的,会报错。可以在代码3中做出以下修改,上述代码2也同理,即使不设置sparse=True或False,加上*.toarray.()就可以输出二维数组了)
print("data_new:\n", data_new.toarray())
(4)那,中文的文本特征词怎么提取呢?
如果数据文本是中文语句的话,程序默认每一句话作为一个特征词。例如,将上述英文文本改为中文文本。
data = ["我爱北京天安门", "天安门上太阳升"]
此时输出的是两个特征词(一句话一个特征词)。
data_new:
[[0 1]
[1 0]]
特征名字:
['天安门上太阳升', '我爱北京天安门']
原因在于英文文本在每个单词中间会以空格隔开,而中文文本是连续的,中间没有空格。如果把中文语句按照词组隔开,进行分词,则每个词组就是一个特征词。例如
data = ["我 爱 北京 天安门", "天安门 上 太阳 升"]
此时输出的是,类似于英文文本那样的词频统计。
data_new:
[[1 1 0]
[0 1 1]]
特征名字:
['北京', '天安门', '太阳']
(5)借助自动分词工具jieba
但手工分词在实际应用中显然是不可取的,于是就借助分词工具,例如jieba分词工具。例如:
from sklearn.feature_extraction.text import CountVectorizer
import jieba
def cut_word(text):
"""
进行中文分词:"我爱北京天安门" --> "我 爱 北京 天安门"
:param text:
:return:
"""
text = " ".join(list(jieba.cut(text))) # jieba_cut是词语生成器,list转成列表形式,join转成字符串类型
return text
def count_chinese_demo2():
"""
中文文本特征抽取,自动分词
:return:
"""
# 将中文文本进行分词
data = ["一种还是一种今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。",
"我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去。",
"如果只用一种方式了解某样事物,你就不会真正了解它。了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。"]
data_new = []
for sent in data:
data_new.append(cut_word(sent)) # append往元素里面添加内容
# print(data_new)
# 1、实例化一个转换器类
transfer = CountVectorizer(stop_words=["一种", "所以"])
# 2、调用fit_transform
data_final = transfer.fit_transform(data_new) # fit是计算,transform是转换
print("data_new:\n", data_final.toarray())
print("特征名字:\n", transfer.get_feature_names())
return None
if __name__ == "__main__":
# 代码4:中文文本特征抽取,自动分词
count_chinese_demo2()
(6)Tf-idf文本特征提取
1)Tf-idf文本特征提取的作用:如果某个词或者短语在一篇文章中出现的频率高,并且在其它文章中很少出现,则认为该词或短语具有很好的类别区分能力,适合用来分类。TF-IDF的作用就是用以评估一个词对于数据的重要程度,简而言之就是衡量一个词的重要程度。
词频(term frequency, tf)是某一个词语在该文件中出现的频率;
逆向文档频率(inverse document frequency, idf)是一个词语普遍重要性的度量,某个词语的idf,可以由总文件数目除以包含该词语的文件的数目,再将结果取以10为底的对数得到。
2)TF-IDF的公式:
例如,语料库有1000篇文章,有100篇文章有“非常”,有10篇文章有“经济”。
文章A有100个词,出现了10次“经济”,则 tf = 10/100 = 0.1,idf = lg(1000/10) = 2
文章B有100个词,出现了10次“非常”,则 tf = 10/100 = 0.1;idf = lg(1000/100) = 1
通过 tf 无法判断这两个词对于数据的重要程度。
“经济”的tfidf = 0.2;“非常”的tfidf = 0.1
则“经济”相对于“非常”在语料库中的重要程度更高。
3)TF-IDF文本特征提取的API:
sklearn.feature_extraction.text.TfidfVectorizer(stop_words=None, ...)
返回词的权重矩阵
TfidfVectorizer.fit_transform(X) X:文本或者包含文本字符串的可迭代对象;返回值:返回sparse矩阵
TfidfVectorizer.inverse_transform(X) X:array数组或者sparse矩阵;返回值:转换之前数据格式
TfidfVectorizer.get_feature_names(X) 返回值:单词列表
4)TF-IDF文本特征抽取示例如下:(与代码4非常类似。里面只有文本特征抽取,后面可以找案例进行tf-idf计算的案例实践)
from sklearn.feature_extraction.text import CountVectorizer, TfidfVectorizer
import jieba
def cut_word(text):
"""
进行中文分词:"我爱北京天安门" --> "我 爱 北京 天安门"
:param text:
:return:
"""
text = " ".join(list(jieba.cut(text))) # jieba_cut是词语生成器,list转成列表形式,join转成字符串类型
return text
def tfidf_demo():
"""
用TF-IDF的方法进行文本特征抽取
:return:
"""
# 将中文文本进行分词
data = ["一种还是一种今天很残酷,明天更残酷,后天