Numpy:
-
一个强大的N维数组对象
-
支持大量的数据运算
-
集成C/C++和Fortran代码的工具
-
众多机器学习框架的基础库
-
数组内存块风格:内存地址连续的
-
创建array的默认方式是"C-type"以row为主在内存中排列
-
如果是"Fortran"的方式创建的,就是以column为主在内存中排列
-
ndarray:提供了一个N维数组类型ndarray
-
ndarray:shape 数组维度的元组
-
ndarray:flags 有关阵列内存布局的信息
-
ndarray:ndim 数组维度
-
ndarray:size 数组中的元素数量
-
ndarray:itemsize 一个数组元素的长度(字节)
-
ndarray:nbytes 数组元素消耗的总字节数
import numpy as np # 创建一个数组 a = np.array([[1, 2, 3], [4, 5, 6]]) # 数组维度的元组 print(a.shape) (2, 3) 两行三列 # 数组维度 print(a.ndim) 2 # 数组中的元素数量 print(a.size) 6 # 一个数组元素的长度(字节) print(a.itemsize) 4 # 数组元素消耗的总字节数 print(a.nbytes) 24 # 有关阵列内存布局的信息 print(a.flags) C_CONTIGUOUS : True F_CONTIGUOUS : False OWNDATA : True WRITEABLE : True ALIGNED : True WRITEBACKIFCOPY : False
自定义数据结构:
创建数组:
一、创建0和1的数组
a = np.ones([2, 3]) b = np.zeros([2, 3]) print(a) print(b) [[1. 1. 1.] [1. 1. 1.]] [[0. 0. 0.] [0. 0. 0.]]
二、从已有数组中创建
a = np.array([[1, 2, 3], [4, 5, 6]]) arr1 = np.array(a) arr2 = np.asarray(a) arr3 = np.copy(a) a[1]=10 # 不同之处:array和copy是创建了一个新的数组 asarray还是引用原来数组 print(arr1) print(arr2) print(arr3) arr1: [[1 2 3] [4 5 6]] arr2: [[ 1 2 3] [10 10 10]] arr3: [[1 2 3] [4 5 6]]
三、创建固定范围的数组
生成等间隔的序列
1、np.linspace(start,stop,num,endpoint,retstep,dtype)
参数:
-
start 序列的起始值
-
stop 序列的终止值
-
如果endpoint位true,该值包含于序列中
-
num 要生成的等间隔样例数量,默认为50
-
endpoint 序列中是否包含stop值,默认为ture
-
retstep 如果位true,返回样例,以及连续数字之间的步长
-
dtype 输出ndarray的数据类型
a = np.linspace(0,50,10) print(a) [ 0. 5.55555556 11.11111111 16.66666667 22.22222222 27.77777778 33.33333333 38.88888889 44.44444444 50. ]
2、np.arange(start,stop,step,dtype):
a = np.arange(10,40,4) print(a) [10 14 18 22 26 30 34 38]
三、创建随机数组
np.random模块:
均匀分布:
a = np.random.randint(100) b = np.random.uniform(0,10) print(a) print(b) 0 8.832109237704984
正态分布:
np.random.normal(1.75,0.1,[10,10])
-
生成10行10列100个身高的数据
案例:股票数据的形状、类型、转换
resize()和reshape:
-
当目标维度元素个数与原数组元素个数不同时np.reshape() 将报错
-
而 np.resize() 将采取 少补多删 的方式处理
import numpy as np # 生成一个符合正态分布的500只股票的涨跌幅数据 stock = np.random.normal(0, 1, [500, 504]) # 我们要获取第0只股票,前100天的涨跌幅数据 print(stock[0, 0:100]) # 修改数组的形状类型 # 从行:500 列504 ----> 行:504 列:500 # 使用reshape:返回一个具有相同数据域,但shape不一样的视图 # 在转换形状的时候,一定要注意数组的元素匹配 print(stock.reshape([504, 500]).shape) # resize:在转换形状的时候,一定要注意数组的元素匹配 print(stock.resize(504, 500))
转换数据类型:astype(类型)
import numpy as np # 生成一个符合正态分布的500只股票的涨跌幅数据 stock = np.random.normal(0, 1, [500, 504]) stock.astype(int)
修改小数点后面的位数:np.round(值,修改位数)
import numpy as np # 生成一个符合正态分布的500只股票的涨跌幅数据 stock = np.random.normal(0, 1, [500, 504]) np.round(stock[0,:100],2)
转置:行列互换 .T
import numpy as np # 生成一个符合正态分布的500只股票的涨跌幅数据 stock = np.random.normal(0, 1, [500, 504]) print(stock.shape) print(stock.T.shape) (500, 504) (504, 500)
转换:tostring() 序列化
import numpy as np arr = np.array([[[1, 2, 3], [4, 5, 6]], [[11, 12, 13], [14, 15, 16]]]) print(arr.tostring()) b'\x01\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00\x04\x00\x00\x00\x05\x00\x00\x00\x06\x00\x00\x00\x0b\x00\x00\x00\x0c\x00\x00\x00\r\x00\x00\x00\x0e\x00\x00\x00\x0f\x00\x00\x00\x10\x00\x00\x00'
简单的逻辑运算:
import numpy as np # 生成一个符合正态分布的500只股票的涨跌幅数据 stock = np.random.normal(0, 1, [500, 504]) temp = stock[:4,:4].copy() print(temp > 0.5) print(temp[temp > 0.5]) [[False False False True] [False False False False] [False True False False] [ True False False False]] [0.73914023 1.23799847 1.42735964]
通用判断函数:
-
np.all()
# 判断stock[0:2,0:5]是否全是上涨的 print(stock[0:3,0:5]) print(np.all(stock[0:2,0:5] > 0)) [[-0.87685738 1.92558403 -0.10842305 -0.86078552 -0.92806403] [ 0.01510393 -0.07691521 0.19561266 -1.33255131 -1.50942188] [ 0.56063758 1.57986586 -1.45216582 0.34000793 -1.2579828 ]] False
-
np.unique():返回新的数组的数值,不存在重复的值
# 将序列中数值值唯一且不重复的值组成新的序列 stock = np.random.normal(0, 1, [500, 504]) change_int = stock[0:3,0:5].astype(int) result = np.unique(change_int) print(change_int) print(result) [[ 2 -1 0 0 0] [ 0 -1 -1 1 -1] [-1 0 1 0 0]] [-1 0 1 2]
-
np.where(三元运算符)
三个参数: (条件,条件成立返回值,条件不成立返回值) # 需求: 对于>0.5 的置为1, else 0 stock = np.random.normal(0, 1, [500, 504]) temp = stock[0:3, 0:5] print(temp) temp1 = np.where(temp > 0.5, 1, 0) print(temp1) [[-0.71346351 0.80456787 0.03005379 0.14350053 0.61954292] [ 0.18756663 -1.29583813 -0.72069357 -0.10330995 -0.21107361] [ 0.59349295 0.22583558 0.78439801 0.93988581 1.4372567 ]] [[0 1 0 0 1] [0 0 0 0 0] [1 0 1 1 1]]
-
np.logical_and
# 需求: 对于>0.5 && <1 的置为1, else 0 stock = np.random.normal(0, 1, [500, 504]) temp = stock[0:3, 0:5] print(temp) temp1 = np.where(np.logical_and(temp > 0.5, temp < 1),1,0) print(temp1) [[-2.14001099 -0.94761009 0.4465462 1.1186463 -0.50115999] [-0.94054136 1.18197315 -0.83032055 -1.35076866 0.88349663] [ 0.37756843 0.00239822 0.12336254 0.1942239 1.01316616]] [[0 0 0 0 0] [0 0 0 0 1] [0 0 0 0 0]]
-
np.logical_or
# 需求: 对于>0.5 or <1 的置为1, else 0 temp = stock[0:3, 0:5] print(temp) temp1 = np.where(np.logical_or(temp > 0.5, temp < 1),1,0) print(temp1) [[-0.60282601 -1.59385328 -0.86680265 1.81152559 -0.55647258] [-0.53471974 0.23374759 0.36690366 -0.69678245 -0.07006649] [-0.44544056 1.43499097 0.30233797 0.40960102 0.54485194] [[1 1 1 1 1] [1 1 1 1 1] [1 1 1 1 1]]
统计运算:
-
np.argmax()、np.argmin()相当于求下标
-
其他的相当于求具体的值
-
统计指标
-
参数:axis:0 对列统计运算 axis:1 对行进行统计运算
-
np.min()
print("这三只股票4天的涨跌幅最小的值{}".format(np.min(temp,axis=1))) 这三只股票4天的涨跌幅最小的值[-1.21836378 -0.86081319 -0.43444155]
-
-
np.max()
# 统计运算 temp = stock[:3, 0:4] print(temp) # 统计每只股票涨跌幅最大是多少 # axis:0 对列统计运算;axis:1 对行进行统计运算 print("这三只股票4天的涨跌幅最大的值{}".format(np.max(temp,axis=1))) [[ 0.5893032 -2.27991744 -0.32691572 1.41229824] [ 0.94382943 -0.91008627 1.80263061 0.86829858] [-0.94808003 -0.84025863 0.50283639 -0.49922297]] 这三只股票4天的涨跌幅最大的值[1.41229824 1.80263061 0.50283639]
-
np.median()中位数
-
np.mean() 平均值
print("这三只股票4天的涨跌幅的平均值{}".format(np.mean(temp,axis=1))) 这三只股票4天的涨跌幅的平均值[-0.26503973 -0.01880806 0.11086508]
-
np.std() 标准差
print("这三只股票4天的涨跌幅的标准差{}".format(np.std(temp,axis=1))) 这三只股票4天的涨跌幅波动情况[0.92384241 0.58773511 0.38445726]
-
np.var() 方差
print("这三只股票4天的涨跌幅波动情况{}".format(np.var(temp,axis=1))) 这三只股票4天的涨跌幅波动情况[0.78035077 0.60654875 0.69766121] ## 第一个股票不稳定,涨跌幅度太大
-
np.argmax()统计股票在某个交易日的涨跌幅最大
# 统计temp,三只股票在4天内的涨跌幅最大实在哪一天 print("这三只股票在4天内的涨跌幅最大{}".format(np.argmax(temp, axis=1))) 这三只股票在4天内的涨跌幅最大[0 2 3]
-
np.argmin()统计股票在某个交易日的涨跌幅最小
# 统计temp,三只股票在4天内的涨跌幅最大实在哪一天 print("这三只股票在4天内的涨跌幅最小{}".format(np.argmin(temp, axis=1))) [[ 1.13724698 -1.37237356 0.1180424 -0.65923202] [-0.42132476 -2.00802803 -0.80681212 -0.6026671 ] [-0.77886677 -0.4623484 0.79525948 0.70778204]] 这三只股票在4天内的涨跌幅最小[1 1 0]
数组间运算:
-
广播机制:(不包括矩阵)
-
当操作两个数组时,numpy会逐个比较它们的shape(构成的元组tuple)只有在以下情况才能进行数组与数组运算
-
维度相等
-
shape(其中相对应的一个地方为1)
-
-
-
数组跟数
# 数组跟数之间的运算 arr = np.array([1, 2, 3, 4]) print(arr) print(arr + 1) print(arr * 2)
-
数组跟数组(用的少)
# 数组跟数组之间的运算 arr1 = np.array([[4, 5, 6], [7, 8, 9]]) print(arr1) arr2 = np.array([[2], [2]]) print(arr2) # arr1 [2,3] arr2 [2,1] print(arr1*arr2)
对比:数组跟数组不管形状怎么变,运算机制已经固定
-
矩阵运算(经常用到的规则)
-
矩阵:就是一种特殊的二维数组
-
np.mat() 将数组转化成矩阵类型
-
np.matmul() 可以直接使用一个乘法运算的API
# 得出学生综合成绩 score = np.array([ [82, 80], [85, 78], [90, 90], [86, 82], [82, 90], [78, 80], [92, 94], [89, 98], ]) print(np.shape(score)) print(np.ndim(score)) percent = np.array([[0.3], [0.7]]) print(np.shape(percent)) print(np.ndim(percent)) # score:(8,2)*(2,1) = (8,1) c = np.matmul(score,percent) print(c) (8, 2) 2 (2, 1) 2 [[80.6] [80.1] [90. ] [83.2] [87.6] [79.4] [93.4] [95.3]]
-
数组的合并、分割:
-
np.cincatenate() 拼接合并
-
asxis = 1时,按照数组的列方向拼接 =np.hstack()
-
asxis = 1时,按照数组的行方向拼接 =np.vstack()
# 生成一个符合正态分布的500只股票的涨跌幅数据 stock = np.random.normal(0, 1, [500, 504]) stock1 = stock[:4, :5] stock2 = stock[4:8, :5] # 合并这stock1、stock2股票 stock3 = np.concatenate([stock1,stock2],axis=0) print(stock3.shape) print(stock3) (8, 5) [[-0.37079453 -1.36684583 -0.74973306 -1.22750429 -0.57475169] [ 0.31685205 -0.48011441 -0.29007355 0.43182973 0.92383138] [ 0.20552045 0.49629362 0.75029666 -0.03843972 -1.13278245] [ 1.21165203 -1.40459186 -0.29336346 0.01072095 0.01493661] [ 2.72885017 0.66701633 0.7717624 1.82754318 -0.1924973 ] [-0.5209661 -2.32455596 0.08510609 1.40410741 0.4536378 ] [ 0.89386792 0.37598941 0.03851727 -0.16879376 1.56965195] [ 0.21368796 -1.47766949 -1.91768293 -1.2893965 1.93745139]]
-
-
np.split() 分割
numpy的IO操作与数据处理:
-
np.genfromtxt() 读取数据
test = np.genfromtxt('data/departments.csv',delimiter=',') print(test)
-
np.nan类型:float
将csv文件转为数组:
data = np.loadtxt('data/data.csv', dtype='int', delimiter=',') print(data) # 取出一个数字 print(data[1, 1]) # 取出整行或整列 print(data[1]) # 行 print(data[:, 1]) # 列 # 取多列 print(data[:,[1,2]])
Pandas介绍:
-
以Numpy为基础,借力Numpy模块在计算方面性能高的优势
-
基于matplotlob,能够简便的画图
-
独特的数据结构
三大结构:
-
Dataframe(二维数据)
-
功能:行索引(Index--axis=0)列索引(columns--axis=1)
-
删除列:
data = pd.read_csv("data_Stock.csv") # print(data.head()) DF = pd.DataFrame(data) Data = DF.drop(labels=['年初至今','市盈(TTM)','换手率','市值'], axis=1) print(Data)
-
修改索引必须整体全部修改
-
重设索引:
-
以某列值设置成新的索引,可设置多重索引,从而变成多维索引
# 以month列为新的索引 print(data_Frame.set_index(['month']))
reset_index() 将原来的索引删除或者变成一列值,添加新的按照下表数字的索引
# drop=True丢弃原来的索引值 drop=False 变成一列值,添加新的索引 print(data_Frame.reset_index(drop=True)) print(data_Frame.reset_index(drop=False)) 0 1 2 3 0 0.421621 1.101260 -2.733399 -0.176862 1 0.840477 0.020553 -0.707415 0.169302 index 2023-01-02 00:00:00 ... 2023-01-04 00:00:00 2023-01-05 00:00:00 0 股票0 0.421621 ... -2.733399 -0.176862 1 股票1 0.840477 ... -0.707415
-
-
属性:
-
shape(行列数)
-
dtypes
-
ndim(维度)
print(data_Frame.ndim) 2
-
index
print(data_Frame.index) Index(['股票0', '股票1'], dtype='object')
-
columns
print(data_Frame.columns) DatetimeIndex(['2023-01-02', '2023-01-03', '2023-01-04', '2023-01-05'], dtype='datetime64[ns]', freq='B') 2
-
values
# 通过获取values直接获取 array的值,不包含索引 print(data_Frame.values) [[-0.80572203 0.96758639 -0.70194211 -0.01177345] [-1.02677215 -1.18259704 -0.53599869 -1.16009042]]
-
T(行列互换)
print(data_Frame.T)
-
head、tail
# 通过整体查询参数,简单查看数据大体结构参数为前x行 print(data_Frame.head(100)) # 后x行 print(data_Frame.tail(100))
-
import pandas as pd import numpy as np # 平均值、标准差 stock = np.random.normal(0, 1, [500, 504]) stock_data = stock[:2, :4] # 将数据变成DataFrame结构 data_Frame = pd.DataFrame(stock_data) print(data_Frame) # 查看行(0) 列(1) # print(stock.shape[1]) # 构造索引值列表 stock_code = ["股票" + str(i) for i in range(stock_data.shape[0])] # 添加行索引 pd.DataFrame(stock_data, index=stock_code) # 添加列索引,时间 data_range创建时间数据列表,freq='B'略过周末非交易日 columns_data = pd.date_range('2023-01-01', periods=stock_data.shape[1], freq='B') data_Frame = pd.DataFrame(stock_data,index=stock_code,columns=columns_data) print(data_Frame) 0 1 2 3 0 -0.002404 1.057367 -1.919406 1.442203 1 -1.647936 -0.098910 -0.982797 2.165306 2023-01-02 2023-01-03 2023-01-04 2023-01-05 股票0 -0.002404 1.057367 -1.919406 1.442203 股票1 -1.647936 -0.098910 -0.982797 2.165306
-
Series(一维数据,只有行index)
-
通过已有数据创建
-
指定内容,默认索引
pd.Series(np.arange(10))
-
指定索引
pd.Series([6,7,8,9],index=)
-
通过字典数据创建
pd.Series({'red':100,'blue':200})
-
基本数据操作:
# 读取数据 data = pd.read_csv('./data/data_01.csv')
关于切片:
# numpy数组支持两个一起切片 stock_data = stock[:6, :5] # pandas必须使用iloc stock_data = stock.iloc[0:3,:2]
前续代码:
import pandas as pd import numpy as np # 平均值、标准差 stock = np.random.normal(0, 1, [500, 504]) stock_data = stock[:6, :5] # 将数据变成DataFrame结构 data_Frame = pd.DataFrame(stock_data) # 构造索引值列表 stock_code = ["股票" + str(i) for i in range(stock_data.shape[0])] # 添加行索引 pd.DataFrame(stock_data, index=stock_code) # 添加列索引,时间 data_range创建时间数据列表,freq='B'略过周末非交易日 columns_data = pd.date_range('2023-01-01', periods=stock_data.shape[1], freq='B') data_Frame = pd.DataFrame(stock_data,index=stock_code,columns=columns_data) Data = data_Frame.T print(Data)
索引操作:
-
直接使用行列索引名字(先列后行)
# 通过索引获取两列、三列 print(Data[['股票0','股票1']]) print(Data[['股票0','股票1','股票3']]) # 先列后行 print(Data['股票0']['2023-01-03'])
-
通过loc和iloc获取数据
-
loc只能指定行列索引的名字获取
# 通过loc获取数据 可以先行后列 print(Data.loc['2023-01-03':'2023-01-05']) print(Data.loc['2023-01-03':'2023-01-05',['股票0','股票3']]) 股票0 股票1 股票2 股票3 股票4 股票5 2023-01-03 -0.668438 -0.985700 -1.151966 -0.809750 0.559733 -0.003048 2023-01-04 -0.612064 0.551887 0.145475 0.305388 0.232861 -1.557081 2023-01-05 0.549580 0.385421 -1.059424 -1.278689 -0.763383 -0.558839 股票0 股票3 2023-01-03 -0.668438 -0.809750 2023-01-04 -0.612064 0.305388 2023-01-05 0.549580 -1.278689
-
iloc可以通过索引的下标去获取
#通过iloc获取数据 print(Data.iloc[0:3,:2]) 股票0 股票1 2023-01-02 -0.395320 1.532603 2023-01-03 1.407965 -0.444833 2023-01-04 -1.088129 1.601823
-
-
使用ix组合索引(不建议使用,有点老了)
# 使用组合索引获取数据 print(Data.ix[0:4, ['股票0', '股票1','股票2', '股票3']])
修改内容:
# 对内容进行修改 Data.loc[['2023-01-02','2023-01-03'],'股票4']=200 Data.iloc[:2,:2] = 100 print(Data) Data['股票2'] = 999 print(Data) Data.股票0 = 1 print(Data)
排序:
-
对于索引进行排序
-
使用.sort_index给索引进行排序
# 对索引排序 Data.sort_index(axis=1,level=False) print(Data)
-
-
对于内容进行排序
-
使用df.sort_value(默认小-->大)
# 对内容进行排序 a=Data.sort_values(by='股票0',ascending=True) print(a) # 当股票1 出现相等时,则接着按照股票2大小排序 b=Data.sort_values(by=['股票0','股票1'],ascending=True) print(b)
-
统计分析:.describe()
print(Data.describe()) 把所有指标都进行了计算
pandas中求最大值最小值:
# 对某个指标求最大值 0:对列求最大值 1:对行求最大值 print(Data['股票0'].max(0)) print(Data['2023-01-04'].max(1)) # 对所有列求最大值 print(Data.max(0)) # 对所有行求最大值 print(Data.max(1))
累计统计分析函数:
-
cumsum()累计求涨跌幅
import pandas as pd import numpy as np import matplotlib.pyplot as plt # 累计求涨跌幅,先排序 Data.sort_values(by='股票0',ascending=True) # 画出涨跌幅图 print(Data['股票0'].cumsum().plot()) plt.show()
逻辑运算:
-
通过query查询:
# 通过query查询 print(Data.query("股票1>0.6 & 股票2 > 0.3"))
-
isin:判断某个值是否存在
# isin:判断值 返回:True or False print(Data["股票1"].isin(['1.5'])) # 输出值 print(Data[Data["股票1"].isin(['1.5'])])
-
apply:自定义运算函数
# 自定义运算函数 Data_lbd = Data[['股票0', '股票1']].apply(lambda x: x.max() - x.min(), axis=0) print(Data_lbd)
文件读取与存储:
优先选择使用hdf文件存储
-
hdf在存储是支持压缩,使用的方式是blosc,这个速度最快,也是pandas默认支持的
-
使用压缩可以提高磁盘利用率,节省空间
-
hdf还是跨平台的,可以轻松迁移到hadoop上面
文件读取与存储:
-
pd.read_csv()
-
nrows: int 读取的行数
-
header: 指定第几行作为列名(忽略注解行),如果没有指定列名,默认header=0; 如果指定了列名header=None
-
sep: 指定分割符,默认是’,’C引擎不能自动检测分隔符,但Python解析引擎可以
-
names 指定列名,如果文件中不包含header的行,应该显性表示header=None
-
dtype: E.g. {‘a’: np.float64, ‘b’: np.int32} 指定数据类型
-
# 文件的读取和存储 # 指定usecols 来读取部分数据,其他不用到的就不需要读取了 Data_read = pd.read_csv("./data/data_02.csv", usecols=['open']) print(Data_read)
-
.to_csv()
-
参数:
-
sep:指定分隔符,默认是逗号。
-
mode:'a' 追加方式
-
header:是否写入标题行,默认True,写入。
-
na_rep:空值如何表示,默认是’’。
-
index:是否写入行索引,默认True,写入。
-
index_label:行索引的名称,默认是None。
-
columns:写入哪些列,默认全部列。
-
# mode:'a' 追加方式 # header=False 追加后去掉索引 Data_read.to_csv("./data/data_03.csv", columns=['open', 'close'], index=False,mode='a',header=False) print(pd.read_csv("./data/data_03.csv"))
-
read_hdf():
-
一个h5文件可以放入多个键值"key:"来保存三维结构
# 读取h5文件 Data_read = pd.read_hdf("/data/data_02.h5") # 保存 key参数随便填一个 Data_read.to_hdf("./data/data_03.csv",key="data")
pandas中缺失值的处理:
-
检测重复值:
data.duplicated() #返回布尔型数据,告诉重复值的位置
data.duplicated().sum() #说明有n个重复值
打印非重复值
data[data.duplicated()==False]#打印重复值
删除重复记录(drop_duplicates())
#inplace=True表示直接在源数据上进行操作 data.drop_duplicates(inplace=True)
-
[pd.to_numeric(arg, errors=‘raise’, downcast=None) [source]
作用:将参数转换为数字类型。
默认返回dtype为float64或int64, 具体取决于提供的数据。使用downcast参数获取其他dtype。
errors中参数的解释
'raise’参数:无效的解析将引发异常
'corece’参数:将无效解析设置为NaN
‘ignore’参数:**无效的解析将返回输入
downcast中参数的意义
默认的None就是不进行处理
‘integer’和’signed’:最小的有符号整数dtype(最小值np.int8)
‘unsigned’:最小的unsigned int dtype(np.uint8)
‘float’:最小的float dtype(np.float32)
返回值:如果解析成功,则为数字。其中返回类型取决于输入。如果为Series,则为Series,否则为ndarray。
-
删除
# pandas的缺失值处理 data = pd.read_csv('data/products.csv') print(data) # 如果有缺失值并且类型是np.nan--->按照所在行去删除 print(data.dropna()) print(data.shape)
-
填充(平均值或者中位数)
-
fillna()的作用是填充缺失值
-
DataFrame.fillna(value=None, method=None, axis=None, inplace=False, limit=None, downcast=None)
-
参数:
-
value:设置用于填充DataFrame的值
-
method:默认为None;设置填充DataFrame的方法有:‘backfill’, ‘bfill’, - ‘pad’, ‘ffill’四种,其中‘backfill’和 ‘bfill’是用前面的值填充空缺值,‘pad’和 ‘ffill’是用后面的值填充空缺值
-
axis:填充缺失值所沿的轴,与上文的axis设置方法一样
-
inplace:是否替换原DataFrame,与上文的设置方法一样
-
limit:设置被替换值的数量限制
-
downcast:表示向下兼容转换类型,不常用
-
# 替换缺失值--->按照所在列去填充 data = data['列名'].fillna(data['填充列名'].mean(),inplace=True) print(data)
-
如果有缺失值,类型不是默认的np.nan
# 替换缺失值--->类型不是默认的np.nan,先替换 data = data.replace(to_replace="?",value=np.nan) data = data.dropna() print(data)
高级处理-数据离散化:
-
连续的属性值域上
-
值域划分为若干离散区间
-
符号、整数值代表落在每个子区间中的属性值
离散化找到异常点:借助分组找到异常点:
-
自动分组和手动分组
-
qcut()
-
cut()
-
import pandas as pd import numpy as np import matplotlib.pyplot as plt import matplotlib font = { 'family': 'SimHei', 'weight': 'bold', 'size': 12 } matplotlib.rc("font", **font) data = pd.read_csv("data_Stock.csv") # print(data.head()) DF = pd.DataFrame(data) Data = DF.drop(labels=['年初至今', '市盈(TTM)', '换手率', '市值'], axis=1) print(Data) # Data = Data.sort_index() # print(Data) zdf = Data['涨跌额'].hist(bins=80) plt.show() # 自动分组 group = pd.qcut(np.abs(Data['涨跌额']), 10) print(group.value_counts()) # 可以得出 > 1.906的涨跌幅说明这个股票异常 # 手动分组 bins = [-100, -7, -5, -3, 0, 3, 5, 7, 100] group = pd.cut(np.abs(Data['涨跌额']), bins) print(group.value_counts()) # 手动分组数据 (0, 3] 249 (3, 5] 12 (7, 100] 5 (-3, 0] 2 (5, 7] 2 (-100, -7] 0 (-7, -5] 0 (-5, -3] 0 Name: 涨跌额, dtype: int64
-
离散化后生成哑变量矩阵:
-
get_dummies(,prefix="行索引命名")
# 生成哑变量矩阵 print(pd.get_dummies(Data['涨跌额'],prefix='stock_rise'))
高级处理-合并:
-
交叉表与透视表:
#该股票所在星期几 week = pd.to_datetime(Data.index).weekday
运用交叉表:
-
data.crosstab(data['week'],data['gailu'])
-
交叉表用于计算一列数据对于另外一列数据的分组个数(寻找两列之间的关系)
画出嵌入柱状图:
-
data.plot(,stacked=Ture)
透视表:
-
data.pivot_table([],index=[])
-
透视表:实现计算一列数据对于另一列数据比例(比交叉表要方便)
分组与聚合:
-
as_index参数:指定不去改变原来的数据结构 按照颜色分组 统计price1的平均价格
-
data.groupby(['color'],as_index=False)['price1'].mean()
groupby统计每个国家多少家店:
pandas:时间序列分析:
datetime():
# 传入一个时间点,pandas会自动解析成时间 a = pd.to_datetime('01.05.2011') print(a) # 传入一个时间列表 b = pd.to_datetime(['2022-01-05','2022-01-06','2022-01-07','2022-01-08']) print(b) 2011-01-05 00:00:00 DatetimeIndex(['2022-01-05', '2022-01-06', '2022-01-07', '2022-01-08'], dtype='datetime64[ns]', freq=None)
-
DatetimeIndex:pandas基本的时间序列类型(多个时间点)
-
当时间序列出现缺失值后,pandas to_datetime 转成NaT类型
-
dtype='datetime64[ns]'是numpy中的时间类型
import pandas as pd # 传入一个时间点,pandas会自动解析成时间 a = pd.to_datetime('01.05.2011') print(a) # 传入一个时间列表 b = pd.to_datetime(['2022-01-05','2022-01-06','2022-01-07','2022-01-08']) print(b) print(type(b.values))
生成一个Series的时间序列结构:
data = pd.DatetimeIndex(['2022-01-05','2022-01-06','2022-01-07','2022-01-08']) # 生成一个Series的时间序列结构 ser = pd.Series(3.0,index=data) print(ser) print(data.year) print(data.weekday) print(data.hour)
时间的偏移:
-
导入接口:(可以进行时间的相加减)
from pandas.tseries.offsets import Hour,Minute,Day,MonthEnd
# 对一个实现序列结构相加 a = Hour(1) + Minute(30) print(a) b = Day(1) + Hour(10) print(b) <90 * Minutes> <34 * Hours>
进行DatetimeIndex的时间类型整体偏移:
data = pd.DatetimeIndex(['2022-01-05','2022-01-06','2022-01-07','2022-01-08']) # n:表示大小,freq:单位:时分秒,年月日 c = data.shift(1,freq='D') print(c) DatetimeIndex(['2022-01-06', '2022-01-07', '2022-01-08', '2022-01-09'], dtype='datetime64[ns]', freq=None) d = data.shift(2,freq='2D') #偏移两个两天 print(d) DatetimeIndex(['2022-01-09', '2022-01-10', '2022-01-11', '2022-01-12'], dtype='datetime64[ns]', freq=None)
Pandas生成指定频率的时间序列:
-
pandas.date_range()
-
star:开始时间
-
end:结束时间
-
perids:产生多长的序列
-
freq:频率 D,H,Q,B(每工作日),M(每月最后一天),BM(每月最后一个工作日)
-
tz:时区
pd.Date_range()生成一个不同频率的时间序列:
-
可以按照多少分钟、多少小时、多少天生成,也可以组合
生成从2020-01-01到2020-04-02时间序列,频率为'D' a = pd.date_range('2020-01-01','2020-04-02',freq='2D') print(a) DatetimeIndex(['2020-01-01', '2020-01-03', '2020-01-05', '2020-01-07'........])
-
生成从2020-01-01到 ? 时间序列
# 生成从2020-01-01到 ? 时间序列,指定生成多长的时间序列,可以指定频率 b = pd.date_range('2020-01-01',periods=10,freq='1H30Min') print(b) DatetimeIndex(['2020-01-01 00:00:00', '2020-01-01 01:30:00'........ '2020-01-01 03:00:00', '2020-01-01 13:30:00'], dtype='datetime64[ns]', freq='90T')
确定性变化分析:
-
移动平均法
-
移动方差和标准差、移动相关系数
移动窗口:移动的单位,按照数据的频率
移动平均线分类:
-
按照计算周期:分为短期、中期、长期
-
按照计算方法:算数、加权法、指数移动平均线
简单移动平均线(SMA):
-
pd.rolling_mean(data,window='计算周期')
-
移动平均线周期越长、曲线越平滑,整体趋势越延迟靠后
-
SMA = (C1+C2+C3+C4+...+Cn)/n
-
C1:第一日收盘价 Cn:最近收盘价 n:移动平均数周期
加权移动平均线(WMA):
-
它的比重以平均线的长度设定,越近期的收市价,对市况影响越重要
-
作用:为了提高最近股票(收盘价)数据的影响
-
末日加权移动平均线:
-
线性加权移动平均线:
-
给的权重比率过大,对时间序列数据影响过大
-
指数平滑移动平均线(EWMA):
-
pd.ewma(com=None,span=one)
-
com:指数平均线 span:时间间隔
-
提高最近的数据的比重,不存在比重过大
-
比重都是一个小数,所有天数的比重加起来为1
投资的两种方法:
技术分析:
技术分析是指研究过去金融市场的资讯来预测价格的趋势与决定投资的策略。技术分析师相信有所谓的价格趋势,K线图、移动平均线以及技术指标应用于股票或者期货投资当中。
-
趋势追踪:
-
技术指标:
-
MACD
-
RSI
-
BOLL
-
-
双均线策略:
-
MACD:
-
用于研判股票价格变化的强度、方向、能量,以及趋势周期,以便把握买进和卖出的时期。
-
基本面分析:
着重于对影响证券价格及其走势的各项因素的分析,宏观数据、市场行为、企业财务数据、交易数据等进行分析,主要是利用数学、统计技术、机器学习技术获得投资机会。
算法:
数据集的划分:
机器学习的数据集会划分为两个部分:
-
训练数据:用于训练、构建模型
-
测试数据:在模型检验时使用,用于评估模型是否有效
-
划分比例:
-
训练集:70% 80% 75%
-
测试集:30% 20% 30%
-
Sklearn数据集介绍:
API
from sklearn.datasets import load_iris, load_boston, fetch_20newsgroups
分类数据集:鸢尾花数据集
lr = load_iris() print("特征值:", lr.data) print("目标值:", lr.target) print(lr.DESCR) print(lr.feature_names) print(lr.target_names)
回归数据集:波斯顿房价数据集
lb = load_boston() print("特征值:", lr.data) print("目标值:", lr.target)
数据量比较大的数据集
news = fetch_20newsgroups(subset='all') print(news.data) print(news.targrt)
数据集划分:
# 进行数据集的训练集和测试集划分 # test_size测试集的大小,一般为float # 返回值有4个部分接收 x:特征值,y:目标值,train:训练集,text:测试集 # x_train,x_text,y_train,y_text lr = load_iris() x_train, x_text, y_train, y_text = train_test_split(lr.data, lr.target, test_size=0.4) print("训练集特征值:", x_train) print("测试集特征值:", x_text) print("训练集目标值:", y_train) print("测试集目标值:", y_text)
转换器与估值器:
转换器:特征工程接口称之为转换器,其中转换器调用有这么几种形式
-
fit_transform,transform,fit
sklearn.preprocessing import StandardScaler
-
fit_transform = fit + transform
-
fit_transform(a) :标准化,以自己a的平均值标准差转换b
-
fit(a):计算a的平均值和标准差,transform(b):以a的平均值和标准差去转化b
-
适用于特征选择、主成分分析、特征抽取
估计器:是一类实现了算法的API
-
fit():训练集训练
-
测试集预测:predict,score
K-近邻算法(KNN)
定义:如果一个样本在特征空间中的K个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别。
import pandas as pd from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier from sklearn.preprocessing import StandardScaler def knncls(): # data_test = pd.read_csv("../data/test.csv", nrows=1000) data_train = pd.read_csv("../data/train.csv",nrows=100000) # 缩小数据范围 data_train = data_train.query("x>1.0 & x<1.25 & y>2.5 & y<2.75") # 分割数据集到训练集和测试集 # 取出特征值x和目标值y y = data_train[['place_id']] x = data_train[['x', 'y', 'accuracy', 'time']] x_trian, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3) # 进行数据的标准化处理 std = StandardScaler() # 对训练集的特征值做标准化处理 x_trian = std.fit_transform(x_trian) # 对测试集的特征值做标准化处理 x_test = std.fit_transform(x_test) # 利用k近邻算法去进行训练预测 knn = KNeighborsClassifier(n_neighbors=1) # 调用fit和predocthuozhe score knn.fit(x_trian, y_train) # 预测测试集的目标值(办的业务类型) y_predict = knn.predict(x_test) print("k近邻算法预测的这些事件的业务类型:", y_predict) print("k近邻预测的准确率:", knn.score(x_test, y_test)) return None if __name__ == '__main__': knncls()
准确率:
-
K值取很小:容易受到异常点的影响
-
K值取很大:收到样本均衡的问题
模型选择与调优:
-
交叉验证:为了让被评估的模型更加准确可信
-
将训练集分成:训练集+验证集 通常采取10折交叉验证
-
超参数:有很多参数是需要手动指定的(如K近邻算法中的k值),这种就叫超参数
应用网格搜索+交叉验证对k近邻进行调优 knn = KNeighborsClassifier() # 构造超参数的字典 对于knn来讲,数据量比较大,k个数 = 根号(样本数) param = {"n_neighbors":[1, 3, 5, 7, 10]} # 为了看到效果不多,cv=2,但是通常会选择10 gc = GridSearchCV(knn, param_grid=param, cv=2) # fit输入数据 gc.fit(x_trian, y_train) # 查看模型超参数调优的过程,交叉验证的结果 print("在2折交叉验证当中额最好结果:", gc.best_score_) print("选择的最好的模型参数是:", gc.best_estimator_) print("每次交叉验证的验证机表现结果(准确率):", gc.cv_results_) # 预测测试模型的准确率 print("在测试集当中的最终预测结果为:", gc.score(x_test, y_test))
机器学习算法类别分类:
-
监督学习:(supervised learning)
-
定义:输入数据是由输入特征值和目标值所组成。函数的输出可以是一个连续的值(称为回归),或是输出有限个离散值(称作分类)
-
分类:k近邻、贝叶斯、决策树与随机森林、逻辑回归、神经网络
-
回归:线性回归、岭回归
-
-
无监督学习:(unsupervised learning)
-
定义:输入数据是由特征值所组成
-
聚类 k-means
-
区别:
监督学习————>有特征值和标签(目标值),有标准答案匹配
无监督学习————>只有特征值,没有目标值
两种数据类型:
-
离散型数据:(分类的目标值是离散型)
由记录不同类别个体的数目所得到的数据,又称计数数据,所有这些数据全部都是整数,而且不能再细分,也布恩那个进一步提高他们的精确度。
-
连续性数据:(回归的目标值是连续性)
变量可以在某个范围内取任意数,即变量的取值可以是连续的,如:长度、时间、质量值等,这类整数通常是非整数,含有小数部分。
朴素贝叶斯算法:
常用于文本分类
公式:
-
成立条件:特征之间相互独立
-
联合概率:
包含多个条件,且所有条件同时成立的概率
-
记作:P(A,B)
-
特性:P(A,B) = P(A)P(B)
-
-
条件概率:
就是事件A在另外一个事件B已经发生条件下的发生概率
-
记作:P(A|B)
-
特性:P(A1,A2|B) = P(A1,B)P(A2|B)
-
贝叶斯公式:
公式分为三个部分:
-
P(C):每个文档类别的概率(某文档类别数/总文档数量)
-
P(W|C)给定类别下特征(被预测文档中出现的词)的概率
-
计算方法:P(F1 | C ) = Ni / N (训练文档中去计算)
-
Ni为F1词在C类别所有文档中出现的次数
-
N为所属类别C下的文档所有词出现的次数和
-
-
P(F1,F2…)预测文档中每个词的概率
拉普拉斯平滑系数:
目的:为了防止计算出的分类概率为0
简单应用:
API:
sklearn.raive_bayes.MultinomialNB(alpha = 1.0)
-
朴素贝叶斯分类
-
alpha:拉普拉斯平滑系数
案例:20个新闻组
from sklearn.datasets import fetch_20newsgroups from sklearn.model_selection import train_test_split from sklearn.feature_extraction.text import TfidfVectorizer from sklearn.naive_bayes import MultinomialNB def multinormalcls(): """ 朴素贝叶斯对20类新闻进行分类 特征值就是一片一片文章 :return: """ news = fetch_20newsgroups(subset='all') # 1、 分割数据集 x_train, x_test, y_train, y_test = train_test_split(news.data, news.target, test_size=0.3) # 2、 进行文本特征抽取(算法能够知道特征值) tfidf = TfidfVectorizer() # 对特征训练集进行特征抽取 x_train = tfidf.fit_transform(x_train) # print(x_train.toarray()) # 对测试集的特征值进行抽取 x_test = tfidf.transform(x_test) # 进行朴素贝叶斯 mlb = MultinomialNB(alpha=1.0) mlb.fit(x_train, y_train) # 预测,准确率 print("预测测试集当中的文档类别是:", mlb.predict(x_test)[:50]) print("测试集当中的文档真实类别是:", y_test[:50]) # 得出准确率 print("文档分类的准确率为:", mlb.score(x_test, y_test)) return None if __name__ == '__main__': multinormalcls()
优点:
-
朴素贝叶斯模型发源于古典数学理论,有稳定的分类效率。
-
对缺失数据不太敏感,算法也比较简单,常用于文本分类
-
分类准确度高,速度快
缺点:
-
由于使用了样本属性独立性假设,所以如果特征属性有关联时效果不好
-
也没有学习功能,固定公式计算,准确率是死的
决策树分类:
-
信息熵:(单位:比特 符号:H)
信息熵和消除不确定性是相联系的
-
信息增益:
决策分类算法的依据:得知某个特征,对总的信息熵减少的大小
-
减少越大:这个特征在建立树的时候越重要
-
API
import pandas as pd from sklearn.feature_extraction import DictVectorizer from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import train_test_split def decision(): """ 决策树预测乘客生存分类 :return: """ # 1、获取乘客数据 titan = pd.read_csv('../data/titanic_train.csv') # 2、确定特征值和目标值,缺失值处理,特征类别数据---->one-hot编码 x = titan[['Pclass', 'Age', 'Sex']] y = titan['Survived'] # 填充数据 x['Age'].fillna(x['Age'].mean(), inplace=True) # 特征类别数据 ----> One-hot编码 dic = DictVectorizer(sparse=False) # 列表转化成字典 x = dic.fit_transform(x.to_dict(orient="records")) # print(dic.get_feature_names()) # # print(x) # 分割数据集 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3) # 决策树进行预测 dec = DecisionTreeClassifier() dec.fit(x_train, y_train) print("预测的准确率为:", dec.score(x_test, y_test)) if __name__ == '__main__': decision()
-
dec = DecisionTreeClassifier()
-
ID3
信息增益 最大的准则
-
C4.5
信息增益比 最大的准则
-
CART
分类树:基尼系数 最小的准则 在sklearn中可以选择划分的的默认原则 优势:划分更加仔细
总结:
-
优点:简单的理解和解释,树木可视化。
-
缺点:
决策树学习者可以创建不能很好地推广数据的过于复杂的树,这被称为过拟合
-
改进:
-
减枝cart算法
-
随机森林
-
集成学习方法之随机森林:
集成学习方法:
-
集成学习通过建立几个模型组合来解决单一预测问题。它的工作原理是生成多个分类器/模型,最终结果多个分类器一起决定
随机森林:
-
随机森林是一个包含多个决策树的分类器
import pandas as pd from sklearn.feature_extraction import DictVectorizer from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import GridSearchCV def decision(): # 1、获取乘客数据 titan = pd.read_csv('../data/titanic_train.csv') # 2、确定特征值和目标值,缺失值处理,特征类别数据---->one-hot编码 x = titan[['Pclass', 'Age', 'Sex']] y = titan['Survived'] # 填充数据 x['Age'].fillna(x['Age'].mean(), inplace=True) # 特征类别数据 ----> One-hot编码 dic = DictVectorizer(sparse=False) # 列表转化成字典 x = dic.fit_transform(x.to_dict(orient="records")) print(dic.get_feature_names()) print(x) # 分割数据集 x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3) # 4、随机森林进行预测 rf = RandomForestClassifier() # 构造超参数字典 param = {'n_estimators': [120, 200], 'max_depth': [5, 8], 'min_samples_split': [2]} gc = GridSearchCV(rf, param_grid=param, cv=2) gc.fit(x_train, y_train) print("随机森林的准确率:", gc.score(x_test, y_test)) print("交叉验证选择的参数:", gc.best_estimator_) if __name__ == '__main__': decision()
API
ross_val_score()
-
交叉验证既可以解决数据集的数据量不够大问题,也可以解决参数调优的问题。
-
参数:
-
estimator:估计器,也就是模型
-
X, y:数据,标签值
-
soring:调用的方法
-
cv:交叉验证生成器或可迭代的次数
-
n_jobs:同时工作的cpu个数(-1代表全部)
-
verbose:日志冗长度,int:冗长度,0:不输出训练过程,1:偶尔输出,>1:对每个子模型都输出
-
fit_params:传递给估计器的拟合方法的参数
-
pre_dispatch:控制并行执行期间调度的作业数量。减少这个数量对于避免在CPU发送更多作业时CPU内存消耗的扩大是有用的。
-
pre_dispatch该参数可以是:none,在这种情况下,所有的工作立即创建并产生。将其用于轻量级和快速运行的作业,以避免由于按需产生作业而导致延迟
-
一个int,给出所产生的总工作的确切数量
-
一个字符串,给出一个表达式作为n_jobs的函数,如'2 * n_jobs'
-
-
from sklearn.model_selection import cross_val_score cross_val_score(estimator, X, y=None, *, groups=None, scoring=None, cv=None, n_jobs=None, verbose=0, fit_params=None, pre_dispatch="2*n_jobs", error_score=np.nan)
总结:
-
在当前所有算法中,具有极好的准确率
-
能够有效的运行在大数据集上,处理具有高维特征的输入样本,而且不需要降维
-
能够评估各个特征在分类问题上的重要性
回归与聚类算法
线性回归:(目标值是连续性)
-
特征值必须进行标准化
定义:y=mx+b b:偏置 m:权重
利用回归方程(函数)对一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方式
-
只有一个自变量的情况为单变量回归
-
一个以上自变量的情况为多变量回归(多元回归)
-
真实结果与预测结果的差距:损失函数
波士顿房价预测案例:正规方程和梯度下降的运用
from sklearn.linear_model import LinearRegression, SGDRegressor from sklearn.datasets import load_boston from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.metrics import mean_squared_error import math def mylinearregression(): """ 线性回归两种求解方式去进行房价预测 :return: """ lb = load_boston() # 分割数据集 x_train, x_test, y_train, y_test = train_test_split(lb.data, lb.target, test_size=0.3) # 对数据进行标准化处理 std = StandardScaler() x_train = std.fit_transform(x_train) x_test = std.fit_transform(x_test) # 使用线性回归的模型进行训练,以及预测 # 正规方程求解方式LinearRegression lr = LinearRegression(fit_intercept=True) # fit之后已经得出参数结果 lr.fit(x_train, y_train) print("正规方程计算出的权重:", lr.coef_) print("正规方程计算出的偏置:", lr.intercept_) # 调用 predict 去预测目标值 y_lr_predict = lr.predict(x_test) print("测试集预测的价格为:", y_lr_predict[:20]) # 调用均方误差去评估LinearRegression的结果误差怎么样 lr_error = mean_squared_error(y_test, y_lr_predict) # erro为每个样本误差的平方,开根号则为每个样本预测差4.58(万) print("LinearRegression的结果误差为:", math.sqrt(lr_error)) # SGDRegressor 梯度下降方法进行预测 sgd = SGDRegressor(loss="squared_error", fit_intercept=True, learning_rate="invscaling") sgd.fit(x_train, y_train) print("梯度下降计算出的权重:", sgd.coef_) print("梯度下降计算出的偏置:", sgd.intercept_) y_sgd_predict = sgd.predict(x_test) # 调用均方误差去评估 SGDRegressor 的结果误差怎么样 sgd_error = mean_squared_error(y_test, y_sgd_predict) print("SGDRegressor的结果误差为:", math.sqrt(sgd_error)) return None if __name__ == '__main__': mylinearregression()
优化算法(学习方法):
导入: from sklearn.linear_model import LinearRegression
-
目的:优化这些权重和偏置
-
正规方程:
直接通过特征值与目标值之间的矩阵运算得出
-
梯度下降(Gradient Descent):
导入: from sklearn.linear_model import SGDRegressor
-
最常用
-
-
随机梯度下降(Stochastic gradient descent)
是一个优化方法,他在一次迭代时只考虑一个训练样本
-
学习速率(α) * 方向(α旁边的部分)
-
fit_intercept=True:是否计算偏置
-
loss="squared_error":最小损失,普通最小二乘法
-
learning_rate="invscaling":指定学习率修改学习率取值:0~1,0.01,0.1,0.001 一般来说比较小,太大的话损失就很大
回归性能评估:
均方误差:
回归性能评估的API:
导入:from sklearn.metrics import mean_squared_error
# 调用均方误差去评估LinearRegression的结果误差怎么样 erro = mean_squared_error(y_test,y_predict) # erro为每个样本误差的平方,开根号则为每个样本预测差4.58(万) print("LinearRegression的结果误差为:",math.sqrt(erro))
非线性关系
欠拟合和过拟合:
-
因为机器学习到的天鹅特征太少了,导致区分标准太粗糙,不能准确识别出天鹅
-
机器学习已经基本能去别天鹅和其他动物了,然后,很不巧已有的天鹅特征学习图片中全是白天鹅,于是机器学习后会认为天鹅只有白色
过拟合:
是指学习时选择的模型所包含的参数过多,以至于出现这一模型对已知数据预测的很好,但对未知数据预测得很差的现象。这种情况下模型可能只是记住了训练集数据,而不是学习到了数据特征。(模型过于复杂)
欠拟合:
模型描述能力太弱,以至于不能很好地学习到数据中的规律。产生欠拟合的原因通常是(模型过于简单)
原因以及解决办法:
-
过拟合的原因以及解决方法:
-
原因:
-
原始特征过多,存在一些嘈杂特征,模型过于复杂是因为模型尝试去兼顾各个测试数据点
-
-
解决办法:
-
正则化:
在学习的时候,数据提供的特征有些影响模型复杂度或者这个特征的数据点异常较多,所以算法在学习的时候尽量减少这个特征的影响(甚至删除某个特征的影响),这就是正则化
-
L2正则化
-
作用:
可以使得其中一些w的值都很小,都接近于0,削弱某个特征的影响
-
优点:
越小的参数说明模型越简单,越简单的模型则越不容易产生过拟合现象
-
典型代表:
Ridge回归(岭回归):线性回归+L2正则化
-
-
L1正则化:
-
作用:
可以使得其中一些w的值直接为0,删除这个特征影响
-
典型代表:
LASSO回归:线性回归+L1正则化
-
-
-
-
-
欠拟合的原因以及解决办法:
-
原因:
-
学习到数据的特征过少
-
-
解决办法:
-
增加数据的特征数量
-
-
线性回归改进:
岭回归:
-
岭回归其实也是一种线性回归,只不过在算法建立回归方程时候,加上正则化的限制,从而达到解决过拟合的效果
-
选择:
对于小的数据集,首选岭回归去做预测
-
API
sklearn.linear_model.Ridge(alpha=1.0,fit_intercept=True,solver="auto",normalize=False) alpha:正则化力度,也叫λ(0~1,1~10) solver:会根据数据自动选择优化方法,sag:如果数据集特征都比较大,选择该随机梯度下降优化 normalize:数据是否进行标准化 Ridge.coef_:回归权重 Ridge.intercept_:回归偏置
SAG:随即平均梯度法,由于收敛的速度太慢,有人提出SAG等于梯度下降的算法
from sklearn.linear_model import LinearRegression,Ridge, SGDRegressor from sklearn.datasets import load_boston from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler from sklearn.metrics import mean_squared_error import math def mylinearregression(): """ 线性回归两种求解方式去进行房价预测 :return: """ lb = load_boston() # 分割数据集 x_train, x_test, y_train, y_test = train_test_split(lb.data, lb.target, test_size=0.3) # 对数据进行标准化处理 std = StandardScaler() x_train = std.fit_transform(x_train) x_test = std.fit_transform(x_test) # 使用带有L2正则化的线性回归去进行预测 rd = Ridge(alpha=1.0) rd.fit(x_train,y_train) print("岭回归计算出的权重:", rd.coef_) print("岭回归计算出的偏置:", rd.intercept_) y_rd_predict = rd.predict(x_test) # 调用均方误差去评估 Regressor 的结果误差怎么样 rd_error = mean_squared_error(y_test, y_rd_predict) print("岭回归的结果误差为:", math.sqrt(rd_error)) return None if __name__ == '__main__': mylinearregression()
分类算法-逻辑回归与二分类
逻辑归回:(Logistic Regression)
-
式机器学习中的一种分类模型,逻辑回归是一种分类算法,虽然名字中带有回归,但是它与回归之间有一定的联系,由于算法的简单和搞笑,字实际应用中非常广泛。
-
应用场景:
广告点击率、是否为垃圾邮件、是否患病、金融诈骗、虚拟账号
-
分类:
线性回归(输出连续性) + sigmoid函数 + 正则化(防止逻辑回归的过拟合)
-
sigmoid函数:
-
损失以及优化
-
损失:称为对数似然损失,公式如下
-
-
例子:
-
优化:
使用梯度下降优化算法,去减少损失函数的值。这样去更新逻辑回归前面对应算法的权重参数,
提升原本属于1类别的概率
降低原本是0类别的概率
逻辑回归API:
-
默认将数量少的当作正例(记为:1)
from sklearn.linear_model import LogisticRegression lr = LogisticRegression()
肿瘤预测案例:
from sklearn.linear_model import LogisticRegression from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler import pandas as pd import numpy as np def logistic(): """ 使用逻辑回归进行肿瘤数据预测 :return: """ # 列标签 column_name = [ 'Sample code number', 'Clump Thickness', 'Uniformity of Cell Size', 'Uniformity of Cell Shape', 'Marginal Adhesion', 'Single Epithelial Cell Size', 'Bare Nuclei', 'Bland Chromatin', 'Normal Nucleoli', 'Mitoses', 'Class' ] # 读取数据,处理缺失值 data = pd.read_csv( "https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/breast-cancer-wisconsin.data" , names=column_name) # 将?替换成np.nan() data = data.replace(to_replace='?', value=np.nan) data = data.dropna() # 分割数据到训练集测试集 # 分割数据集,iloc可以通过索引的下标去获取 x = data.iloc[:, 1:10] y = data.iloc[:, 10] x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3) # 进行标准化(前面的输入也是一个线性回归) std = StandardScaler() x_train = std.fit_transform(x_train) x_test = std.fit_transform(x_test) # 逻辑回归进行训练与预测 lr = LogisticRegression() # 会把恶性当作正例,记作4 会把良性当作反例,记作2 lr.fit(x_train, y_train) print("逻辑回归计算出的权重:", lr.coef_) print("逻辑回归计算出的偏置:", lr.intercept_) print("逻辑回归在测试集中的预测类别:", lr.predict(x_test)) print("逻辑回归预测的准确率:", lr.score(x_test, y_test)) return None if __name__ == '__main__': logistic()
分类评估
-
召回率(Recall):
真实为正例的样本中预测结果为正例的比例
-
分类评估报告API:
from sklearn.metrics import classification_report
# 召回率 recall = classification_report ( y_test, lr.predict(x_test), labels=[2, 4], target_names=['良性', '恶行'] ) print("预测的召回率为:", recall)
-
样本不均衡下的评估问题:
TPR与FPR:
-
ROC曲线:
-
AUC指标:
-
AUC最小值为0.5,最大值为1,取值越高越好 AUC指标>0.7 都是比较好的分类器
-
只能用来评价二分类
-
非常适合评价样本不平衡的分类器性能
-
-
AUC计算API:
from sklearn.metrics import roc_auc_score roc_auc_score(y_test, lr.predict(x_test)) y_test:每个样本的真实类别,必须为0(反例),1(正例)标记 lr.predict(x_test):每个样本预测的概率值
# 查看我们这个分类在这些癌症数据的AUC指标值 y_test = np.where(y_test > 2.5, 1, 0) print("此场景的分类器的AUC指标为:", roc_auc_score(y_test, lr.predict(x_test)))
模型的保存与加载:
API:
import joblib
# 保存模型 joblib.dump(lr, "My_linearegression.kpl") # 下次使用时直接加载kpl文件即可 lr_model = joblib.load("My_linearegression.kpl") print("预测未知的测试集:",lr_model.predict(x_test))
无监督学习:
-
聚类:K-means算法
-
原理:
-
API:
sklearn.cluster.KMeans(n_clusters=8,init=‘k-means++’)
-
参数:
-
n_clusters:开始的聚类中心数量
-
init:初始化方法,默认为’k-means ++’
-
labels_:默认标记的类型,可以和真实值比较(不是值比较)
-
-
-
Kmeans性能评估指标
-
import pandas as pd from sklearn.decomposition import PCA from sklearn.cluster import KMeans import matplotlib.pyplot as plt from sklearn.metrics import silhouette_score # 读取四张表的数据 prior = pd.read_csv("D:\Py-thon\pythonProject1\data\order_products__prior.csv", nrows=50000) products = pd.read_csv("D:\Py-thon\pythonProject1\data\products.csv", nrows=50000) orders = pd.read_csv("D:\Py-thon\pythonProject1\data\orders.csv", nrows=50000) aisles = pd.read_csv(r"D:\Py-thon\pythonProject1\data\aisles.csv", nrows=50000) # 合并四张表到一张表 (用户-物品类别) mg0 = pd.merge(prior, products, on=['product_id', 'product_id']) mg1 = pd.merge(mg0, orders, on=['order_id', 'order_id']) mt = pd.merge(mg1, aisles, on=['aisle_id', 'aisle_id']) # 交叉表(特殊的分组工具) # 进行交叉表变换,用户跟物品类别的分组次数统计 cross = pd.crosstab(mt['user_id'], mt['aisle']) # 进行PCA主成分分析 pca = PCA(n_components=0.95) data = pca.fit_transform(cross) # 把样本数量减少 cusumer = data[:400] # 假设用户一共分为四个类别 km = KMeans(n_clusters=4) km.fit(cusumer) # 得出每个用户在那个群里当中 predict = km.predict(cusumer) print(predict) # 评判聚类效果,轮廓系数 score = silhouette_score(cusumer,predict) print(score) # 显示聚类的结果 print(plt.figure(figsize=(10, 10))) # 建立四个颜色的列表 colored = ['orange', 'green', 'blue', 'purple'] colr = [colored[i] for i in predict] plt.scatter(cusumer[:, 1], cusumer[:, 20], color=colr) plt.xlabel("1") plt.ylabel("20") plt.show()
-
-
轮廓系数:
-
-
注:对于每个点i 为已聚类数据中的样本 ,b_i 为i 到其它族群的所有样本的平均距离,a_i 为i 到本身簇的距离平均值
-
最好的情况是x-0/x=1,最差的情况是0=x/x=-1,因此轮廓系数 [-1, 1]
-
b_i>>a_i: 1 完美
-
a_i>> b_i: -1 最差
-
-
Kmeans性能评估指标API
-
sklearn.metrics.silhouette_score(X, labels)
-
计算所有样本的平均轮廓系数
-
X:特征值
-
labels:被聚类标记的目标值
-
-
-
Kmeans总结
-
采用迭代式算法,直观易懂并且非常实用
-
缺点:容易收敛到局部最优解(多次聚类)
-
需要预先设定簇的数量(k-means++解决)
-