Python机器学习软件包Scikit-Learn的学习与运用

第1关:使用scikit-learn导入数据集

任务描述

使用 scikit-learndatasets模块导入 iris 数据集,并打印数据。

相关知识

scikit-learn 包括一些标准数据集,不需要从外部下载,可直接导入使用,比如与分类问题相关的 Iris数据集digits手写图像数据集 ,与回归问题相关的 波士顿房价数据集

以下列举一些简单的数据集,括号内表示对应的问题是分类还是回归:

#加载并返回波士顿房价数据集(回归)
load_boston([return_X_y])
#加载并返回iris数据集(分类)
load_iris([return_X_y])
#加载并返回糖尿病数据集(回归)
load_diabetes([return_X_y])
#加载并返回数字数据集(分类)
load_digits([n_class, return_X_y])
#加载并返回linnerud数据集(多分类)
load_linnerud([return_X_y])

这些标准数据集采用类字典的对象格式存储,比如 .data 表示原始数据,是一个 (n_samples,n_features) 二维数组,通过 .shape 可以得到二维数组大小,.target 表示存储数据类别即标签。

下面我们将利用 datasets 加载数据集 digits 作为示例,如下图所示:
在这里插入图片描述
在命令行输入 python 进入 Python 终端,>>> 表示 Python 终端提示符,输入 Python 命令即可执行。y[:5] 表示标签的前 5 个数据。

编程要求

本关任务是,使用 scikit-learndatasets 模块导入 iris数据集,提取前 5 条原数据、前 5 条数据标签及原数据的数组大小。
请按照编程要求,补全右侧编辑器 Begin-End 区间的代码。

from sklearn import datasetsdef getIrisData():

    '''    导入Iris数据集
    返回值:
    X - 前5条训练特征数据
    y - 前5条训练数据类别
    X_shape - 训练特征数据的二维数组大小
    '''
    
    #初始化
    X = []
    y = []
    X_shape = () 
    
    #   请在此添加实现代码   #
    #********** Begin *********#
    iris = datasets.load_iris()
    X = iris.data
    y = iris.target
    X_shape = X.shape
    X = X[:5]
    y = y[:5]
    #********** End **********#
    
    return X,y,X_shape

测试说明

本关的测试文件是 step1/testImportData.py ,该代码负责对你的实现代码进行测试,注意 step1/testImportData.py 不能被修改,该测试代码具体如下:

import importData
X,y,X_shape = importData.getIrisData()

print(X)
print(y)
print(X_shape)

第2关:数据预处理 — 标准化

任务描述

在前一关卡,我们已经学会了使用 sklearn 导入数据,然而原始数据总是比较杂乱、不规整的,直接加载至模型中训练,会影响预测效果。
本关卡,将学习使用sklearn 对导入的数据进行预处理。

相关知识

原始数据存在的几个问题:不一致、重复、含噪声、维度高。数据挖掘中,数据预处理包含数据清洗、数据集成、数据变换和数据归约几种方法,在这里不过多叙述预处理方法细节。
接下来将简单介绍,如何通过调用 sklearn 中的模块进行数据预处理。

sklearn.preprocessing 模块提供很多公共的方法,将原始不规整的数据转化为更适合分类器的具有代表性的数据。一般说来,使用标准化后的数据集训练学习模型具有更好的效果。

数据标准化的方法有很多种,常用的有“最小—最大标准化”、“Z-score标准化”等等。经过上述标准化处理,各属性值都处于同一个数量级别上,可以进行综合数据分析。

Z-score 标准化

这种方法基于原始数据的均值(mean)和标准差(standard deviation)进行数据的标准化。将 A 的原始值 x 使用 Z-score 标准化到 x’。
Z-score 标准化方法适用于属性A的最大值和最小值未知的情况,或有超出取值范围的离群数据的情况,其公式为:
新数据 =(原数据-均值)/ 标准差

sklearn.preprocessing.scale 函数,可以直接将给定数据进行标准化。在这里插入图片描述
标准化处理后,数据的均值和方差:在这里插入图片描述
sklearn.preprocessing.StandardScaler 类实现了 Transformer 接口,可以保存训练数据中的参数(均值 mean_、缩放比例 scale_),并能将其应用到测试数据的标准化转换中。
在这里插入图片描述
将标准化转换器应用到新的测试数据:在这里插入图片描述

min-max 标准化

min-max 标准化方法是对原始数据进行线性变换。设 minA 和 maxA 分别为属性 A 的最小值和最大值,将 A 的一个原始值 x 通过 min-max 标准化,映射成在区间[0,1]中的值 x’,其公式为:
新数据 =(原数据-极小值)/(极大值-极小值)

sklearn.preprocessing.MinMaxScaler 将属性缩放到一个指定的最大和最小值(通常是1-0)之间。
MinMaxScaler 中可以通过设置参数 feature_range=(min, max) 指定最大最小区间。其具体的计算公式为:

X_std = (X - X.min(axis=0)) / (X.max(axis=0) - X.min(axis=0))
X_scaled = X_std * (max - min) + min

在这里插入图片描述
将标准化缩放,应用到新的测试数据:在这里插入图片描述

编程要求

本关任务希望对于 California housing 数据集进行标准化转换。

代码中已通过 fetch_california_housing 函数加载好了数据集 California housing 数据集包含 8 个特征,分别是 ['MedInc', 'HouseAge', 'AveRooms', 'AveBedrms', 'Population', 'AveOccup', 'Latitude', 'Longitude'] ,可通过 dataset.feature_names 访问数据具体的特征名称,通过在上一关卡的学习,相信大家对于原始数据的查看应该比较熟练了,在这里不过多说明。

本次任务只对 California housing 数据集中的两个特征进行操作,分别是第 1 个特征 MedInc,其数据服从长尾分布;第 6 个特征 AveOccup,数据中包含大量离群点。

本关分成为几个子任务:
1.使用 MinMaxScaler 对特征数据 X 进行标准化转换,并返回转换后的特征数据的前 5 条;
2.使用 scale 对目标数据 y 进行标准化转换,并返回转换后的前 5 条数据;
3.使用 StandardScaler 对特征数据 X 的进行标准化转换,并返回转换后的均值和缩放比例值。

from sklearn.preprocessing import MinMaxScaler
from sklearn.preprocessing import scale
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import fetch_california_housing
'''Data descrption:The data contains 20,640 observations on 9 variables.This dataset contains 
the average house value as target variableand the following input variables (features): 
average income,housing average age, average rooms, average bedrooms, population,
average occupation, latitude, and longitude in that order.
dataset : dict-like object with the following attributes:
	dataset.data : ndarray, shape [20640, 8]
		Each row corresponding to the 8 feature values in order.
	dataset.target : numpy array of shape (20640,)
		Each value corresponds to the average house value in units of 100,000.
	dataset.feature_names : array of length 8
		Array of ordered feature names used in the dataset.
	dataset.DESCR : string
		Description of the California housing dataset.'''
dataset = fetch_california_housing("./step4/")
X_full, y = dataset.data, dataset.target
#抽取其中两个特征数据
X = X_full[:, [0, 5]]

def getMinMaxScalerValue():
	'''
	对特征数据X进行MinMaxScaler标准化转换,并返回转换后的数据前5条
	返回值:
	X_first5 - 数据列表
	'''
	X_first5 = []
	#   请在此添加实现代码   #
	# ********** Begin *********#
	min_max_scaler = MinMaxScaler()
	X_minmax = min_max_scaler.fit_transform(X)
	X_first5 = X_minmax[:5]
	# ********** End **********#
	return X_first5
def getScaleValue():
	'''
	对目标数据y进行简单scale标准化转换,并返回转换后的数据前5条
	返回值:
	y_first5 - 数据列表
	'''
	y_first5 = []
	#   请在此添加实现代码   #
	# ********** Begin *********#
	y_scaled = scale(y)
	y_first5 = y_scaled[:5]
	# ********** End **********#
	return y_first5
def getStandardScalerValue():
	'''
	对特征数据X进行StandardScaler标准化转换,并返回转换后的数据均值和缩放比例
	返回值:
	X_mean - 均值
	X_scale - 缩放比例值
	'''
	X_mean = None
	X_scale = None
	#   请在此添加实现代码   #
	#********** Begin *********#
	scaler = StandardScaler().fit(X)
	X_mean = scaler.mean_
	X_scale = scaler.scale_
	#********** End **********#
	return X_mean,X_scale

第3关:文本数据特征提取

任务描述

在前一关卡,我们已经学会了数据集标准化处理,标准化一般主要针对数值型数据。对于文本数据,我们无法直接将原始文本作为训练数据,需通过特征提取将其转化为特征向量。本关卡,将学习提取文本数据特征的基本操作。

相关知识

文本分析是机器学习算法的一个主要应用领域。文本分析的原始数据无法直接输入算法,因为大部分算法期望的输入,是固定长度的数值特征向量,而不是可变长的文本数据。
为了解决这个问题,sklearn 提供了一些实用工具,用最常见的方式从文本内容中抽取数值特征。比如说:

  • 分词(tokenizing),对句子分词后,为每一个词(token)分配的一个整型 id,通常用空格和标点符号作为分词的分割符;
  • 计数(counting),计算某个词在文本中的出现频率;
  • 归一化权重(nomalizating and weighting), 降低在大多数样本/文档中都出现的词的权重。

在文本特征提取中,特征和样本的定义如下:

  • 将每个词出现的频率作为特征;
  • 将给定文档中所有词的出现频率所构成的向量看做一个样本。

因此,整个语料库可以看做一个矩阵,矩阵的每行代表一个文档,每列代表一个分词。我们将文档集合转化为数值特征向量的过程称为向量化。这一整套策略被称为词袋模型,用词频描述文档,完全忽略词在文档中出现的相对位置信息。

sklearn中文本数据特征提取的方法

CountVectorizer 模块实现了分词和计数,该方法包含许多参数,如下图所示,打印了其默认的参数值。在这里插入图片描述
常见参数:
input : 指定输入格式;
tokenizer : 指定分词器;
stop_words : 指定停止词,比如当设置 stop_words="english"时,将会使用内建的英语停用词列表;
max_df : 设置最大词频,若为浮点数且范围在[0,1]之间,则表示频率,若为整数则表示频数;
min_df : 设置最小词频;
max_features: 设置最大的特征数量;
vocabulary: 指定语料库,即指定词和特征索引间的映射关系表。
属性:
vocabulary_ : 字典类型,返回词和特征索引间的映射关系表;

#得到词汇映射表
vocab = vectorizer.vocabulary_
#字典结构,返回特征值‘document’对应的下标索引
vectorizer.vocabulary_.get('document')

stop_words_ : set 集合,停止词集合。
方法:
fit(raw_documents[, y]) : 从原文本数据得到词汇-特征索引间的映射关系;
transform(raw_documents) :将原文本集合转换为特征矩阵;
fit_transform(raw_documents[, y]): 结合 fit 和 transform 方法,返回特征矩阵,如下图所示:在这里插入图片描述
build_analyzer():返回预处理和分词的引用;
下图表示对“This is a text document to analyze.”进行分词并验证结果。在这里插入图片描述
get_feature_names():返回特征索引id对应的特征名字(下标对应的某个词);在这里插入图片描述
将向量化转换器应用到新的测试数据。在这里插入图片描述

注意:transform 函数的返回结果是一个矩阵(sparse matrix),为了更好的表示数据,采用 toarray() 将数据转化为 numpy 数组,注意接下来的编程任务中,也要转化为一个数组。

在文本语料库中,一些词非常常见(例如,英文中的“the”,“a”,“is”),但是有用信息含量不高。如果我们将词频直接输入分类器,那些频繁出现的词会掩盖那些很少出现,但是更有意义的词,将达不到比较好的预期效果。为了重新计算特征的计数权重,通常都会进行 TFIDF 转换。

TFIDF 的主要思想是:如果某个词或短语在一篇文章中出现的频率高,并且在其他文章中很少出现,则认为此词或者短语具有很好的类别区分能力,适合用来分类。
TFIDF 实际上是:TF * IDF,TF 词频(Term Frequency),IDF 反文档频率(Inverse Document Frequency)。TF 词频(Term Frequency)指的是某一个给定的词语在该文件中出现的次数。IDF 反文档频率(Inverse Document Frequency)是指如果包含词条的文档越少,IDF 越大,则说明词条具有很好的类别区分能力。

sklearn 中的 TfidfVectorizer 模块,实现了 TFIDF 思想。该模块的参数、属性及方法与 CountVectorizer 类似,可参考 CountVectorizer 的调用方式。

编程要求

本关任务,希望分别使用 CountVectorizer 和 TfidfVectorizer 对新闻文本数据进行特征提取,并验证提取是否正确。

数据介绍:
采用 fetch_20newsgroups("./step5/",subset='train', categories=categories) 函数加载对应目录的新闻数据,subset='train' 指定采用的是该数据的训练集,categories 指定新闻目录,具体的函数调用可参考官方文档 fetch_20newsgroups 。X 是一个 string 数组,包含 857 个新闻文档。

本关具体分成为几个子任务:
1.使用 CountVectorizer 方法提取新闻数据的特征向量,返回词汇表大小和前五条特征向量;
2.使用 TfidfVectorizer 方法得到新闻数据的词汇-特征向量映射关系,指定使用内建的英文停止词列表作为停止词,并且词出现的最小频数等于 2。然后,将向量化转换器应用到新的测试数据。

from sklearn.datasets import fetch_20newsgroups
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfVectorizer

categories = [
	'alt.atheism',
	'talk.religion.misc',
]

# 加载对应目录的新闻数据,包含857个文档
data = fetch_20newsgroups("./step5/",subset='train', categories=categories)
X = data.data

def transfer2CountVector():
	'''
	使用CountVectorizer方法提取特征向量,返回词汇表大小和前五条特征向量
	返回值:
	vocab_len - 标量,词汇表大小
	tokenizer_list - 数组,对测试字符串test_str进行分词后的结果
	'''
	vocab_len = 0
	test_str = "what's your favorite programming language?"
	tokenizer_list = []
	
	#   请在此添加实现代码   #
	# ********** Begin *********#
	vectorizer = CountVectorizer()
	vectorizer.fit_transform(X)
	
	vocab = vectorizer.vocabulary_
	vocab_len = len(vocab)
	
	analyze = vectorizer.build_analyzer()
	tokenizer_list = analyze(test_str)
	# ********** End **********#
	return vocab_len,tokenizer_list
	
def transfer2TfidfVector():
	'''
	使用TfidfVectorizer方法提取特征向量,并将向量化转换器应用到新的测试数据
	TfidfVectorizer()方法的参数设置:
	min_df = 2,stop_words="english"
	test_data - 需要转换的原数据
	
	返回值:
        transfer_test_data - 二维数组ndarray
        '''
	test_data = ['Once again, to not believe in God is different than saying\n>I BELIEVE that God does not exist. I still maintain the position, even\n>after reading the FAQs, that strong atheism requires faith.\n>\n \nNo it in the way it is usually used. In my view, you are saying here that\ndriving a car requires faith that the car drives.\n \nFor me it is a conclusion, and I have no more faith in it than I have in the\npremises and the argument used.\n \n \n>But first let me say the following.\n>We might have a language problem here - in regards to "faith" and\n>"existence". I, as a Christian, maintain that God does not exist.\n>To exist means to have being in space and time. God does not HAVE\n>being - God IS Being. Kierkegaard once said that God does not\n>exist, He is eternal. With this said, I feel it\'s rather pointless\n>to debate the so called "existence" of God - and that is not what\n>I\'m doing here. I believe that God is the source and ground of\n>being. When you say that "god does not exist", I also accept this\n>statement - but we obviously mean two different things by it. However,\n>in what follows I will use the phrase "the existence of God" in it\'s\n>\'usual sense\' - and this is the sense that I think you are using it.\n>I would like a clarification upon what you mean by "the existence of\n>God".\n>\n \nNo, that\'s a word game. The term god is used in a different way usually.\nWhen you use a different definition it is your thing, but until it is\ncommonly accepted you would have to say the way I define god is ... and\nthat does not exist, it is existence itself, so I say it does not exist.\n \nInterestingly, there are those who say that "existence exists" is one of\nthe indubitable statements possible.\n \nFurther, saying god is existence is either a waste of time, existence is\nalready used and there is no need to replace it by god, or you are implying\nmore with it, in which case your definition and your argument so far\nare incomplete, making it a fallacy.\n \n \n(Deletion)\n>One can never prove that God does or does not exist. When you say\n>that you believe God does not exist, and that this is an opinion\n>"based upon observation", I will have to ask "what observtions are\n>you refering to?" There are NO observations - pro or con - that\n>are valid here in establishing a POSITIVE belief.\n(Deletion)\n \nWhere does that follow? Aren\'t observations based on the assumption\nthat something exists?\n \nAnd wouldn\'t you say there is a level of definition that the assumption\n"god is" is meaningful. If not, I would reject that concept anyway.\n \nSo, where is your evidence for that "god is" is meaningful at some level?\n   Benedikt\n']
	transfer_test_data = None
	
	#   请在此添加实现代码   #
	# ********** Begin *********#
	tfidf_vertor = TfidfVectorizer(min_df=2, stop_words="english")
	tfidf_vertor.fit(X)
	transfer_test_data = tfidf_vertor.transform(test_data).toarray()
	# ********** End **********#
	return transfer_test_data

第4关:使用scikit-learn分类器SVM对digits数据分类

任务描述

采用 scikit-learn 中的 svm 模型,训练一个对 digits 数据集进行分类的模型。

相关知识

在 scikit-learn 中,对于分类问题的估计器是一个实现了 fit(X, y)predict(T) 方法的 Python 对象。估计器的实例很多,例如实现了支持向量分类的类 sklearn.svm.svc。估计器的结构可以通过初始化模型时设置的参数决定,但目前,我们将估计器看做一个黑盒子,先不关心具体的参数设置。
digits 数据集中包含大量的数字图片,如下图所示,我们希望给定其中的一张图片,能识别图中代表的数字,这是一个分类问题,数字 0…9 代表十个分类,目标是希望能正确估计图中样本属于哪一个数字类别。
在这里插入图片描述
digits 数据集可以通过以下命令导入:

from sklearn import datasets
digits = datasets.load_digits()

digits 的原始图像采用一个(8,8)的二维数组表示,如下图所示:在这里插入图片描述
可以通过 digits.data 查看图片数据表示,行表示样本数量,列表示样本特征(将 (8,8) 的矩阵压缩成一行,可以从digits.data.shape的列数为 64 维看出);digits.target 给出 digits 数据集的真实值,即我们要学习的每个数字图像对应的数字。

本关任务

本关要求采用 scikit-learn 中的 svm 模型,训练一个对 digits 数据集进行分类的模型。训练集是 digits 数据集的前半部分数据,测试集是 digits 数据集的后半部分数据。根据要求,补全右侧编辑器 Begin-End 区间的代码。

# 使用前一半的数据集作为训练数据,后一半数据集作为测试数据
train_data,train_target = data[:n_samples // 2],digits.target[:n_samples // 2]
test_data,test_target = data[n_samples // 2:],digits.target[n_samples // 2:]

希望通过训练集,训练出分类模型,对于测试集数据能正确预测出图片对应的数字(0…9)。
本关需编程实现 step2/digitsClassification.pycreateModelandPredict() 函数创建分类模型并预测:
predicted 是模型对测试数据的预测值,该函数会返回预测值,并在测试文件中检测是否正确。

另外,step2/digitsClassification.py 代码中包含两个显示样本图像的函数分别是 show4TrainImage()show4TestImage(),分别用来显示训练集的前 4 张图像,和模型预测值的前 4 张图像,大家可以通过在本机 Python 环境调用这两个函数直观查看原始样本集,并且验证预测是否正确,如下图所示:
在这里插入图片描述
在这里插入图片描述
拓展(本次不需要实现):
从预测集的图像可以看出,并不是完全预测正确,这一点是很正常的,说明使用默认的 svc 训练模型的无法完全将测试集正确分类,可以通过调整模型的参数使分类更准确,大家可以尝试下设置参数gamma=0.001重新训练模型并预测看是否准确。

import matplotlib.pyplot as plt
# 导入数据集,分类器相关包
from sklearn import datasets, svm, metrics

# 导入digits数据集
digits = datasets.load_digits()
n_samples = len(digits.data)
data = digits.data

# 使用前一半的数据集作为训练数据,后一半数据集作为测试数据
train_data,train_target = data[:n_samples // 2],digits.target[:n_samples // 2]
test_data,test_target = data[n_samples // 2:],digits.target[n_samples // 2:]

def createModelandPredict():
	'''
	创建分类模型并对测试数据预测
	返回值:
	predicted - 测试数据预测分类值
	'''
	predicted = None
	#   请在此添加实现代码   #
	#********** Begin *********#
	classifier = svm.SVC()
	classifier.fit(train_data,train_target)
	predicted = classifier.predict(test_data)
	#********** End **********#
	return predicted
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值