【课程】金融科技工具箱

基于B站 up 无机言nokay 的视频《金融科技工具箱——面向经管金融同学的Python、爬虫、机器学习课》的笔记,此视频偏向面对金融系学生的基础讲解;

优点:快速入门,全面,有主讲人个人研究时的想法;

缺点:因为面向群众不是计算机系且时间有限,比较零碎,深入需要自学;

0. 其他资料

  1. 廖雪峰的官方网站
  2. 《Python数据科学手册》
  3. 《利用python进行数据分析》

1. 基础部分

  • 跳过,有时间另外整一版统一复习

1.5 数据结构

用于导出$Jason$的数据结构,爬虫时应该会用到

1
2
3
4
import json
l1 = [['李磊',25,[{'name':'韩梅梅','age':'23'}]],['王二蛋',21,[]],['朱一旦',35,[{'name':'赵大','age':'23'},{'name':'钱二','age':'21','ex':['周五','吴六','郑七']}]]]
js = json.dumps(l1, sort_keys=True, indent=4, separators=(',', ':'),ensure_ascii=False)
print(js)

导出/导入$Jason$文件

1
2
3
4
5
6
root_dir = !echo %cd% # 在notebook里面运用的系统查找当前路径的方法
# 或os.getcwd()
with open(root_dir+'exs'+ '.json','wb+') as f:
f.write(json.dumps(l1).encode('utf-8'))
del l1
l1 = json.load(open(root_dir+'exs.json'))

1.6 常用函数

$cmd$操作

1
os.system(str格式的命令)

按位

1
2
3
# 按位与& 参与运算的两个值,如果其二进制值对应位都为1,则该位的结果为1,否则该位为 0
# 按位或| 只要对应的二个二进位有一个为 1 时,结果位就为 1,只有对应为都是 0, 结果为才是 0
# 二进制运算符

复制

1
# .copy()

打乱

1
2
3
4
import random
l_1 = [1,2,3,4,5,6]
random.shuffle(l_1)
print(l_1)

计个时

1
2
ltime = time.asctime( time.localtime(time.time()) )
print (ltime)

查看文档

1
?要查的fun名

1.7 作业

有趣的$tips$

1
[1,*[0.1]] # 做一个list首位是1,后面连接[0.1],类似[1]+[0.1]

画红❤

1
2
3
4
5
6
7
8
import  time,os,math
[(time.sleep(0.001), print("\033[91m"+i,end="",flush=True))
#\033[91m 红色 flush 滑动特效
for i in (' *'+'\n *'.join([''.join([(' I love U'[(x-y)%9] # 画出错位效果
if((x*0.05)**2+(y*0.15)**2-1)**3-(x*0.05)**2*(y*0.15)**3<=0 else' '
# 心型的函数,注释掉就是一面表白墙(↑)
)for x in range(-30,30)])+'*' for y in range(15,-15,-1)]))
]

图片颜色代替(不提供材料,可在原视频下载)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
import cv2
import os
#cv2 是OpenCV,一个专门用于图像处理的包
import numpy as np

root_dir = 'C:/Users/lenovo/Desktop/.....' #替换
#定义根目录

#------------------------
#此部分用于读取文件夹lego brick所有图片,并根据文件名,构建颜色名和颜色RGB的字典
work_dir = root_dir + 'lego'
color_dic = {}

for parent, dirnames, filenames in os.walk(work_dir, followlinks=True):
for filename in filenames:
#file_path = os.path.join(parent, filename)
file_path = work_dir+'/'+filename
#print(file_path)
# 以上为遍历work_dir中所有文件
if file_path[-3:] != 'jpg' and file_path[-3:] != 'png':
continue

# cv2.imread()接口读图像,读进来直接是BGR 格式数据格式在 0~255,通道格式为(W,H,C)
img = cv2.imread(file_path)
x_size = len(img)
y_size = len(img[0])
mid_point = img[x_size//2][y_size//2] #选中点
color_dic[filename.split('.')[0]] = mid_point

col_list=[]
for key in color_dic:
col_list.append(color_dic[key].astype('float64'))
#------------------------
#此部分用于读取待处理图片,并截取中心1:1比例,并resize至le*le
def img_mosaic(file_name,base_len):
raw_img = cv2.imread(file_name)
xlen = len(raw_img)
ylen = len(raw_img[0])
min_len = min(xlen,ylen)

sq_img = raw_img[xlen//2-min_len//2:xlen//2+min_len//2][ylen//2-min_len//2:ylen//2+min_len//2]
# 按最小长or宽截图
mc_img = cv2.resize(sq_img,(base_len,base_len))
# 按比例压缩
return mc_img
#------------------------
#此部分用于替换颜色,按照RGB数之差的平方的最小值选择
le=350 #resize值
mc_lena = img_mosaic(root_dir+'lena.jpg',le)

for y in range(le):
for x in range(le):
diff = np.sum(np.subtract(mc_lena[x,y],col_list)**2,axis=1)
index = np.argmin(diff)
mc_lena[x,y]=col_list[index]

cv2.imwrite(root_dir+'lena_mc.jpg', mc_lena) # 保存

2. Numpy和Pandas

2.1 Numpy

  • $array$所有元素都会变成同一个格式
  • 注意 $dtype$ 格式,有时候(格式不对会导致计算错误,如非10进制的格式)

初始化函数

1
2
3
4
5
6
7
8
9
10
# 矩阵生成
np.zeros/np.empty/np.ones/np.identity
np.full(维度,值)
np.eye(维,度,k = 偏移)
# 区间生成
np.arange(首,尾,步长)
np.linspace(首,尾,分离点个数)
# 随机数生成
np.random.random/np.random.normal/np.random.randint
np.random.seed(num) # 伪随机数

属性

1
2
3
4
5
6
7
8
9
10
# 维度
arr.ndim # 第一层维度 = len(arr)
arr.shape # 所有维度 = (len(arr),len(arr[0]),len(arr[0][0]))
arr.size # 总数
# 数据类型
# arr_浮点数.dtype > arr_整数.dtype
# arr_字符串.dtype 与其他无法比较
arr.itemsize # 每一个元素所占字节数
arr.nbytes # 共占多大
arr.astype(np.float) # 改数据类型

索引

  • 更换新数字时如果$type$不同将无法替换
  • 但如果是字符串包数字,可以放
  • $array$内截取的部分是$point$,如果改动截取的部分,原矩阵也会改变
1
2
3
4
5
6
7
8
# 数字索引
arr[首:尾:步长]
arr = np.array(range(20))
arr[3::3]
arr[5::-1]
arr[:10:-2]
# 布尔索引
arr[(arr > 0)&(arr < 10)]

变形,拼接和分裂

1
2
3
4
5
arr.T
arr.reshape
np.concatenate # 有 axis
np.vstack/np.hstack
np.split/np.vsplit/np.hsplit

函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
arr = np.arange(100000)
li = list(range(100000))
%time arr = arr*2
%time li = [l*2 for l in li]
# 高级函数
l1 =map(lambda x:x*2,li) # 此时只是map函数本身的对象,需要list()操作
def fun(x):
return x*2
l1 =map(fun,li) # 同等上面的
from functools import reduce
l2 = reduce(lambda x,y:x+y,li)
# 运算
# +-*/ // ** %
np.sin/cos/tan/arcsin
np.log/log2/log10/exp/exp2/exp10
np.expm1(x) # = exp(x) - 1
np.log1p(x) # = log(1 + x)
arr1.dot(arr2)/np.dot(arr1,arr2)
# tips:np有matrix函数,利于矩阵计算
Numpy中可用的聚合函数
函数名称 描述 函数名称 描述
np.sum 计算元素的和 np.argmin 找出最小值的索引
np.prod 计算元素的积 np.argmax 找出最大值的索引
np.mean 计算元素的平均值 np.median 计算元素的中位数
np.std 计算元素的标准差 np.percentile 计算基于元素排序的统计值
np.var 计算元素的方差 np.quantile 计算基于元素排序的统计值
np.min 找出最小值 np.any 验证任何一个元素是否为真
np.max 找出最大值 np.all 验证所以元素是否为真
1
2
3
4
# 排序
np.sort/np.argsort/arr.sort
li.sort(key = lambda x:x%3) # 有 axis
np.sort(arr)[::-1]/li.sort(...,reverse=True) # 降序排序

2.2 Pandas

初始化

1
2
3
4
5
# 一维
pd.Series(arr,index = []) # index 可重复
pd.Series(dict)
# 二维
pd.DataFrame({col1:sr1,col2:sr2})

定位

1
2
3
4
5
6
7
8
df.loc[[index],col]
df.iloc[num]
# df.ix 综合以上两种方法,不推荐
# 缺失值
df.isnull()/df.notnull() # 找缺失值
df.dropna() # 删除整行
df.fillna(method = "ffill") # 按前位填充 有 axis
df.fillna({col1:num1,col2:num2},limit = fillnum, inplace = True)

合并

1
2
3
4
pd.concate # 用于纵向合并
# join = "inner" 交集 "outer" 并集
pd.merge # 用于横向合并
# on 依照哪个变量拼接 left_on/right_on 不同名称对应拼接

Group

1
2
df.groupby(col)
df.describe() # 描述性统计

Jason转DF

1
2
3
4
5
6
7
8
9
10
11
12
13
all_res = []
for ii in range(10):
this_line = {}
this_line['num'] = ii
this_line['奇偶'] = 0 # 0是奇数
if ii % 2 == 0:
this_line['奇偶'] = 1
all_res.append(this_line)
import json
js = json.dumps(all_res, sort_keys=True, indent=4, separators=(',',':'),ensure_ascii=False)
print(js)
df_l = pd.DataFrame(all_res)
df_l

保存、读取

1
2
df.to_csv(root_dir+'df.csv',encoding='utf-8_sig') # sig 有中文时
df_in = pd.read_csv(root_dir+'df.csv')

3. 可视化

  • 跳过,有时间另外整一版统一复习
  • 可视化不只是画图,而是为了更好地表达(如:南丁格尔玫瑰图)
  • 画图工具包$pyecharts$

4. 爬虫

  • 跳过,有时间另外整一版统一复习

BeautifulSoup

1
2
3
html.strip() # 刚爬取到网页之后以防格式问题需要提前去头掐尾
html.find()/html.find_all() # 可包含 class_=
parse.quote() # 汉字编码

selenium

1
driver.find_element_by_xpath() # 可以使用xpath查找

API

  • 高德地图,$FutuQuant,Tushare,RiceQuant$等

5. 自然语言处理

  • 有监督算法的描述-情绪判断,作者识别
  • 无监督算法的描述-主题模型,词嵌入

独热编码(One-Hot)

主要是采用N位状态寄存器来对N个状态进行编码

1
2
3
4
5
6
7
8
9
10
from sklearn import preprocessing  

enc = preprocessing.OneHotEncoder()
enc.fit([[0,0,3],[1,1,0],[0,2,1],[1,0,2]])
# 这里一共有4个数据,3种特征

array = enc.transform([[0,1,3]]).toarray()
# 这里使用一个新的数据来测试

print (array) # [[ 1 0 | 0 1 0 | 0 0 0 1]]

5.1 词袋模型(bag of words)

1
2
3
4
5
6
7
from gensim.corpora import Dictionary

texts = [['human','interface','computer']]
dct = Dictionary(texts)
dct.add_documents([['cat','say','moon'],['dog']])
dct.doc2bow(['dog','computer','non_existent_word'])
# output:[(0,1),(6,1)] -> (index,num)

TF-IDF(term frequency–inverse document frequency)

TF用以评估一字词对于一个文章的重要程度

  • $n_{i,j}$ 词 $i$ 在 $j$ 中出现的次数

IDF用以评估一字词对于一个文章的不相关程度

  • $D$ 文章总数
  • $\{j:t_i\in d_j\}$ 包含词 $t_i$ 的文件数目

时间转换工具

用于时间排序

1
2
3
4
5
def large_time(raw_str):
tt = time.strptime(raw_str,'%Y-%m-%d')
return float(tt[0])*10000+float(tt[1])*100+float(tt[2])
# time.localtime/time.mktime
# 注意冬令时夏令时切换会少一小时

英文文章预处理

1
list(map(lambda x:x['content'].upper(),all_text))

分词

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import jieba
trial_str = '该书根据邓小平同志建设有中国特色的社会主义理论,把生产关系的研究与生产力的研究结合起来,把政治经济学与宏观经济学结合起来,把经济运动质的规律性与量的规律性的研究结合起来,形成了一个独具特色的国民经济学的理论体系'
r1 = jieba.cut(trial_str)
print("/ ".join(r1))
r2 = jieba.cut(trial_str,cut_all=True) # cut_all所有可能
print("/ ".join(r2))
jieba.add_word('宏观经济学', True) # 增加新词 防止切开
jieba.suggest_freq('与量', False) # 降低切割频率
r1 = jieba.cut(trial_str,HMM=False)
print("/ ".join(r1))
# 增加新词典
jieba.set_dictionary(root_dir+'dict.txt.big') # 官方提供
jieba.load_userdict(root_dir+"user_dict.txt")
# 词 频率 词性(可选)

以防万一,先保存

1
2
3
4
5
6
all_para = []
for li in range(len(ptext)):
cutted = jieba.cut(ptext[li])
all_para.append(list(cutted))
with open(root_dir+'sub_cutted'+ '.json','wb+') as f:
f.write(json.dumps(all_para).encode('utf-8'))

添加停用词

1
2
3
4
5
6
7
8
9
stwf = open(root_dir+'stop_words.txt','r',encoding = 'utf-8')
stset = stwf.readlines()
stop_words = []
for sti in stset[:-1]:
stop_words.append(sti[:-1])
stoplist = set(stop_words)
# 开始去除
texts = [[word for word in doc if word not in stoplist]
for doc in all_para]

去除低频词

1
2
3
4
5
6
7
8
from collections import defaultdict
frequency = defaultdict(int)
for text in texts:
for token in text:
frequency[token] += 1

texts = [[token for token in text if frequency[token] > 1]
for text in texts]

小容量储存

1
2
3
4
from gensim import corpora, models, similarities
dic = corpora.Dictionary(texts)
print(dic.token2id)
dic.save(root_dir+'sub_rmrb.dict') # 向前兼容

转为语料格式

1
2
3
4
from gensim.corpora import MmCorpus
corpus = [dic.doc2bow(text) for text in texts]
output_fname = root_dir+'sub_rmrb.mm'
MmCorpus.serialize(output_fname, corpus)

TF-IDF 模型

1
2
3
from gensim.models import TfidfModel
tf_model = TfidfModel(corpus)
vector = tf_model[corpus[0]]

更多可查看 gensim官方网站

5.2 主题模型

Unigram

step 1

  • $N:$ 文档
  • $w:$ 词
  • $Unigram$ 认为,每篇文章的词语是从一个独立多项式分布中抽取出来的
step 2

引入了一个主题的概念

  • $z:$ 主题
step 3

提出了混合主题,概率潜语义分析(pLSA/pLSI)

step 4

为参数引入先验分布,潜狄利克雷分布(LDA)

  • 主题 $z$ 是一个参数为 $\theta$ 的多项式分布,这个参数的先验分布是一个参数为$\alpha$ 的狄利克雷分布
  • 主题是否包含一个词是一个参数为 $\eta$ 的多项式分布,这个参数的先验分布是一个参数为 $\beta$ 的狄利克雷分布
  • 如果主题数目为 $K$ ,则 $\alpha = 50/K$
  • 如果词数量为 $W$ ,则 $\beta = 200/W $

扩展

动态主题模型

代码部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from gensim.models import LdaMulticore
num_topics = 20 #主题数
lda_fst = LdaMulticore(
corpus=corpus, num_topics=num_topics, id2word=dic,
workers=6, eval_every=None, passes=10, batch=True
)
# 以下步骤仅在Jupyter notebook内显示
import pyLDAvis.gensim
pyLDAvis.enable_notebook()
vis_sub_10 = pyLDAvis.gensim.prepare(lda_fst, corpus, dic, sort_topics = False)

pyLDAvis.display(vis_sub_10)
lda_fst.save(root_dir+'tiny_10.lda')

# 读取的方法
lda_fst = LdaMulticore.load('tiny_10.lda')
dic = corpora.Dictionary.load(root_dir+'sub_rmrb.dict')
corpus = MmCorpus(root_dir+'sub_rmrb.mm')

# 某篇文章对应主题的概率,可不用训练集
print(lda_fst.get_document_topics(corpus[0],minimum_probability=0.5))

主题相关性检验
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# 官方文档给的代码
from string import punctuation
from nltk import RegexpTokenizer
from nltk.stem.porter import PorterStemmer
from nltk.corpus import stopwords
from sklearn.datasets import fetch_20newsgroups
%matplotlib inline
def plot_difference_plotly(mdiff, title="", annotation=None):
"""Plot the difference between models.
Uses plotly as the backend."""
import plotly.graph_objs as go
import plotly.offline as py
annotation_html = None
if annotation is not None:
annotation_html = [
[
"+++ {}<br>--- {}".format(", ".join(int_tokens), ", ".join(diff_tokens))
for (int_tokens, diff_tokens) in row
]
for row in annotation
]
data = go.Heatmap(z=mdiff, colorscale='RdBu', text=annotation_html)
layout = go.Layout(width=950, height=950, title=title, xaxis=dict(title="topic"), yaxis=dict(title="topic"))
py.iplot(dict(data=[data], layout=layout))


def plot_difference_matplotlib(mdiff, title="", annotation=None):
"""Helper function to plot difference between models.
Uses matplotlib as the backend."""
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(18, 14))
data = ax.imshow(mdiff, cmap='RdBu_r', origin='lower')
plt.title(title)
plt.colorbar(data)
try:
get_ipython()
import plotly.offline as py
except Exception:
#
# Fall back to matplotlib if we're not in a notebook, or if plotly is
# unavailable for whatever reason.
#
plot_difference = plot_difference_matplotlib
else:
py.init_notebook_mode()
plot_difference = plot_difference_plotly
1
2
3
4
from gensim.models import LdaMulticore,LdaModel
lda_sub_10 = LdaModel.load(root_dir+'sub_10.lda')
mdiff, annotation = lda_sub_10.diff(lda_sub_10, distance='jaccard', num_words=50)
plot_difference(mdiff, title="Topic difference (one model) [jaccard distance]", annotation=annotation)

当集体颜色偏红,且对角一条为蓝点,则拟合成功

5.3 词向量模型

  • $Word2vec$ 简单扩展:$doc2vec$
针对主题
1
2
3
4
5
6
7
8
9
10
from gensim.models import Word2Vec
# 输入doc2bow之前的texts
model = Word2Vec(texts, size=50, window=5, min_count=1, workers=-1)
# workers=-1 , 最大-1
model.train(sentences = texts,total_words = len(dic),epochs = 50)
model.wv.most_similar("中国")

# 保存和读取
model.save(root_dir+'sub.w2v')
model = Word2Vec.load(root_dir+'sub.w2v')
针对文章
1
2
3
4
from gensim.models.doc2vec import Doc2Vec, TaggedDocument
documents = [TaggedDocument(doc, [i]) for i, doc in enumerate(texts)]
model = Doc2Vec(documents, size=50)
model.train(sentences = documents,total_examples=len(documents),epochs = 40)

6. 机器学习

6.1 一些概念

监督学习

  • 有监督 : 有标签的数据,人能指出的
  • 无监督 : 无标签的数据,理论上无法给出完美答案
  • 半监督 : 部分数据带标签, 如部分带标签的情绪识别
  • 强化学习 : 含隐藏标签

训练过程

  • $Batch$ 批处理 : 一次性训练所有数据
  • $Online$ : 一批一批使用数据
  • $Mini-batch$ : 以上两者结合
  • $Active Learning$ : 机器自己选择需要的数据

数据类型

  • 特征数据 : 有具体的含义
  • 原始数据 : 图像声音本身
  • 抽象数据 : 无意义的$UID$,主成分,其他中间结果

大数定律

由于不可能真正地存在完整的数据,输入数据$E_{in}(simple)$和真正完美的数据$E_{out}$ 必然存在误差;由于大数定理,及霍夫丁不等式 $(Hoeffding’s inequality)$ 得

如果$|E_{in}(h)-E_{out}(h)|$ 过大,则为坏数据

当存在$Breakpoint$, 则增长函数存在上限, 得$Vapnik-Chervonenkis (VC) bound$

因此,机器学习不仅要使$E_{in}$的误差尽量小,还需要使$E_{in}(h) \approx E_{out}(h)$ ;对此需要求得 $dvc (OLS,线性中为变量+1)$ , $N = 10 dvc$

6.2 线性回归

  • $Lasso$ 和 岭回归 此类带正则的通常不是无偏, 而计量经济中多为对系数的解释,通常不用此方法
  • 超参数($hyperparameter$)

6.3 SVM (Support Vector Machine)

  • $fewer dichotomies \to smaller ‘VC dim’$

  • $SVM$ 虽然不是无偏的,但 $B$ 变量可大于 $N$ 样本量

  • $CV(Cross-Validation)$ 交叉验证,可用 $K-Fold$ $(sklearn包)$

  • 反向扩充(基础)
    • $PLA(perceptron learning algorithm)$ -> $Pocket$算法 (前者改进)
    • $KNN(k-NearestNeighbor)$

6.4 决策树 (Decision Tree)

节点选择/切分策略

  • $ID3$算法,选择信息熵增大的最优算法
  • $C4.5$算法,选择信息增益比最大的切分点,限制了$ID3$多切带来的过拟合
  • $CART$算法,每一步切分使得数据正确率提升最多

停止切分

  • 剩余数据$y$相同
  • 剩余数据$x$相同
  • 设定最小收益值

决策树的正则化

  • 剪枝,减去几个带来收益最小的分叉节点
  • $Early Stopping$,提升停止的最小值阈值
  • 限制树高

实操建议

  • 特征数量大容易过拟合
  • 应预先进行维度压缩 $(PCA,ICA)$
  • 对不同树的构建方法应有了解
  • 提前将样本调平
    • 把劣势数据复制多份

融合算法 (Blending​)

  • $t = 1,2,3…T$
  • $D_t$ : the data at time $t$
  • Obtain $g_t$ by $A(D)$

Bootstrap Aggregation (Bagging)

在$Size$为$N$的数据里面抽$N’$个数据作为第一个子样本,放回去,再抽$N’$个数据作为第二个子样本

随机森林 (Random Forest)

Out of Bag

  • 当数据足够大时,一定有约等于 $\frac{1}{e}$的数据没有被抽取到
  • 样本外数据可以用于 对$G$的$Validation$
    • $G_N^-(x)=average(g_{没被用到的t})$
    • $E_{oob}(G)=\frac{1}{N}\sum_{n=1}^Nerr(y_n,G_n^-(x_n))$

特征选择

  • 变量重要性筛选 $permutation$ : 把变量打乱,$x_1 \to y_5$ ,差距越大越重要
    • 对于$Dummy Variable$ 这种方法肯能会低估,因为打乱不充足

AdaBoost

  • 计算$E_{in}$的时候,减少对做错过的$g_t$的$err$的权重
    • 所有做错的权重只占1/2
    • 当错$=n_1$,对$=n_2$
      • $incorrect: u_n^{(t)}·n_2 \to u_n^{(t+1)}$
      • $correct: u_n^{(t)}·n_1 \to u_n^{(t+1)}$
    • $\epsilon_t = \frac{\sum_{n=1}^N u_n^{(t)}[y_n \neq g_t(x_n)]}{\sum_{n=1}^N u_n^{(t)}}$,$\Diamond_t=\sqrt\frac{1-\epsilon_t}{\epsilon_t}$,$\alpha_t=ln(\Diamond_t)$
      • $incorrect: u_n^{(t)}·\Diamond_t \to u_n^{(t+1)}$
      • $correct: u_n^{(t)}/\Diamond_t \to u_n^{(t+1)}$
      • $G(x)=sign(\sum_{t=1}^T\alpha_tg_t(x))$
  • 决策树中,在再抽样的步骤完成$u^{(t)}\to u^{(t+1)}$的变换(复制多份)
  • 对于连续值:$GradientBoost$

6.5 编程的流程

  • 数据的准备
    • 数据的获取与存储方式
    • 数据的标签化(特征化)
    • 数据的清洗与预处理
  • 方法的选择
    • 合适的方法
    • 合适的超参数
    • 编程实现
  • 工程流水线
    • 标准流程
    • 训练、测试集切分
    • 正确的评价
  • 结果呈现
    • 表达准确
    • 易于理解

( 编程包 $sklearn$ )

7 深度学习

7.1 基础部分

  • 对元和层的理解
    • 单元数表达更细致的切分
    • 多层表达更复杂的非线性组合方式
  • $Sigmoid$
    • 代替$sign$求导
    • $S(x)=\frac{1}{1+e^{-x}}$
    • $S’(x)=\frac{e^{-x}}{(1+e^{-x})^2}=S(x)(1-S(x))$
  • $VC-dimension$
    • $V = $神经元的数量, $D = $权重的数量 (前一个元数$+1$再乘后一个元数)
  • 正则化
    • $L2$正则, 由于$sign$中心趋近0,且为了保持可导,通常用其他方法
    • $Early Stopping$
    • 加入白噪音
    • $Dropout$
  • 发展进程
    • $BP$神经网络(1986,$Hinton$)
    • 手写体识别(1989,$LeCun$)
    • 预处理 :权重训练方法的革新(2007,$Bengio$)
    • 正式提出$CNN$(2012,$Hinton$)
      • 图像分类,输入的是$3(RGB)\times224\times224$ (三维张量$tensor$)

7.2 卷积神经网络(CNN)

卷积

  • $input$为一个矩阵
  • 同时设定一个$filter$作为特征,和$step$值作为每次平移的步长
  • $input$最左上角切割出一个同$filter$同大小的矩阵,并与其相乘,得到$output$中的第一块
  • 按照步长平移最终得到完整的$output$

  • 卷积神经网络中会取一个值$b$,$output=sign(output-b)$
  • 达到了稀疏连接参数共享的效果

Pooling

  • 把数据变小,并保留最敏感的数$(Max Pooling)$
  • 对应可放大缩小的性质

扩充

  • 根据图片的特性推断,卷积神经网络适用于拥有以下特征的某些事物
    • 小特征决定
    • 放缩旋转存在
    • 放大缩小不改变性质
  • 不够数据的时候可以补0​

7.3 循环神经网络(RNN)

  • 把握时序特征($Recurrent NN$)
    • 隐藏层有一个循环
    • 历史输出端作为隐藏层的元素
    • 双向$RNN$
  • 当权重$w$跨过1的临界值时,如果迭代次数大,会有一个断崖式的变化,解决方法:
    • $Clipping$
      • $(2013,Pascanu)$
    • $Long Short-Term Memory$
      • $(1997,Sepp Hochreiter \& Jurgen Schmidhuber)$
      • 建立遗忘门

7.4 聚类算法

算法总览

Method name Parameters Scalability Usecase Geometry (metric used)
K-Means number of clusters Very large n_samples, medium n_clusters with MiniBatch code General-purpose, even cluster size, flat geometry, not too many clusters Distances between points
Affinity propagation damping, sample preference Not scalable with n_samples Many clusters, uneven cluster size, non-flat geometry Graph distance (e.g. nearest-neighbor graph)
Mean-shift bandwidth Not scalable with n_samples Many clusters, uneven cluster size, non-flat geometry Distances between points
Spectral clustering number of clusters Medium n_samples, small n_clusters Few clusters, even cluster size, non-flat geometry Graph distance (e.g. nearest-neighbor graph)
Ward hierarchical clustering number of clusters or distance threshold Large n_samples and n_clusters Many clusters, possibly connectivity constraints Distances between points
Agglomerative clustering number of clusters or distance threshold, linkage type, distance Large n_samples and n_clusters Many clusters, possibly connectivity constraints, non Euclidean distances Any pairwise distance
DBSCAN neighborhood size Very large n_samples, medium n_clusters Non-flat geometry, uneven cluster sizes Distances between nearest points
OPTICS minimum cluster membership Very large n_samples, large n_clusters Non-flat geometry, uneven cluster sizes, variable cluster density Distances between points
Gaussian mixtures many Not scalable Flat geometry, good for density estimation Mahalanobis distances to centers
Birch branching factor, threshold, optional global clusterer. Large n_clusters and n_samples Large dataset, outlier removal, data reduction. Euclidean distance between points

7.5 PCA

将数据投射为波动最大的$n$维

优点

  • 缓解维度灾难,提高可视度
  • 降噪,提高模型稳定性
  • 特征独立
  • 可以对数据进行放缩(各向同性)

风险

  • $PCA$的根据源于训练集,可能会过拟合
  • 如果在训练数据进行了放缩,那么测试集要进行同参数的$mean-shift$和$variance$
  • 不要先放缩再分割样本

Auto-Encoder

  • 输入输出长度相等
  • 扩展:$Denoising AutoEncoder$

7.6 生成模型

  • $GAN Generative Adversarial Network$
    • 人脸生成
    • 图片上色
    • 照片补充
    • 根据文字生成图片

8 特征工程

从数据到变量

8.1 结构化与缺失值

缺失值处理

  • 先思考缺失本身是不是就是一种信息
    • 确保缺失是纯随机的
    • 缺失是在哪个环境造成的
      • 原始收集环节/采集环节/清洗环节
  • 是否可以承担删变量带来的风险
    • 主要变量与控制变量,应该补上
    • 其他缺失如果超过阈值(一般为60%),应该删去
  • 处理方法
    • $Sklearn 6.4$ 专门用于缺失值处理
    • 单变量填充(固定值,统计值)
    • 多变量填充,近邻填充
    • 先分割再填充

结构化

  • 数据
    • 分类信息:性别,学历
    • 文本信息:$one-hot$
  • $Encoding$
    • $Ordinary encoder$
      • 0,1,2;
    • $one-hot encoder$
      • 类似计量中的方法:$FixedEffect$
      • 0,1 ; 0,1 ; 0,1 ;
  • $Embedding$ : 嵌入
    • $Doc2vec$:每一段(篇)文章一个向量
    • $Glove$:考虑上下文窗口之外的其他文本
    • $Elmo$:考虑不同文本在不同环境下的变义
    • 图片嵌入
      • $VAE(variation auto-encoder)$

8.2 改变分布

正则项和系数有关系,而系数又和数据有关系,所以要先做标准化

树方法的正则化不是来自于对系数的惩罚,可省略

前奏

  • 清洗异常值

  • 变形,删除极端值($winsor$)

标准化

  • (变量-均值)/标准差

  • 测试集的标准化按训练集来

  • $preprocessing.StandardScaler()+scaler.transform()$

  • 其他类似处理

    • $MinMaxScaler$
    • $MaxAbsScaler$

非线性变化:不惜一切变正态分布

  • 方法

    • $Box-Cox$
    • $Yeo-Johnson$
    • $Quantile transform$
  • 可以 $Lognormal,Ohi-squared,Weibull$

  • 不建议 $Gaussian,Uniform,Bimodal$,会损失信息

  • 改进了线性模型的预测能力

    • 看$R^2$和$MAE$

连续值变成分段值

  • 增强稳健性:对异常值和非线性

  • 试用于分类算法:信用风险模型,征信模型

  • $preprocessing.KBinsDiscretizer()$

8.3 变量选择

$sklearn.feature_selection$

为什么

  • 方法制约
  • 解释制约
  • 预测制约
  • 实践制约

单变量选择

单纯地从一个变量数据的分布进行筛选:$variation$大

  • $VarianceThreshold$:$variance$大于某值的
  • $SelectKBest$:筛选$K$个$variance$最高
  • $SelectPercentile$:筛选高于某个阈值的
    • 用于回归方法的分布:$f_regression,mutual_info_regression$
    • 用于分类方法的分布:$chi2,f_classif,mutual_info_classif$

多变量选择

多次共线性的影响

  • 方差膨胀系数($variance inflation factor$)
    • $VIF_i = \frac{1}{1-R_i^2}$
    • 当$VIF>10(or 5)$时,可以删去
    • 当变量比较重要,删去与它相关的变量

算法选择

最稳健的方法

  • $SelectFromModel$ 统一接口
  • 后台算法
    • $L1-based$
    • $Support vector based$
    • $Tree based$

8.4 实践:金融风控

  • 方法基础:评分卡模型,逻辑回归
  • 变量处理:离散化
  • 变量筛选:单变量,多变量
  • 重要方法:$WOE$与$IV$
    • $WOE_i = ln(\frac{py_i}{pn_i}) = ln(\frac{y_i/y_T}{n_i/n_T}) = ln(\frac{y_i/n_i}{y_T/n_T})$
    • $IV_i = (py_i-pn_i)*WOE_i$
    • $i = 1$ 是男生
    • $py_1 : $男生违约占比
    • $pn_1 : $男生不违约占比
    • $y_1 : $男生违约数量
    • $n_1 : $男生不违约数量
    • $y_T : $总体违约数量
    • $n_T : $总体不违约数量
IV范围 预测效果 英文描述
<0.02 几乎没有 Useless for prediction
0.02~0.1 Weak predictor
0.1~0.3 中等 Medium predictor
0.3~0.5 Strong predictor
>0.5 难以置信 Suspicious or too good to be true

9 训练框架

9.1 度量指标:二分类问题

一个标准

四个定义(数据-模型)
  • $True-positives$:数据+,模型+
  • $False-positives$:数据-,模型+
  • $False-negatives$:数据+,模型-
  • $True-negatives$:数据-,模型-
两个公式
  • $Precision = True-positives$/ 模型+
  • $Recall = True-positives$/ 数据+
一个指标:F1_score

另一个标准:ROC曲线与ROC面积(AUROC)

两个指标
  • 真正例率($TPR$):召回的同义词 ,$sensitivity$
    • $TPR = \frac{TP}{TP+FN}$
  • 假正例率($FPR$)$specifity$
    • $FPR = \frac{FP}{FP+TN}$

扩展:多分类问题

  • 三个指标:F1_micro,F1_macro,F1_weighted

9.2 度量指标:回归

  • $MAE = \frac{1}{N}\sum_{t=1}^N|y_i-\hat{y}|$
  • $MSE = \frac{1}{N}\sum_{t=1}^N(y_i-\hat{y})^2$
  • $RMSE = \sqrt{MSE}$
  • $R^2 = 1-\frac{\sum(y_i-\hat{y})^2}{\sum(y_i-\bar{y})^2} = 1-\frac{MSE(\hat{y},y)}{Var(y)}$

9.3 超参搜寻

搜索方法

  • $Grid Layout$
  • $Random Layout$
  • 步骤
    • 阅读论文找范围
    • 不同尺度的$Grid Layout$
    • $Random Layout$
  • 暴力手段之外
    • $Model specific cross-validation$
    • $AIC,BIC$
    • $Out of Bag Estimates$

9.4 交叉验证

$sklearn.model_selection$

数据切割

  • 训练数据(7)验证数据(2)测验数据(1)

  • 时间上的泄漏:注意时序数据中途没有被其他情况影响

  • 数据分组上的泄漏:一家人不能分开处理
  • 统计特征上的泄漏:先分割后处理

怎么划分

  • $KFold$
  • 随机抽取 = $ShuffleSplit$
  • 抽取时要保证类别间的平衡$= StratifiedShuffleSplit$
  • 当有小组时 $= GroupKFold$
  • 当有时间存在,训练集必须早于验证集 = $TimeSeriesSplit$

流程图

  1. 问题提出

  2. 文献搜集

    • 做过吗
    • 怎么做
    • 与课题有何差别
    • 能改什么方法
  3. 数据搜集
    • 典型数据库
    • 特异数据源
    • 数据更新管理
    • 成本控制
  4. 特征工程
    • 抽取哪些变量
    • 生成那些指标
    • 是否要改特征
    • 是否能改特征
  5. 模型选择
    • 符合假设
    • 能力优化
    • 容易解释
    • 开销合理
  6. 模型优化
    • 变量
    • 结构
    • 超参数
    • 训练技巧
  7. 结构呈现
    • 数据可视化
    • 关键词提炼
    • 模型更新策略
    • 边界与预警

Reference

  1. 金融科技工具箱——面向经管金融同学的Python、爬虫、机器学习课
  2. 文本挖掘从小白到精通(二)—-语料库和词向量空间
  3. 林轩田机器学习基石(国语)
  4. scikit-learn

【课程】金融科技工具箱
http://achlier.github.io/2021/04/14/金融科技工具箱/
Author
Hailey
Posted on
April 14, 2021
Licensed under