目录
1. 数据挖掘基础
Day01
Day02
Day03
Day04
Day05
Day06
2. 机器学习
Day07
Day08
Day09
3. 量化交易
Day10
Day11
Day12
Day13
4. 深度学习
Day14
Day15
Day16
绘制北京、上海两地11点到12点每分钟的温度变化状况。
答:
# 画出温度变化图
import random
# 准备x, y坐标的数据
x = range(60)
y_shanghai = [random.uniform(15, 18) for i in x]
# 增加北京的温度数据
y_beijing = [random.uniform(1, 3) for i in x]
# 1)创建画布
plt.figure(figsize=(20, 8), dpi=80)
# 2)绘制折线图
# plt.plot(x, y_shanghai)
plt.plot(x, y_shanghai, label="上海")
# 使用多次plot可以画多个折线
plt.plot(x, y_beijing, color='r', linestyle='--', label="北京")
# 显示图例
plt.legend(loc="best")
# 增加以下两行代码
# 构造x轴刻度标签
x_ticks_label = ["11点{}分".format(i) for i in x]
# 构造y轴刻度
y_ticks = range(40)
# 修改x,y轴坐标的刻度显示
plt.xticks(x[::5], x_ticks_label[::5])
plt.yticks(y_ticks[::5])
# 添加网格显示
plt.grid(True, linestyle='--', alpha=0.5)
# 添加x轴、y轴描述信息及标题
plt.xlabel("时间")
plt.ylabel("温度")
plt.title("中午11点0分到12点之间的温度变化图示")
# 3)显示图像
plt.show()
下面两个ndarray是否能够进行运算?
arr1 = np.array([[1, 2, 3, 2, 1, 4], [5, 6, 1, 2, 3, 1]])
arr2 = np.array([[1], [3]])
答:
可以,因为符合广播机制。
用Pandas筛选符合条件的数据的方法有哪些?
答:
data[(data['p_change'] > 2) & (data['open'] > 15)]
data.query("p_change > 2 & turnover > 15")
请简述Pandas处理缺失值的思路。
答:如何处理np.nan
1)判断数据中是否存在NaN缺失值
pd.isnull(df)
pd.notnull(df)
2) 两种方法:
1、删除含有缺失值的样本
df.dropna(axis=0, inplace=False)
2、替换/插补
sr.fillna(value, inplace=False)
如何处理其他默认标记的缺失值
1)将默认标记转换成np.nan
2)处理np.nan缺失值的思路
根据给定日线数据绘制日K线图。
答:
import pandas as pd
from mpl_finance import candlestick_ochl
import matplotlib.pyplot as plt
from matplotlib.pylab import date2num
# 数据读取
stock_day = pd.read_csv("./stock_day/stock_day.csv")
# 按时间顺序排列数据
stock_day = stock_day.sort_index()
# 准备ax
fig, axes = plt.subplots(nrows=1, ncols=1, figsize=(13, 8), dpi=100)
# 准备quotes
# 处理time字段
# 将时间索引类型转换成Pandas默认的类型
stock_day.index = pd.to_datetime(stock_day.index)
# 将时间转换成日K线绘制要求的浮点型
stock_day['time'] = date2num(stock_day.index)
# 索引sequence
day_k = stock_day[['time', 'open', 'close', 'high', 'low']]
# 绘制k线图
candlestick_ochl(axes, day_k.values[:30], width=0.4, colorup='r', colordown='g')
# x刻度设置为日期
axes.xaxis_date()
# 添加网格
plt.grid(linestyle="--", alpha=0.5)
# 显示图像
plt.show()
简述双均线策略。
答:
预设两条均线一条长均线、一条短均线。比如一个ma=5,一个ma=60, 5的均线被称作快线,60的均线被称作慢线。
买入策略中当快线上穿慢线(ma5上穿ma60)称为形成金叉买点信号,买入股票。
卖出策略中当快线下穿慢线(ma5下穿ma60)称为形成死叉卖点信号,卖出股票。
(1)机器学习概述
什么是深度学习,它与机器学习算法之间有什么联系?
深度学习是机器学习的一个子领域,它关心的是参照神经学科的理论构建神经网络,使用反向传播对大量未标注或半结构化的数据进行建模。从这个角度看,深度学习可以看成一种非监督学习算法,通过使用神经网络学习数据的表示。
监督学习和非监督学习有什么不同?
监督学习需要具有标签(label)的训练数据,比如做分类,你需要先对训练数据做标记,然后才能训练模型将数据分成你说需要的标记类。
而非监督学习则不需要。
什么时候你应该使用分类而不是回归?
分类会产生离散的数值,使得数据严格的分为不同类。回归会得到连续的值,使你更好的区分独立点之间的区别。当你需要知道你的数据明确的属于那些类时你可以用分类。
请简要说说一个完整机器学习项目的流程。
1 抽象成数学问题
明确问题是进行机器学习的第一步。指的我们明确我们可以获得什么样的数据,目标是一个分类还是回归或者是聚类的问题,如果都不是的话,如果划归为其中的某类问题。
2 获取数据
数据决定了机器学习结果的上限,而算法只是尽可能逼近这个上限。数据要有代表性,否则必然会过拟合。
而且对于分类问题,数据偏斜不能过于严重,不同类别的数据数量不要有数个数量级的差距。
而且还要对数据的量级有一个评估,多少个样本,多少个特征,可以估算出其对内存的消耗程度,判断训练过程中内存是否能够放得下。如果放不下就得考虑改进算法或者使用一些降维的技巧了。如果数据量实在太大,那就要考虑分布式了。
3 特征预处理与特征选择
特征预处理、数据清洗是很关键的步骤,往往能够使得算法的效果和性能得到显著提高。归一化、离散化、因子化、缺失值处理、去除共线性等,数据挖掘过程中很多时间就花在它们上面。这些工作简单可复制,收益稳定可预期,是机器学习的基础必备步骤。
筛选出显著特征、摒弃非显著特征,需要机器学习工程师反复理解业务。这对很多结果有决定性的影响。特征选择好了,非常简单的算法也能得出良好、稳定的结果。这需要运用特征有效性分析的相关技术,如相关系数、卡方检验、平均互信息、条件熵、后验概率、逻辑回归权重等方法。
4 训练模型与调优
直到这一步才用到我们上面说的算法进行训练。现在很多算法都能够封装成黑盒供人使用。但是真正考验水平的是调整这些算法的(超)参数,使得结果变得更加优良。这需要我们对算法的原理有深入的理解。理解越深入,就越能发现问题的症结,提出良好的调优方案。
5 模型诊断
过拟合、欠拟合 判断是模型诊断中至关重要的一步。常见的方法如交叉验证,绘制学习曲线等。过拟合的基本调优思路是增加数据量,降低模型复杂度。欠拟合的基本调优思路是提高特征数量和质量,增加模型复杂度。
误差分析 也是机器学习至关重要的步骤。通过观察误差样本,全面分析误差产生误差的原因:是参数的问题还是算法选择的问题,是特征的问题还是数据本身的问题……
诊断后的模型需要进行调优,调优后的新模型需要重新进行诊断,这是一个反复迭代不断逼近的过程,需要不断地尝试, 进而达到最优状态。
6 模型融合
一般来说,模型融合后都能使得效果有一定提升。而且效果很好。
工程上,主要提升算法准确度的方法是分别在模型的前端(特征清洗和预处理,不同的采样模式)与后端(模型融合)上下功夫。因为他们比较标准可复制,效果比较稳定。而直接调参的工作不会很多,毕竟大量数据训练起来太慢了,而且效果难以保证。
7 上线运行
这一部分内容主要跟工程实现的相关性比较大。工程上是结果导向,模型在线上运行的效果直接决定模型的成败。 不单纯包括其准确程度、误差等情况,还包括其运行的速度(时间复杂度)、资源消耗程度(空间复杂度)、稳定性是否可接受。
特征工程
TF-IDF是什么?
TF指Term frequecy,代表词频,IDF代表inverse document frequency,叫做逆文档频率,这个算法可以用来提取文档的关键词,首先一般认为在文章中出现次数较多的词是关键词,词频就代表了这一项,然而有些词是停用词,例如的,是,有这种大量出现的词,首先需要进行过滤,比如过滤之后再统计词频出现了中国,蜜蜂,养殖且三个词的词频几乎一致,但是中国这个词出现在其他文章的概率比其他两个词要高不少,因此我们应该认为后两个词更能表现文章的主题,IDF就代表了这样的信息,计算该值需要一个语料库,如果一个词在语料库中出现的概率越小,那么该词的IDF应该越大,一般来说TF计算公式为(某个词在文章中出现次数/文章的总词数),这样消除长文章中词出现次数多的影响,IDF计算公式为log(语料库文章总数/(包含该词的文章数)+1)。将两者乘乘起来就得到了词的TF-IDF。传统的TF-IDF对词出现的位置没有进行考虑,可以针对不同位置赋予不同的权重进行修正,注意这些修正之所以是有效的,正是因为人观测过了大量的信息,因此建议了一个先验估计,人将这个先验估计融合到了算法里面,所以使算法更加的有效。
数据规范化是什么?为什么需要对数据进行规范化?
数据规范化在预处理阶段尤为重要,它可以将数值缩放到特定的范围,以在反向传播时获得更好的收敛性。一般而言,规范化就是让每一个数据点减去它们的均值,并除以标准差。
如果不这样处理,一些(数量级较大的)特征值在代价函数中的权重就会更大(如果大数量级特征值改变1%,代价函数的变化就会很大,但小数量级的特征值改变1%产生的影响则微乎其微)。规范化使得所有特征值具有相同的权重。
请解释降维,以及使用场合和它的优势。
降维是一种通过分析出主变量来减少特征变量的过程,其中主变量通常就是重要的特征。一个特征变量的重要性取决于它对数据信息的解释程度,以及你所采用的方法。至于如何选取方法,主要靠不断摸索,以及你自己的偏好。通常大家会从线性方法开始,如果结果欠缺拟合性,则考虑尝试非线性的方法。
数据降维的优势有以下几点:
(1)节省存储空间;
(2)节省计算时间(比如应用于机器学习算法时);
(3)去除冗余特征变量,正如同时以平方米和平方英里存储地区面积没有任何意义(甚至可能是收集数据时出现错误);
(4)将数据降维到二维或三维后,我们或许可以画图,将数据可视化,以观察数据具有的模式,获得对数据的直观感受;
(5)特征变量过多或模型过于复杂可能导致模型过拟合。
如何进行特征选择?
特征选择是一个重要的数据预处理过程,主要有两个原因,首先在现实任务中我们会遇到维数灾难的问题(样本密度非常稀疏),若能从中选择一部分特征,那么这个问题能大大缓解,另外就是去除不相关特征会降低学习任务的难度,增加模型的泛化能力。冗余特征指该特征包含的信息可以从其他特征中推演出来,但是这并不代表该冗余特征一定没有作用,例如在欠拟合的情况下也可以用过加入冗余特征,增加简单模型的复杂度。
在理论上如果没有任何领域知识作为先验假设那么只能遍历所有可能的子集。但是这显然是不可能的,因为需要遍历的数量是组合爆炸的。一般我们分为子集搜索和子集评价两个过程,子集搜索一般采用贪心算法,每一轮从候选特征中添加或者删除,分别成为前向和后先搜索。或者两者结合的双向搜索。子集评价一般采用信息增益,对于连续数据往往排序之后选择中点作为分割点。
常见的特征选择方式有过滤式,包裹式和嵌入式,filter,wrapper和embedding。Filter类型先对数据集进行特征选择,再训练学习器。Wrapper直接把最终学习器的性能作为特征子集的评价准则,一般通过不断候选子集,然后利用cross-validation过程更新候选特征,通常计算量比较大。嵌入式特征选择将特征选择过程和训练过程融为了一体,在训练过程中自动进行了特征选择,例如L1正则化更易于获得稀疏解,而L2正则化更不容易过拟合。L1正则化可以通过PGD,近端梯度下降进行求解。
如何处理数据集中缺失或损坏的数据?
可以在数据集中找到缺失/损坏的数据,并删除它所在的行或列,或是用其他值代替之。Pandas中有两个非常有效的函数:isnull()和dropna(),这两个函数可以帮你找到有缺失/损坏数据的行,并删除对应值。如果要用占位符(比如0)填充这些无效值,你可以使用fillna()函数。
KNN中的K如何选取的?
如果选择较小的K值,就相当于用较小的领域中的训练实例进行预测,“学习”近似误差会减小,只有与输入实例较近或相似的训练实例才会对预测结果起作用,与此同时带来的问题是“学习”的估计误差会增大,换句话说,K值的减小就意味着整体模型变得复杂,容易发生过拟合;
如果选择较大的K值,就相当于用较大领域中的训练实例进行预测,其优点是可以减少学习的估计误差,但缺点是学习的近似误差会增大。这时候,与输入实例较远(不相似的)训练实例也会对预测器作用,使预测发生错误,且K值的增大就意味着整体的模型变得简单。
K=N,则完全不足取,因为此时无论输入实例是什么,都只是简单的预测它属于在训练实例中最多的累,模型过于简单,忽略了训练实例中大量有用信息。
在实际应用中,K值一般取一个比较小的数值,例如采用交叉验证法来选择最优的K值。
KNN和k-means聚类由什么不同?
k-Nearest Neighbors 是一种监督学习算法,而k-means 是非监督的。这两种算法看起来很相似,都需要计算样本之间的距离。knn算法需要事先已有标注好的数据,当你需要对未标注的数据进行分类时,统计它附近最近的k个样本,将其划分为样本数最多的类别中。k-means聚类只需要一些未分类的数据点和阀值,算法会逐渐将样本点进行分成族类。
为什么我们要称“朴素“贝叶斯?
因为我们在用到它的时候,有一个很强的假设,现实数据中几乎不会出现的:我们假设特征之间是相互独立,也就是我们计算条件概率时可以简化成它的组件的条件概率乘积。
举个例子,说明使用集成学习会很有用。
集成学习通过组合一些基学习算法来优化得到更好的预测性能,通常可以防止模型的过拟合使模型更具有鲁棒性。
你可以列举一些集成学习的例子,如bagging、boosting、stacking等,并且了解他们是如何增加模型预测能力的。
为什么会产生过拟合,有哪些方法可以预防或克服过拟合?
一般在机器学习中,将学习器在训练集上的误差称为训练误差或者经验误差,在新样本上的误差称为泛化误差。显然我们希望得到泛化误差小的学习器,但是我们事先并不知道新样本,因此实际上往往努力使经验误差最小化。然而,当学习器将训练样本学的太好的时候,往往可能把训练样本自身的特点当做了潜在样本具有的一般性质。这样就会导致泛化性能下降,称之为过拟合,相反,欠拟合一般指对训练样本的一般性质尚未学习好,在训练集上仍然有较大的误差。
欠拟合:一般来说欠拟合更容易解决一些,例如增加模型的复杂度,增加决策树中的分支,增加神经网络中的训练次数等等。
过拟合:一般认为过拟合是无法彻底避免的,因为机器学习面临的问题一般是np-hard,但是一个有效的解一定要在多项式内可以工作,所以会牺牲一些泛化能力。过拟合的解决方案一般有增加样本数量,对样本进行降维,降低模型复杂度,利用先验知识(L1,L2正则化),利用cross-validation,early stopping等等。
L1、L2正则之间有什么不同?
L2正则 对应的是加入2范数,使得对权重进行衰减,从而达到惩罚损失函数的目的,防止模型过拟合。保留显著减小损失函数方向上的权重,而对于那些对函数值影响不大的权重使其衰减接近于0。相当于加入一个gaussian prior。
L1正则 对应得失加入1范数,同样可以防止过拟合。它会产生更稀疏的解,即会使得部分权重变为0,达到特征选择的效果。相当于加入了一个laplacean prior。
L1范数(L1 norm)是指向量中各个元素绝对值之和
L2范数: 为x向量各个元素平方和的1/2次方.
L1范数可以使权值稀疏,方便特征提取。
L2范数可以防止过拟合,提升模型的泛化能力。
L1和L2正则先验分别服从什么分布
L1是拉普拉斯分布,L2是高斯分布。
先验就是优化的起跑线, 有先验的好处就是可以在较小的数据集中有良好的泛化性能,当然这是在先验分布是接近真实分布的情况下得到的了,从信息论的角度看,向系统加入了正确先验这个信息,肯定会提高系统的性能。
你如何确保你的模型没有过拟合?
过度拟合的训练数据以及数据携带的噪音,对于测试数据会带来不确定的推测。有如下三种方法避免过拟合:
保持模型尽可能地简单:通过考量较少的变量和参数来减少方差,达到数据中消除部分噪音的效果。
使用交叉检验的手段如:k-folds cross-validation。
使用正则化的技术如:LASSO方法来惩罚模型中可能导致过拟合的参数。
LR与线性回归的区别与联系。
逻辑回归的模型本质上是一个线性回归模型,逻辑回归都是以线性回归为理论支持的。但线性回归模型无法做到sigmoid的非线性形式。
KNN和k-means聚类由什么不同?
k-Nearest Neighbors 是一种监督学习算法,而k-means 是非监督的。这两种算法看起来很相似,都需要计算样本之间的距离。knn算法需要事先已有标注好的数据,当你需要对未标注的数据进行分类时,统计它附近最近的k个样本,将其划分为样本数最多的类别中。k-means聚类只需要一些未分类的数据点和阀值,算法会逐渐将样本点进行分成族类。
在k-means或kNN,我们常用欧氏距离来计算最近的邻居之间的距离,有时也用曼哈顿距离,请对比下这两种距离的差别。
欧氏距离,最常见的两点之间或多点之间的距离表示法,又称之为欧几里得度量。欧氏距离的缺点是将样品的不同属性之间的差别等同看待,然而个体的不同属性对于区分个体有着很重。因此,欧氏距离适用于向量各分量的度量标准统一的情况。
曼哈顿距离,我们可以定义曼哈顿距离的正式意义为L1-距离或城市区块距离,也就是在欧几里得空间的固定直角坐标系上两点所形成的线段对轴产生的投影的距离总和。
曼哈顿距离和欧式距离一般用途不同,无相互替代性。
解释一下ROC曲线的原理
ROC曲线是真正率和假正率在不同的阈值下之间的图形表示关系。通常用作权衡模型的敏感度与模型对一个错误分类报警的概率。
真正率表示:表示正的样本被预测为正占所有正样本的比例。
假正率表示:表示负的样本被预测为正占所有负样本的比例。
(0,0)点表示所有样本都被预测为负,此时阈值很大。
(1,1)点表示所有样本都被预测为正,此时阈值很小。
定义一下prediction准确率、recall召回率
召回率就是真正率。
准确率指的是:正样本被预测为正所占所有预测为正样本数的比例。
模型的精度和模型的性能哪个对你更重要?
许多机器学习的模型会有高的精度,但是预测能力也就是泛化能力较低,如何去理解它们呢?
精度只是模型性能的一部分,有可能是会产生误导的那个。对于具有倾斜的数据集,比如要从大量的金融数据中识别出少量的诈骗数据,一个精度高的模型可能会告诉你没有诈骗,然而这样的模型预测是没有意义的。所以,不要总是把精度当作模型最重要的事。
什么是F1数,怎么使用它?
F1数是衡量模型性能的一个指标。它是模型精准率和召回率的加权平均,1表示最好,0表示最差。在分类问题中有时精准率和召回率不会同时都高,那么我们可以使用F1数。
如何处理一个不平衡的数据集?
不平衡的数据集:比如二分类问题中,一类数据有90%,而另一类只有10%。我们可以轻易的得到90%准确率的模型,但是它对第二类的预测值为0。那么我们需要对这样的数据进行处理:
收集更多的数据,使其达到平衡
使用重复采样
使用不同的算法
重要的是:你注意到了数据的不平衡导致的问题,以及如何去解决它们。
如何评估你的机器学习模型的有效性?
首先你需要将数据分成训练集和测试集,或者使用给交叉验证方法分割。然后你需要选择度量模型表现的metrics,如F1数、准确率、混淆矩阵等。更重要的是,根据实际情况你需要理解模型度量的轻微差别,以便于选择正确的度量标准。
在分类问题中,我们经常会遇到正负样本数据量不等的情况,比如正样本为10w条数据,负样本只有1w条数据,以下最合适的处理方法是()
A.将负样本重复10次,生成10w样本量,打乱顺序参与分类
B.直接进行分类,可以最大限度利用数据
C.从10w正样本中随机抽取1w参与分类
D.将负样本每个权重设置为10,正样本权重为1,参与训练过程
正确答案:ACD
解析:1. 重采样。 A可视作重采样的变形。改变数据分布消除不平衡,可能导致过拟合。
2. 欠采样。 C的方案 提高少数类的分类性能,可能丢失多数类的重要信息。
如果1:10算是均匀的话,可以将多数类分割成为1000份。然后将每一份跟少数类的样本组合进行训练得到分类器。而后将这1000个分类器用assemble的方法组合位一个分类器。A选项可以看作此方式,因而相对比较合理。
另:如果目标是 预测的分布 跟训练的分布一致,那就加大对分布不一致的惩罚系数。
3. 权值调整。 D方案也是其中一种方式。
当然,这只是在数据集上进行相应的处理,在算法上也有相应的处理方法。
用量化交易平台写一个简单的交易策略。
答:
import talib
def init(context):
# 在context中保存全局变量
# 设置股票池
context.stocks = index_components("000300.XSHG")
# 设置周期
context.short = 12
context.long = 26
context.signal = 9
context.observe = 100
# before_trading此函数会在每天策略交易开始前被调用,当天只会被调用一次
def before_trading(context):
pass
# 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新
def handle_bar(context, bar_dict):
# 开始编写你的主要的算法逻辑
for stock in context.stocks:
# print(stock)
# 获取历史收盘价
price = history_bars(stock, context.observe, "1d", "close")
# 计算MACD指标
dif, dea, bar = talib.MACD(price, context.short, context.long, context.signal)
# print(dif)
# 双均线策略:
# 卖出:
# 昨天 快线 > 慢线 并且 今天 快线 < 慢线
if dif[-2] > dea[-2] and dif[-1] < dea[-1]:
if context.portfolio.positions[stock].quantity > 0:
order_target_percent(stock, 0)
# 买入:
# 昨天 快线 < 慢线 并且 今天 快线 > 慢线
if dif[-2] < dea[-2] and dif[-1] > dea[-1]:
order_target_percent(stock, 0.1)
# after_trading函数会在每天交易结束后被调用,当天只会被调用一次
def after_trading(context):
pass
用代码实现市值中性化。
答:
# 获取这两个因子数据
q = query(fundamentals.eod_derivative_indicator.pb_ratio,
fundamentals.eod_derivative_indicator.market_cap)
# 获取的是某一天的横截面数据
factor = get_fundamentals(q, entry_date="2018-01-03")[:, 0, :]
# 先对pb_ratio进行去极值标准化处理
factor['pb_ratio'] = mad(factor['pb_ratio'])
factor['pb_ratio'] = stand(factor['pb_ratio'])
# 确定回归的数据
# x:市值
# y : 因子数据
x = factor['market_cap'].reshape(-1, 1)
y = factor['pb_ratio']
# 建立回归方程并预测
lr = LinearRegression()
lr.fit(x, y)
y_predict = lr.predict(x)
# 去除线性的关系,留下误差作为该因子的值
factor['pb_ratio'] = y - y_predict
编写代码计算因子IC值。
答:
import scipy.stats as st
import pandas as pd
import numpy as np
# 1、获取因子暴露度
# 1)获取财务数据
stocks = industry("C39")
q = query(fundamentals.eod_derivative_indicator.pe_ratio).filter(
fundamentals.stockcode.in_(stocks))
fund = get_fundamentals(q, entry_date="20170105")[:, 0, :]
def med_method(factor):
# 1、找到MAD值
med = np.median(factor)
distance = abs(factor - med)
MAD = np.median(distance)
# 2、求出MAD_e
MAD_e = 1.4826 * MAD
# 3、求出正常值范围的边界
up_scale = med + 3 * MAD_e
down_scale = med - 3 * MAD_e
# 4、替换
factor = np.where(factor > up_scale, up_scale, factor)
factor = np.where(factor < down_scale, down_scale, factor)
return factor
# 自实现标准化
# (x - mean) / std
def stand_method(factor):
mean = np.mean(factor)
std = np.std(factor)
factor = (factor - mean) / std
return factor
# 2)处理缺失值
fund = fund.dropna()
# 3)去极值、标准化
fund["pe_ratio"] = med_method(fund["pe_ratio"])
fund["pe_ratio"] = stand_method(fund["pe_ratio"])
# 2、获取该因子的收益率
# 1)获取历史交易数据
price = get_price(list(fund.index), start_date="20170105", end_date="20170106", fields="close").T
# 2)处理缺失值
price = price.dropna()
# 3)进行收益率计算
return_rate = price.iloc[:, 1] / price.iloc[:, 0] - 1
# 合并处理
data = pd.concat([fund["pe_ratio"], return_rate], axis=1)
# 3、进行相关系数计算
st.spearmanr(data["pe_ratio"], data[0])
代码实现打分法选股策略。
答:
# 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。
import pandas as pd
# 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。
def init(context):
# 1、定义选股的数量
context.stocks_num = 20
# 2、定义分组的组数
context.groups_num = 10
# 3、定义月定时器
scheduler.run_monthly(score_select, tradingday=1)
# 实现打分法选股策略
def score_select(context, bar_dict):
# 1、获取因子数据
q = query(fundamentals.eod_derivative_indicator.market_cap,
fundamentals.eod_derivative_indicator.pe_ratio,
fundamentals.eod_derivative_indicator.pb_ratio,
fundamentals.financial_indicator.return_on_invested_capital,
fundamentals.financial_indicator.inc_revenue,
fundamentals.financial_indicator.inc_profit_before_tax)
fund = get_fundamentals(q)
factor_data = fund.T
# print(factor_data)
# 不需要进行去极值、标准化、市值中性化(打分法选股只需知道排名)
# 处理缺失值
factor_data = factor_data.dropna()
# 2、进行打分,得出股票列表
select_stocks(context, factor_data)
# 3、每月调仓
rebalance(context)
def select_stocks(context, factor_data):
# 分组打分
for factor in factor_data.columns:
# 根据因子方向进行不同处理
# 越小越好:市值、市盈率、市净率
if factor in ["market_cap", "pe_ratio", "pb_ratio"]:
sorted_factor = factor_data.sort_values(by=factor)[factor]
# print("sorted_factor:\n", sorted_factor)
# print("sorted_factor类型:\n", type(sorted_factor))
# 越大越好:ROIC、inc_revenue营业总收入和inc_profit_before_tax利润增长率
else:
sorted_factor = factor_data.sort_values(by=factor, ascending=False)[factor]
# print("sorted_factor:\n", sorted_factor)
# 分组打分
# 将sorted_factor转换成dataframe方便我们打分
sorted_factor = pd.DataFrame(sorted_factor)
sorted_factor[factor+"_score"] = 0
# print(sorted_factor)
# 计算每组的股票数量
stock_count = len(sorted_factor) // context.groups_num
for i in range(context.groups_num):
if i == context.groups_num - 1:
sorted_factor[factor+"_score"][i*stock_count:] = i+1
else:
sorted_factor[factor+"_score"][i*stock_count:(i+1)*stock_count] = i+1
# 合并所有因子的分数
factor_data = pd.concat([factor_data, sorted_factor[factor+"_score"]], axis=1)
# print("合并后的表:\n", factor_data)
# 分数加和
sum_score = factor_data.iloc[:, 6:].sum(1).sort_values()
# 选股结果
context.stocks = sum_score[:context.stocks_num].index
# print(sum_score)
# print(context.stocks)
def rebalance(context):
# 卖出
for stock in context.portfolio.positions.keys():
if context.portfolio.positions[stock].quantity > 0:
if stock not in context.stocks:
order_target_percent(stock, 0)
# 买入
for stock in context.stocks:
order_target_percent(stock, 1.0/context.stocks_num)
# before_trading此函数会在每天策略交易开始前被调用,当天只会被调用一次
def before_trading(context):
pass
# 你选择的证券的数据更新将会触发此段逻辑,例如日或分钟历史数据切片或者是实时数据切片更新
def handle_bar(context, bar_dict):
pass
# after_trading函数会在每天交易结束后被调用,当天只会被调用一次
def after_trading(context):
pass
用TensorFlow实现线性回归。
答:
# 用tensorflow自实现一个线性回归案例
# 定义一些常用的命令行参数
# 训练步数
tf.app.flags.DEFINE_integer("max_step", 0, "训练模型的步数")
# 定义模型的路径
tf.app.flags.DEFINE_string("model_dir", " ", "模型保存的路径+模型名字")
FLAGS = tf.app.flags.FLAGS
class MyLinearRegression(object):
"""
自实现线性回归
"""
def __init__(self):
pass
def inputs(self):
"""
获取特征值目标值数据数据
:return:
"""
x_data = tf.random_normal([100, 1], mean=1.0, stddev=1.0, name="x_data")
y_true = tf.matmul(x_data, [[0.7]]) + 0.8
return x_data, y_true
def inference(self, feature):
"""
根据输入数据建立模型
:param feature:
:param label:
:return:
"""
with tf.variable_scope("linea_model"):
# 2、建立回归模型,分析别人的数据的特征数量--->权重数量, 偏置b
# 由于有梯度下降算法优化,所以一开始给随机的参数,权重和偏置
# 被优化的参数,必须得使用变量op去定义
# 变量初始化权重和偏置
# weight 2维[1, 1] bias [1]
# 变量op当中会有trainable参数决定是否训练
self.weight = tf.Variable(tf.random_normal([1, 1], mean=0.0, stddev=1.0),
name="weights")
self.bias = tf.Variable(0.0, name='biases')
# 建立回归公式去得出预测结果
y_predict = tf.matmul(feature, self.weight) + self.bias
return y_predict
def loss(self, y_true, y_predict):
"""
目标值和真实值计算损失
:return: loss
"""
# 3、求出我们模型跟真实数据之间的损失
# 均方误差公式
loss = tf.reduce_mean(tf.square(y_true - y_predict))
return loss
def merge_summary(self, loss):
# 1、收集张量的值
tf.summary.scalar("losses", loss)
tf.summary.histogram("w", self.weight)
tf.summary.histogram('b', self.bias)
# 2、合并变量
merged = tf.summary.merge_all()
return merged
def sgd_op(self, loss):
"""
获取训练OP
:return:
"""
# 4、使用梯度下降优化器优化
# 填充学习率:0 ~ 1 学习率是非常小,
# 学习率大小决定你到达损失一个步数多少
# 最小化损失
train_op = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
return train_op
def train(self):
"""
训练模型
:param loss:
:return:
"""
g = tf.get_default_graph()
with g.as_default():
x_data, y_true = self.inputs()
y_predict = self.inference(x_data)
loss = self.loss(y_true, y_predict)
train_op = self.sgd_op(loss)
# 收集观察的结果值
merged = self.merge_summary(loss)
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
# 在没训练,模型的参数值
print("初始化的权重:%f, 偏置:%f" % (self.weight.eval(), self.bias.eval()))
# 加载模型
checkpoint = tf.train.latest_checkpoint("./tmp/model/")
# print(checkpoint)
if checkpoint:
print('Restoring', checkpoint)
saver.restore(sess, checkpoint)
# 开启训练
# 训练的步数(依据模型大小而定)
for i in range(FLAGS.max_step):
sess.run(train_op)
# 生成事件文件,观察图结构
file_writer = tf.summary.FileWriter("./tmp/summary/", graph=sess.graph)
print("训练第%d步之后的损失:%f, 权重:%f, 偏置:%f" % (
i,
loss.eval(),
self.weight.eval(),
self.bias.eval()))
# 运行收集变量的结果
summary = sess.run(merged)
# 添加到文件
file_writer.add_summary(summary, i)
if i % 100 == 0:
# 保存的是会话当中的变量op值,其他op定义的值不保存
saver.save(sess, FLAGS.model_dir)
if __name__ == '__main__':
lr = MyLinearRegression()
lr.train()
用全连接层实现对手写数学进行识别。
答:
import tensorflow as tf
import os
from tensorflow.examples.tutorials.mnist import input_data
# 1、利用数据,在训练的时候实时提供数据
# mnist手写数字数据在运行时候实时提供给给占位符
tf.app.flags.DEFINE_integer("is_train", 1, "指定是否是训练模型,还是拿数据去预测")
FLAGS = tf.app.flags.FLAGS
def full_connected_mnist():
"""
单层全连接神经网络识别手写数字图片
特征值:[None, 784]
目标值:one_hot编码 [None, 10]
:return:
"""
mnist = input_data.read_data_sets("./mnist_data/", one_hot=True)
# 1、准备数据
# x [None, 784] y_true [None. 10]
with tf.variable_scope("mnist_data"):
x = tf.placeholder(tf.float32, [None, 784])
y_true = tf.placeholder(tf.int32, [None, 10])
# 2、全连接层神经网络计算
# 类别:10个类别 全连接层:10个神经元
# 参数w: [784, 10] b:[10]
# 全连接层神经网络的计算公式:[None, 784] * [784, 10] + [10] = [None, 10]
# 随机初始化权重偏置参数,这些是优化的参数,必须使用变量op去定义
with tf.variable_scope("fc_model"):
weight = tf.Variable(tf.random_normal([784, 10]), name="w")
bias = tf.Variable(tf.random_normal([10]), name="b")
# fc层的计算
# y_predict [None, 10]输出结果,提供给softmax使用
y_predict = tf.matmul(x, weight) + bias
# 3、softmax回归以及交叉熵损失计算
with tf.variable_scope("softmax_crossentropy"):
# labels:真实值 [None, 10] one_hot
# logits:全脸层的输出[None,10]
# 返回每个样本的损失组成的列表
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict))
# 4、梯度下降损失优化
with tf.variable_scope("optimizer"):
# 学习率
train_op = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
# 5、得出每次训练的准确率(通过真实值和预测值进行位置比较,每个样本都比较)
with tf.variable_scope("accuracy"):
equal_list = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1))
accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))
# (2)收集要显示的变量
# 先收集损失和准确率
tf.summary.scalar("losses", loss)
tf.summary.scalar("acc", accuracy)
# 收集权重和偏置
tf.summary.histogram("weightes", weight)
tf.summary.histogram("biaes", bias)
# 初始化变量op
init_op = tf.global_variables_initializer()
# (3)合并所有变量op
merged = tf.summary.merge_all()
# 创建模型保存和加载
saver = tf.train.Saver()
# 开启会话去训练
with tf.Session() as sess:
# 初始化变量
sess.run(init_op)
# (1)创建一个events文件实例
file_writer = tf.summary.FileWriter("./tmp/summary/", graph=sess.graph)
# 加载模型
if os.path.exists("./tmp/modelckpt/checkpoint"):
saver.restore(sess, "./tmp/modelckpt/fc_nn_model")
if FLAGS.is_train == 1:
# 循环步数去训练
for i in range(3000):
# 获取数据,实时提供
# 每步提供50个样本训练
mnist_x, mnist_y = mnist.train.next_batch(50)
# 运行训练op
sess.run(train_op, feed_dict={x: mnist_x, y_true: mnist_y})
print("训练第%d步的准确率为:%f, 损失为:%f " % (i+1,
sess.run(accuracy, feed_dict={x: mnist_x, y_true: mnist_y}),
sess.run(loss, feed_dict={x: mnist_x, y_true: mnist_y})
)
)
# 运行合变量op,写入事件文件当中
summary = sess.run(merged, feed_dict={x: mnist_x, y_true: mnist_y})
file_writer.add_summary(summary, i)
if i % 100 == 0:
saver.save(sess, "./tmp/modelckpt/fc_nn_model")
else:
# 如果不是训练,我们就去进行预测测试集数据
for i in range(100):
# 每次拿一个样本预测
mnist_x, mnist_y = mnist.test.next_batch(1)
print("第%d个样本的真实值为:%d, 模型预测结果为:%d" % (
i+1,
tf.argmax(sess.run(y_true, feed_dict={x: mnist_x, y_true: mnist_y}), 1).eval(),
tf.argmax(sess.run(y_predict, feed_dict={x: mnist_x, y_true: mnist_y}), 1).eval()
)
)
return None
if __name__ == "__main__":
full_connected_mnist()
为什么对图像使用卷积而不只是FC层?
答案应分成两部分:首先,卷积可以保存、编码、使用图像的空间信息。只用FC层的话可能就没有相关空间信息了。其次,卷积神经网络(CNN)某种程度上本身具有平移不变性,因为每个卷积核都充当了它自己的滤波器/特征监测器。
为什么CNN具有平移不变性?
每个卷积核都充当了它自己的滤波器/特征监测器。假设你正在进行目标检测,这个目标处于图片的何处并不重要,因为我们要以滑动窗口的方式,将卷积应用于整个图像。
为什么用CNN分类需要进行最大池化?
CNN中的最大池化可以减少计算量,因为特征图在池化后将会变小。与此同时,因为采取了最大池化,并不会丧失太多图像的语义信息。还有一个理论认为,最大池化有利于使CNN具有更好的平移不变性。
为什么要使用许多小卷积核(如3*3的卷积核),而非少量大卷积核?
有两个原因:首先,同少数大卷积核一样,更多小卷积核也可以得到相同的感受野和空间背景,而且用小卷积核需要的参数更少、计算量更小。其次,使用小卷积核需要更多过滤器,这意味会使用更多的激活函数,因此你的CNN可以得到更具特异性的映射函数。
CNN的卷积核是单层的还是多层的?
卷积核(filter)一般是3D多层的,除了面积参数, 比如3x3之外, 还有厚度参数H(2D的视为厚度1). 还有一个属性是卷积核的个数N。
卷积核的厚度H, 一般等于前层厚度M(输入通道数或feature map数). 特殊情况M > H。
卷积核的个数N, 一般等于后层厚度(后层feature maps数,因为相等所以也用N表示)。
卷积核通常从属于后层,为后层提供了各种查看前层特征的视角,这个视角是自动形成的。
卷积核厚度等于1时为2D卷积,也就是平面对应点分别相乘然后把结果加起来,相当于点积运算.
卷积核厚度大于1时为3D卷积(depth-wise),每片平面分别求2D卷积,然后把每片卷积结果加起来,作为3D卷积结果;1x1卷积属于3D卷积的一个特例(point-wise),有厚度无面积, 直接把每层单个点相乘再相加
overfitting怎么解决?
dropout、regularization、batch normalization early stopping
overfitting就是过拟合, 其直观的表现如下图所示,随着训练过程的进行,模型复杂度增加,在training data上的error渐渐减小,但是在验证集上的error却反而渐渐增大——因为训练出来的网络过拟合了训练集, 对训练集外的数据却不work, 这称之为泛化(generalization)性能不好。
dropout
regularization
batch normalization
early stopping:在训练中多次迭代后发现模型性能没有显著提高就停止训练
数据集扩增:原有数据增加、原有数据加随机噪声、重采样
交叉验证
特征选择/特征降维
创建一个验证集:是最基本的防止过拟合的方法。我们最终训练得到的模型目标是要在验证集上面有好的表现,而不训练集。
CNN最成功的应用是在CV,那为什么NLP和Speech的很多问题也可以用CNN解出来?为什么AlphaGo里也用了CNN?这几个不相关的问题的相似性在哪里?CNN通过什么手段抓住了这个共性?
以上几个不相关问题的相关性在于,都存在局部与整体的关系,由低层次的特征经过组合,组成高层次的特征,并且得到不同特征之间的空间相关性。CNN抓住此共性的手段主要有四个:局部连接/权值共享/池化操作/多层次结构。
局部连接使网络可以提取数据的局部特征;权值共享大大降低了网络的训练难度,一个Filter只提取一个特征,在整个图片(或者语音/文本) 中进行卷积;池化操作与多层次结构一起,实现了数据的降维,将低层次的局部特征组合成为较高层次的特征,从而对整个图片进行表示。
最后小编给大家准备了一些学习资料
日常分享都是一些纯干货,是我学习很多教程筛选出来合适新手快速入门学Python,掌握一门技能让自己变得更好吧!一定要记得粉小可爱我哦!
公众号:学习py最风sao的方式