import numpy as np
= {i : np.random.randn() for i in range(7)}
data data
{0: -0.6641839891537453,
1: 0.5097008879665877,
2: 0.6440338445822978,
3: 0.5965156223580141,
4: 0.23135186472436986,
5: -0.2986398249522905,
6: -0.09558735413887375}
September 10, 2022
由于之前的python课没能将一些基础的操作学得透彻,只能再回炉重造一下。
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import seaborn as sns
import statsmodels as sm
conda install nb_conda ### 字符串
由于你可能不太熟悉书中使用的一些有关编程和数据科学方面的常用术语,所以我在这里先给出其简单定义:
数据规整(Munge/Munging/Wrangling) 指的是将非结构化和(或)散乱数据处理为结构化或整洁形式的整个过程。这几个词已经悄悄成为当今数据黑客们的行话了。Munge这个词跟Lunge押韵。
伪码(Pseudocode) 算法或过程的“代码式”描述,而这些代码本身并不是实际有效的源代码。
语法糖(Syntactic sugar) 这是一种编程语法,它并不会带来新的特性,但却能使代码更易读、更易写。
{0: -0.6641839891537453,
1: 0.5097008879665877,
2: 0.6440338445822978,
3: 0.5965156223580141,
4: 0.23135186472436986,
5: -0.2986398249522905,
6: -0.09558735413887375}
通过输入代码并按下 return
运行任意Python语句。当只是输入一个变量,会显示代表的对象:
或者通过在chrome中输入法http://localhost:8888/ 手动打开notebook
在变量前后使用问号,可以显示对象的信息: 这可以作为对象的自省: 若对象是一个函数或实例方法,定义过的文档都可显示出信息;
%run
命令可以使用%run
命令运行所有python程序。假设有一个文件:
#%run ipython_script_test.py
即可实现
Enter : 转入编辑模式
Shift-Enter : 运行本单元,选中下个单元
Ctrl-Enter : 运行本单元
Alt-Enter : 运行本单元,在其下插入新单元
Y : 单元转入代码状态
M :单元转入markdown状态
R : 单元转入raw状态
Tab : 代码补全或缩进
Shift-Tab : 提示
Ctrl-] : 缩进
Ctrl-[ : 解除缩进
Ctrl-A : 全选
Ctrl-Z : 复原
Ctrl-Shift-Z : 再做
Ctrl-Y : 再做
Ctrl-Home : 跳到单元开头
Ctrl-Up : 跳到单元开头
Ctrl-End : 跳到单元末尾
Ctrl-Down : 跳到单元末尾
Ctrl-Left : 跳到左边一个字首
Ctrl-Right : 跳到右边一个字首
Ctrl-Backspace : 删除前面一个字
Ctrl-Delete : 删除后面一个字
笔记:赋值也被称作绑定,我们是把一个名字绑定给一个对象。变量名有时可能被称为绑定变量。
程序的本质是针对数据的一种处理流程,有了不同的数据类型,程序才可以有的放矢的进行各种不同的数据操作。
常用的数值型包括int,float,comlex等。对于数值型的赋值和计算都较为直观。在python中,输入一个赋值语句就直接会将原有赋值清除。
我们还可以对多个变量(对象)进行赋值。
使用\t
来进行转义,还可以使用+
或*
来实现字符串的运算。
元组与列表较为相似,可以用索引进行访问,可同样可以被嵌套,不同在于元组的元素一旦创建就不能再修改。有点像常量版本的列表。 最为简单的创建方式——通过逗号隔开即可
若元组只包含一个元素,则需要在元素之后添加逗号,代码如下:
若不添加的话:
可以看见编译器对tup1
作为一个整型对象,100的外围括号仅仅是一摆设。
因此可以更加简洁的实现生成一个元组,通过逗号进行分割即可实现。
用turble
可以将任意序列转换为元组
因为元组的大小和内容不能修改,它的实例方法都很轻量。其中一个很有用的就是count(也适用于列表),它可以统计某个值得出现频率:
在原先的元组进行插入之后,先通过分片技术,以第2个元素为基点,将原始元组拆分为两个部分,再中间插入一个。
对于不同元组的连接,通过加法操作符可完成。
列表是python中最为常用的一个数据类型,与元组对比,列表的长度可变、内容可以被修改。你可以用方括号定义,不同的数据以逗号,
分隔,或用list
函数:
生成一个空列表
append
可以用于添加元素,insert
可以用于在特定位置插入元素(在指定位置的末尾)
dict1 = {key1: value1,key2:vaule2}
删除的话使用pop
集合和字典差不多
与字典类似,集合元素通常都是不可变的。要获得类似列表的元素,必须转换成元组:
NumPy最重要的一个特点就是其支持N维数组对象(即ndarray),该对象是一个快速而灵活的大数据集容器。你可以利用这种数组对整块数据执行一些数学运算,其语法跟标量元素之间的运算一样。numpy的数组与列表有点相似,但仍然不同的是要纯洁一点,只能是一个数组类型。
因为data2是列表的列表,NumPy数组arr2的两个维度的shape是从data2引入的。可以用属性ndim和shape验证:
每一个数组都有一个dtype属性,用于描述数组的数据类型。 np.array会自动推断数据类型。数据类型被存储在一个特殊的元数据dtype中。
arrage
方法根据start与stop指定的范围及step设定的步长来生成一个ndarray对象,start为起时值。
arange()
根据start与stop指定的范围设定的步长范围,生成一个ndarray对象。
print
的时候的样子是不同于直接输出的
与range()
函数较为相像,但range()
生成的只能用于迭代。(属于一个迭代器)
np.range()
的数据是左开右闭的,最后一个数取不到。当然可以在设置option中指定endpoint=False
精度的不同,n.rate会进行转换,复杂性增大
ts1 tensorflow 深度学习框架,推出一个以tensorprosing n层的数组,tensor一维是一个list,二维就是一个矩阵; 这个方法就可生成
维度(dimension)都是由ndim属性来描述的。
64bit 8byte\ 100M byte 10M bit
对于N维数组而言,还有一个重要的属性是shape(数组形状),形状主要用于表征数组每个维度的数量,一维数组的形状就是它的长度一维也称为1D张量(1D tensor)
取出一列,当最终出来的结果和一行类似; 其实这本身就是函数的概念;
?RandomForestRegressor
A random forest is a meta estimator that fits a number of classifying decision trees on various sub-samples of the dataset and uses averaging to improve the predictive accuracy and control over-fitting. The sub-sample size is controlled with the max_samples
parameter if bootstrap=True
(default), otherwise the whole dataset is used to build each tree.
def
关键词定义开头,后接函数标识符号名称和圆括号()
return
来结束函数,选择性的返回某个特定值给调用方。def return_mul_val():
my_str = "hello world"
num = 20
return my_str,num
str_, x = return_mul_val()
print(str_,x)
hello world 20
看上去好像是返回了多个值,但实际上只是一种假象,在python中,我们上述讨论到一个最为简易的生成元组的方式是通过逗号分隔数据,因此实际上上述的多个返回值本质上返回的是一个元组。
可变参数:在函数调用中,其参数并不固定,比如在使用C语言中,printf
无论传递多少个参数都不会报错,在python中也可以较为方便的实现,在python中实现的方法是通过在形参前添加*
,意味着函数传递的实参个数不定。而在函数内部,都被收集起来作为形参名为某个特定标识符的元组之中。
可变参数就可以被视为是“收集参数”
def mySum(*args):
sum = 0
for i in range(0,len(args)):
sum = sum + args[i]
return sum
print(mySum(1,2,3,4,5))
print(mySum(20.1,22.2))
15
42.3
另一种实现方法是通过两个星号**
标识,将可变参数打包为字典形式。
利用numpy
函数生成数组
需要由一个特定数字序列(0、1、序数和特定统计分布)组成的向量或矩阵,Numpy
函数提供了很多的选择。
生成随机整数的数组(数组无序且可能重复),可以使用下面命令:
与pandas
交互是可以很方便的,事实上,pandas
是建立在Numpy上;
而对于numpy,先需要将列表转化为数组,而这个就直接可以用加号(+
)
还有很多的统计函数: - sum()
- min()
- max()
- mean()
- std()
同时还有一些数学函数: - sin()
- cos()
Numpy都是一个类矩阵的形式,因此NumPy中的数组在进行运算时候,都是基于基础算法库BLAS实现的。
这时元素对元素原则,即数组的元素与元素位置对应相加。
数学意义上的矩阵乘法并非如此,不同形状的矩阵可以进行乘法运算。只要满足第一个矩阵的列与第二个矩阵的行数相同。
转化为矩阵
np.mat()
将非矩阵的数据类型转换为矩阵输出
einsum()
不是一个简单的求和运算,而是一个高效的符号计算规则。
一个例子:点乘公式
仅仅用一个einsum()
就可以实现求和、求外积、矩阵乘法等过程。 sum()
和mat()
以及trace()
就会显得非常繁琐
einsum()
理论上可支持任意多的参数。 - 不同的输入变量之间的格式要用逗号隔开; - 输入格式字符和输出格式字符要用箭头分隔开;
其中张量(数组)a就是一个三维矩阵,ijk是由三个字符构成,类似的输入张量b也是一个三维矩阵。
einsum()
通过求和,将一条线转化为一个点,也就是’i->’的含义。
元素的约简:实现在数量上的减少来反映数据,该原理同样适用于mean
和max
等
索引要么是一个,要么是一片值,自然只能访问一个数组元素。
花式索引是指将多个访问的元素索引汇集起来,构成一个整型数组,然后将这个内含索引的数组,整体作为一个目标数组的索引,一次能够读取多个重复的数组的元素。
将不同的数组需要堆叠stack操作,拼接为一个较大的数组,堆叠方式大致可以分为水平方向堆叠和垂直方向堆叠。
探索性科学(exploratory Data Analysis,EDA)是数据科学的第一步。EDA是John Tukey在1977年提出。
取出数据列表中的一些东西
use the data to plot
分相值需要不断修正得到,一般来说是所有观测值的平方根。len(iris)=150 sqrt(150)=14
不得不将一些包含大量特征的数据集,其中有很多特征不必要的,有些特征包含丰富的信息,有些特征与预测相关。有些事完全不相关的。只是包含噪声或不相关信息。 维数化简,消除输入数据集的某些特征。创建一个有限的特征数据集,这些特征包含所有需要的信息。从而更有效的预测目标变量。减少特征数意味着减少输出的变化性和复杂性(以及时间)。 许多维数化简算法主要假设:数据包含加性高数白噪声(additive white gaussian Noise,AWGN),一种独立的高斯噪声。
协方差矩阵给出了所有不同的特征对之间的相关性。 Iris中有四个特征,通过简单的图形显示容易计算。
主成分分析(principal component analysis,PCA)帮助于定义更小的、更相关特征集合的技术。新的特征就是现有特征的线性组合/旋转(按道理不算新特征) 第二个向量与第一个向量正交,包含剩余能量的大部分。 理想的加性高斯白噪声下。
要加载的数据集过大,而与采用的内存不适应,需要使用统一的机器学习方法。使用python可以加载数据到区块。该操作也称为数据流。 数据集以连续流的形式流入数据框或其他的数据结构中。
PCA的主要问题在于它所采用的奇异值分解的复杂性。Scikit-learn提供了一种基于随机SVD(randomiezd SVD)的算法。 另一方面,随机SVD比经典SVD更为快速。
目前来看的结果是与经典是接近的,但到大数据集中就显著会差异的。
LFA是另一种实现数据集降维分析的技术。总体思路与PCA方法相近。不需要度输入信号进行正交分解,因此没有输出基。 applied:主要在系统中有一个潜在因素或结构的情形。所有的特征是潜在因素经过线性变化后观测到的,具有任意波形发生器(AWG)的噪声。 一般会认为,潜在因素符号高斯分布,具有归一化的协方差。
LDA是一种分类器,经常用于维数约简。LDA是一种监督的方法。需要标签集来优化维数化简的步骤。LDA产生输入特征的线性组合,试图建立最能区分不同类别的模型 与PCA相比,LDA方法获得的输出数据集能够清晰地分出各个类别。
样本是数据科学核心。变量中出现异常高的值,不仅会改变变量的均值和方差等描述性的测量还会影响到很多从数据中学习到的算法。 从而使得这些算法暴露给异常值。 数据点成为异常值的原因: - 数据点表示极少发生的事件,但仍然是一个可能的数据; - 数据点表示经常发生的另一种分布。 - 数据点明显是有某种类型的错误;
数据点的异常如何去说明,单变量的问题通常用EDA分析和箱线图等可视化方式实现。 极端值可以被当作异常值。若使用z-scores,得分绝对值高于3的观测值必需当作可疑异常值。 观测量是用数据描述
加载波士顿房价数据集,数据集中索引为3的变量CHAS是二进制(dummy variable)的,因此不使用该变量做。
由此,单变量方法可以检测出很多的异常值,但不能检测出那些不是极端值的异常值。若他可以发现两个或两个以上的变量组合出现非正常值。仍然会发现这个异常值。 所涉及的变量可能不是极端值,因此这个异常值就可能会漏选。
EllipticEnvelope是用于找出数据总体分布的关键参数的函数。 总体均值要考虑数据集中的所有变量。能够发现单变量和多变量的异常值。
EllipticEnvelope适用于有控制参数的高斯分布假设,而OneClassSVM适用于一种通过学习来得知分布。 - Kernel和Degree:这个两个变量是相关的。 - Gamma:是一个与rbf核相关的参数。 - nu :是一个选择参数,决定模型是否必须符合一个精确的分布,还是应该尽量保持
评估系统的性能并检查与目标距离,需要使用一个能对于结果进行评分的函数。通常有不同的评分函数分别处理二分类、多标号分类、回归或聚类问题。 #### 3.5.1多标号分类 对一个进行预测时候,需要多标号分类。
from sklearn import datasets
iris = datasets.load_iris()
from sklearn.model_selection import train_test_split
x_train,x_test,y_train,y_test=train_test_split(iris.data,iris.target,test_size=.50,random_state=4)
from sklearn.tree import DecisionTreeClassifier
classifier = DecisionTreeClassifier(max_depth=2)
classifier.fit(x_train,y_train)
#用训练数据进行拟合
y_pred = classifier.predict(x_test)
#用测试数据做预测
iris.target_names
准确率(accuracy):准确率表示的是预测标号也是实际标号的比例。
最常用的指标是ROC曲线或AUC曲线。ROC曲线是一种图形化方法,用于表示分类器性能是如何随可能的分类阀值改变的。
MAE(L1 norm)mean_absolute_error
MSE(L2 norm)mean_squared_error
R2,决定了预测器与目标变量之间的线性拟合的好坏,取值在0-1之间。取值越高表示模型越好。sklearn.metrics.r2_score
加载数据之后,经过预处理、创建新的特征、检查异常值和其他不一致的数据点等过程,完成了机器学习的算法准备。 机器学习通过观测一系列样本,使样本与它们的结果相匹配,从而抽取一系列能够成功泛化到新样本的规则。一种有监督的学习方法。 首先加载一个数据集:
这个方法使用数组x拟合一个模型,以正确预测出向量中十个类别。然后调用.score()
的方法,指定同一个预测器,用向量真值y进行评价模型性能。 这个得分表示的是样本内(in-sample)性能,也是学习算法的性能。
当样本不同时候,验证和测试的结果也会有所不同; 所选择的假设往往是最好的,但并非总是如此; 可行方案:交叉验证。SL:sklearn.cross_validation
交叉验证,主要思想是在于将训练数据分为K组(折)训练模型k次,每次保留一个不同分组的不参与训练。 十折是一个常见的设置。每次模型训练结束以后都会使用剩下的进行训练。 标准差用于均值表示模型总体性能的公正估计。使用不同的模型交叉验证结果的均值。
from sklearn import cross_validation
choosen_random_state=1
cv_folds=10
eval_scoring='accuracy'
workers=-1
x_train,x_test,y_train,y_test=cross_validation.train_test_split(X,y,test_size=0.30,random_state=choosen_random_state)
for hypothesis in [h1,h2,h3]:
scores = cross_validation.cross_val_score(hypothesis,x_train,y_train,cv=cv_folds,scoring=eval_scoring,n_jobs=workers)
print("%s -> cross validation accuracy:mean =%0.3f std=%0.3f"%(hypothesis,np.mean(scores),np.std(scores)))
需要自己建立自己的交叉验证迭代器,cross_validation
提供了一个较好的迭代器选择。 ##### KFold 折数n变量已知,根据训练集的索引进行n次迭代,每次都在剩下都验证集上测试。
采样方法和之前的方法不同,不分割训练集,对训练集进行二次抽样(resample)或(mbootstrap) - 需要去选择一部分可以使用的数据,就需要二次抽样 - 二次抽样可以让你广泛的测试假设而又不用非常小的测试集中验证
机器学习不仅取决于学习算法,还会受到超参数和变量选择的影响。其中超参数是算法事先确定的,无法在训练过程中学习得到。 变量选择能够帮助假设获得最佳的参数。
Series数据是Pandas的核心数据结构之一。
Series 的数据源用列表来填充,两者有相似之处,都是相同的类型,也可以是不同的类型。 series 增加对应的标签(label)作为索引,若没有,就默认是0~n-1内的索引值。
因为这种对应关系,因此对于Series可以使用字典的方式来实现对应的dict的key,series中的value相对应。
Series中的数据是有序的,同时index和value是相互独立的,两者的索引也存在区别,Series和value是可变的。而字典的是不可变的。
一些指标的含义: - count
一列数据的个数 - mean
一列数据的均值 - 25%
:一列数据中前25的分位数
可以通过特定索引值来访问、修改索引位置对应的数值,series对象再本质上就是一个带有Numpy数组,因此Numpy可直接运用于Series中。
堆叠操作:append()
任何NaN(Not a Number)参与的计算,返回的结果依然是NaN。
向量化加法:
会产生一个与原矩阵维度类似的bool矩阵。这个布尔矩阵也可以作为Series对象对应下标,用于获得值为True的位置的对应的数值。从而达到抽取特定样本的目的。
通过索引切片或处理Series中的一个或多个值,返回的结果依然是Series对象。
提取的是第一和第二个元素,第三个元素访问不到。
isnull()
还可以把Series对象作为参数
数据量庞大时候,缺失值可能处于正常数据中,这时候可以用布尔表达式形式,将这些数据筛选出来。
利用Pandas中的drop()
添加元素
若将Series看作Excel的一列,则DataFrame就是一张表
改变index行名,显示指定列名
在pandas,Dataframe可以将列的名称作为DataFrame对象的属性来访问数据。
上述两者是等价的
类似于Series,可以同样使用drop
来删除一行或一列
matpltlib.pyplot.figure
(
num = None, # 设定figure名称。系统默认按数字升序命名的figure_num(透视表输出窗口)e.g. “figure1”。可自行设定figure名称,名称或是INT,或是str类型;
figsize=None, # 设定figure尺寸。系统默认命令是rcParams["figure.fig.size"] = [6.4, 4.8],即figure长宽为6.4 * 4.8;
dpi=None, # 设定figure像素密度。系统默命令是rcParams["sigure.dpi"] = 100;
facecolor=None, # 设定figure背景色。系统默认命令是rcParams["figure.facecolor"] = 'w',即白色white;
edgecolor=None, frameon=True, # 设定要不要绘制轮廓&轮廓颜色。系统默认绘制轮廓,轮廓染色rcParams["figure.edgecolor"]='w',即白色white;
FigureClass=<class 'matplotlib.figure.Figure'>, # 设定使不使用一个figure模板。系统默认不使用;
clear=False, # 设定当同名figure存在时,是否替换它。系统默认False,即不替换。
**kwargs
)
nbsample = 256
xrange = [-math.pi,math.pi]
x ,y = [],[] #create the void list
for i in range(nbsample):
ratio = (i + 0.5)/nbsample
x.append(xrange[0]+(xrange[1]-xrange[0])*ratio)
y.append(math.sin(x[-1])) #反向操作,将列表中的最后一个元素带入函数,再append in y
plt.plot(x,y)
plt.show()
上述做法可以用numpy来得到简化
linspace(linspace(start,stop,num=50))
能够批量生产指定区间内的数量为num的均匀间隔的数组向量。
pyplot
的高级功能import numpy as np
import matplotlib.pyplot as plt
nbsample = 128
x = np.linspace(-np.pi,np.pi,nbsample)
y1 = np.sin(x)
y2 = np.cos(x)
plt.plot(x,y1,color='g',linewidth=4,linestyle='--')
plt.plot(x,y2,markersize=9,markerfacecolor='r',markeredgecolor='k')
plt.title("tangle function plot")
plt.xlabel("x")
plt.ylabel("y")
plt.show()
使用plt.grid()
即可实现。
data = np.arange(0,4,0.2)
plt.plot(data,data,'r-.',data,data**2,'bs',data,data**3,'g^')
plt.grid(b=True)
plt.savefig('mult_lines-grid.png',dpi=600)
/var/folders/sn/g01cvq2j72j6tbq2pmmm074h0000gq/T/ipykernel_44709/2338610709.py:4: MatplotlibDeprecationWarning: The 'b' parameter of grid() has been renamed 'visible' since Matplotlib 3.5; support for the old name will be dropped two minor releases later.
plt.grid(b=True)
实际上有时候需要多个子图,使用subplot()
def f(t):
return np.exp(-t) * np.cos(2 * np.pi * t)
t1 = np.arange(0,5,0.01)
t2 = np.arange(0,5,0.02)
plt.figure(12)
plt.subplot(221)
plt.plot(t1, f(t1), 'bo', t2, f(t2), 'r--')
plt.subplot(222)
plt.plot(t2, np.cos(2 * np.pi * t2), 'r--')
plt.subplot(212)
plt.plot([1, 2, 3, 4], [1, 4, 9, 16])
plt.show()
整个图形按照2*2
进行划分,前两为(2,2,1)
和(2,2,2)
,第三个图直接占据的是第三块和第四块,按照2*1
来划分,因此,前两张图合并为(2,1,1)
后一张为(2,1,2)
num_rows, num_cols = 3, 2
fig, axes = plt.subplots(num_rows, num_cols)
for i in range(num_rows):
for j in range(num_cols):
m, s = uniform(-1, 1), uniform(1, 2)
x = norm.rvs(loc=m, scale=s, size=100)
axes[i, j].hist(x, alpha=0.6, bins=20)
t = f'$\mu = {m:.2}, \quad \sigma = {s:.2}$'
axes[i, j].set(title=t, xticks=[-4, 0, 4], yticks=[])
plt.tight_layout()
plt.show()
其中参数alpha
表示透明度,s就是plot()
中的markersize参数。
matplotlib对三维图形的支持很强大:
np.meshgrid
生成的是网点坐标,也就是将二维的数据传递进去,生成出三维的数据矩阵。
主要使用的函数是plot_surface
,传入参数为x
,y
和一个z=f(x,y)
三个坐标轴。
Seaborn基于Matplotlib的数据可视化库,在Matplotlib的基础上实现了一些好用的功能,在代码形式上会更加像R语言上的ggplot。
This generates a
draw from the distribution with the density function below when a, b = 5, 5
但一些时候我们需要生成的是密度,或者cdf,或分位数等。因此可以使用scipy.stats
来实现
from scipy.stats import beta
import matplotlib.pyplot as plt
%matplotlib inline
q = beta(5, 5) # Beta(a, b), with a = b = 5
obs = q.rvs(2000) # 2000 observations
grid = np.linspace(0.01, 0.99, 100)
fig, ax = plt.subplots()
ax.hist(obs, bins=40, density=True)
ax.plot(grid, q.pdf(grid), 'k-', linewidth=2)
plt.show()
OMP: Info #276: omp_set_nested routine deprecated, please use omp_set_max_active_levels instead.