本章会用到的数据
公开数据:恒瑞医药分钟行情;图像示例使用仓库随附图片,所有读者使用相同文件。
这些数据能做什么:理解图像分类、目标检测和把价格序列转成图像的基本思路。
分析时注意:处理图片、声音和金融数据前,要确认使用许可并保护个人与敏感信息。
判断模型:按时间划分价格样本,并与简单基准比较;结果不构成投资建议。
【课堂核心】2.5 学时学习安排
| 动机与合规先修 |
20 |
| CNN 最小机制 |
35 |
| 形成性检查 |
15 |
| 统一图像示例 |
30 |
| 独立练习 |
35 |
| 反馈与小结 |
15 |
【可选拓展】:货架模板、语音推断、外部论文迁移与未列入表内的页面均为未执行课后材料。
本章学习目标
- 解释边界:区分目标检测、当前图形方向识别与未来收益预测,不把候选信号直接称为 alpha。
- 执行检测:在公开课程图像上运行预训练 Faster R-CNN,报告阈值、IoU、精确率与召回率。
- 验证 CNN:把公开 A 股分钟价格窗口栅格化,按时间最终测试并将微型 CNN 与训练期多数类基线比较。
- 检查失败:根据真实输出解释迁移失败、单类测试窗和未胜基线等条件;声音材料仅作未执行拓展。
本章学习路线
- 先分解另类数据、CNN 与检测指标的必要概念。
- 运行固定
profile.jpg 目标检测并核对 IoU/召回率。
- 运行公开恒瑞医药分钟图像 CNN,并与多数类基线比较。
- 用形成性检查和课后题解释结果不理想时如何解释,再完成总结与参考文献。
可选阅读不影响本章练习;先完成公开图片的目标检测和分钟行情图的时间顺序预测。
检验候选信号:从信息到风险调整后收益
在金融研究中,阿尔法(\(\alpha\))是相对于明确基准或风险模型的异常收益/回归截距,不是“超过市场平均回报”的同义词。报告 alpha 必须写明基准模型、估计窗口、标准误或置信区间,并扣除交易成本与可实施约束。
另类数据只可能提供候选预测信息。它是否产生未来风险调整后异常收益,必须在点时样本上相对事先确定基准做样本外检验;信息增量不会必然转化为已实现 alpha。
候选数据先过合规四问
- 来源与授权是否合法?
- 是否含重大非公开信息(MNPI)?
- 是否含个人信息或敏感个人信息?
- 研究与交易使用是否符合许可、内幕交易、数据保护与要求限制?
合法专有数据(自建、授权采购或公开数据增值处理)不等于内幕信息;MNPI 也不会因购买或模型加工而变成可交易信息。
另类数据:候选测量的新来源
答案在于:从传统财报、行情等常规来源之外构造候选测量。
- 定义边界:另类数据以来源或采集方式的“非传统性”为界。
- 来源类型:公开信息、获授权的专有/交易/运营数据或传感器数据。
- 不能推出:公开不自动等于可用;付费或专有也不自动等于可交易。
- 验证清单:授权、隐私与 MNPI、点时构造、误差、基线、成本和样本外增量。
文字之外:形成待验证的候选测量
视觉与听觉数据提供额外输入;是否及时、有效或具有增量,必须用点时构造、人工真值、基线和最终测试指标验证。
图像数据
- 卫星与无人机影像
- 停车场车辆 → 零售候选代理
- 工厂烟雾 → 工业活动候选代理
- 油轮动向 → 物流或供需候选代理
声音数据
- 高管采访与业绩会议
- 语音转写形成可检查文本
- 音高、语速等只形成情绪或标签假设
- 不得由声学特征直接断言欺诈
机器学习:解锁另类数据的钥匙
这些图像、声音数据是非结构化的,传统计量经济学方法难以处理。
卷积神经网络 (CNN) 可从原始像素学习任务相关表示;是否有意义须用人工真值、最终测试指标和基线验证,模型不会自动产生经济信号。
图像中蕴含的经济信号
一张图片胜过千言万语,在金融领域尤其如此。
假设链:卫星图像能否形成零售候选特征?
- 合规输入:在授权、隐私与点时条件下取得影像并确定覆盖范围。
- 测量检查:用人工真值评估车辆或库存计数误差、缺失与区域覆盖。
- 候选构造:把通过检查的计数按事先确定频率转为候选特征,不预称领先指标。
- 增量验证:只在最终测试期相对财报与季节性基线检验销售或客流增量,并计入延迟、缺失、成本与合规;未通过时不触发交易结论。
另一个经典应用:库存清点
- 候选测量: 获授权影像可用于估计库存,但必须以人工真值报告计数误差;不能仅凭影像断言官方库存准确或销售状况。
- 自动盘点: 机器学习可辅助识别和计数;覆盖、漂移、成本与样本外增量决定其是否可用。
本章案例:识别公开课程图片中的人物
课程图片与代码一起公开。无论是作者还是读者,代码都会从同一个地址取得 profile.jpg,然后在当前 QMD 中运行目标检测并核对结果。
核心工具:卷积神经网络 (CNN)
要让机器理解图片,我们主要使用卷积神经网络 (Convolutional Neural Network, CNN)。
在深入其内部结构之前,我们先建立一个直观的认识:计算机如何“看待”图像?
计算机眼中的图像:像素与通道
- 像素 (Pixel): 图像的基本单位,每个像素代表图像中一个点。
- 通道 (Channel):
- 灰度图: 只有一个通道,每个像素值代表亮度 (0=黑, 255=白)。
- 彩色图 (RGB): 有三个通道(红、绿、蓝),每个像素由三个数值组成,代表三种颜色的强度。
图像的矩阵表示
对于计算机,一张灰度图就是一个由数字组成的矩阵。每个数字代表一个像素的亮度。
例如,我们可以用 5x5 的矩阵,清晰地表示字母 ‘O’ 和 ‘X’。
CNN 的三大核心构建模块
最简单的CNN模型,可以看作是由三个核心部件按顺序组装起来的“信息处理流水线”。
模块一:卷积层 (Convolutional Layer)
- 目标:从原始图片中检测出基础的特征 (Features)。
- 什么是特征? 图像的局部模式,例如边缘、角落、纹理、颜色块等。
卷积层的工具:卷积核 (Kernel)
卷积核 (或称滤波器 Filter) 是一个很小的矩阵 (例如 3x3),它被设计用来识别一种特定的微观模式。
- 卷积层的工作,就是让这个小的卷积核,在大的输入图像上滑动 (Slide),并进行计算。
- 它的参数(矩阵中的数值)通过模型训练不断学习和优化,最终变得能够识别有意义的特征。
图解卷积运算
下图展示了一个 5x5 输入图像和一个 2x2 卷积核。卷积核从左上角开始,在输入图像上滑动。
卷积运算步骤
在每个位置,执行元素级相乘 (element-wise product),然后将所有结果求和。
位置 1 (左上角):
\[
\begin{aligned}
s_{1,1}&=0\times1+1\times0\\
&\phantom{=}+1\times0+0\times1=0
\end{aligned}
\]
滑动与重复
卷积核向右滑动一个单位 (步长 Stride = 1),覆盖新的区域,并重复运算。
位置 2: (1×1) + (1×0) + (0×0) + (0×1) = 1
卷积层的产物:局部加权响应
当卷积核遍历完整个输入图像后,会得到一个新的、尺寸稍小的矩阵,这就是特征图 (Feature Map)。
- 卷积输出是局部加权和(实践中常为互相关响应);正负号和大小依赖核、偏置与输入尺度。
- 只有核被训练或定义为某类模式探测器并经过相应激活后,较大激活才可条件性解释为更强响应。
一个卷积层,多个卷积核
一个卷积核只能检测一种特征。为了识别多种特征(横线、竖线、曲线等),一个卷积层通常包含多个不同的卷积核。
- 每一个卷积核都会生成一个自己独立的特征图。
- 因此,一个卷积层的输出是一叠(多个)特征图,共同描绘了原始图像的多种基础特征。
重要细节:激活函数 (Activation)
在生成特征图后,通常会使用一个激活函数,最常用的是 ReLU (Rectified Linear Unit)。
\[ \large{ReLU(x) = \max(0, x)} \]
- 作用: 它会把特征图里所有的负数值都变为0,保留正数值。
- 机制边界:ReLU 逐元素截断负激活并引入分段线性;激活值的正负号不等于语义上的匹配或不匹配。
【课堂核心】填充(Padding)与步长(Stride)
\[H_{out}=\left\lfloor\frac{H+2P_h-D_h(K_h-1)-1}{S_h}\right\rfloor+1\]
\(W_{out}\) 同理。Padding 用于控制空间输出尺寸与边缘覆盖;只有特定 kernel、stride、dilation 与 padding 组合(例如 stride=1 的适当 same padding)才保持尺寸。
- 填充 (Padding)
- 在输入图像的边缘添加额外的像素(通常是0)。
- 目的:控制输出空间尺寸与边缘覆盖;是否同尺寸由公式中的 kernel、stride、dilation 与 padding 共同决定。
- 步长 (Stride)
- 卷积核每次滑动的像素数。
- 目的: 步长大于1可以减小输出特征图的尺寸,实现降采样。
模块二:池化层 (Pooling Layer)
- 目标: 对特征图进行降采样 (Downsampling)。
- 可能作用:减少后续计算量;在 kernel 与 stride 条件合适时,可能提供有限的局部平移容忍。
- 边界:池化不保证平移不变性或目标域稳健性,这些性质必须用目标域扰动与最终测试指标验证。
局部平移容忍是待验证性质
下图只示意“相邻位置可能得到相近聚合值”的候选机制;位移幅度、池化窗口、stride 与上游特征都会改变结果,不能据此宣称不变性。
池化的操作过程
与卷积类似,池化窗口(常见为 2×2)按指定 stride 在特征图上滑动并聚合数值。窗口是否重叠由 kernel 与 stride 共同决定:本页示例使用 kernel=2, stride=2,因此不重叠。
池化的两种主要方法
- 最大池化 (Max Pooling): 取池化窗口内所有元素的最大值。最常用。
- 平均池化 (Average Pooling): 取池化窗口内所有元素的平均值。
直观理解: 最大池化可以看作是“只保留每个小区域内最显著的特征信号”。
最大池化实例
对之前的特征图采用最大池化: max(0,1,1,0) = 1 max(1,2,0,1) = 2 max(1,0,2,1) = 2 max(0,1,1,0) = 1
最终得到一个 2x2 的池化后矩阵:
尺寸从 4x4 降为 2x2,输出空间单元(本例也即张量元素)减少 75%。后续计算量与内存节省取决于网络结构、通道数和实现;池化本身还需要窗口内比较,不能据此断言整网计算量减少 75%。
模块三:全连接层 (Fully Connected Layer)
目标: 在经过多轮“卷积-池化”提取出高级特征后,做出最终的分类预测。
- 输入: 最后的池化层输出被“压平”(Flatten) 成一个长向量。
- 结构: 本质上就是一个标准的前馈神经网络。
- 输出: 通常先输出 logits \(z\);二分类经 sigmoid、多分类经 softmax 才得到模型概率,且仍需在独立验证集检查校准。
CNN 的完整训练流程
训练过程是一个不断迭代优化的循环。
真实世界的复杂模型:AlexNet
实际应用的CNN模型会堆叠多个卷积层和池化层,以学习从低级到高级的层级化特征。
- AlexNet (2012): 深度学习领域的项目阶段,证明了深层CNN在复杂图像识别任务上的巨大潜力。
挑战:识别图像中的多个物体
在金融应用中,我们往往需要识别和计数多个物体。例如,清点整个货架的库存,而不是为每件商品单独拍照。
这需要更高级的模型,能够同时完成物体定位 (Localization) 和 分类 (Classification)。
两阶段与单阶段检测器:概念对比
R-CNN(Region-based CNN)
两阶段思路:
- 区域提议: 先用算法找出可能包含物体的候选区域。
- 分类与框回归:经典 R-CNN 逐区域运行 CNN;Faster R-CNN 等后续两阶段模型先共享特征,再处理候选区域。
条件性特点:速度与精度取决于具体版本、输入尺寸、硬件、精度/召回指标及延迟口径,不能把所有 R-CNN 系列概括为固定慢速。
YOLO(You Only Look Once)
一步法:
- 将物体定位和识别合并到一个单一的神经网络中完成。
条件性特点:单阶段结构可减少逐区域处理,但是否满足实时要求取决于 YOLO 版本、输入尺寸、硬件、精度模式、批量与延迟口径;必须在目标域以同一指标评估。
检查:尺寸与概率口径
独立作答 2 分钟:
- 给定 \(H=5,K=3,P=1,S=2,D=1\),计算 \(H_{out}\)。
- 全连接层给出三个 logits,尚未经过 softmax,能否称为概率?
反馈:先算几何,再做概率变换
- 几何结果:\(H_{out}=3\)。
- 概率边界:logits 尚未经过 softmax,不能称为概率。
- 订正路径:尺寸算错回看 相关内容;概率概念错回看“模块三:全连接层”。
第二部分:可执行核心——固定图像目标检测
课程的 profile.jpg 可从课程网站直接下载。本练习用轻量 Faster R-CNN 执行目标检测,人工标注只包含画面中的一名人物,树木等其他内容不进入评分。
代码
from pathlib import Path
from urllib.request import urlretrieve # 复用本章隐藏设置单元安装的浏览器标识下载器
import torch # 运行预训练目标检测推理
import numpy as np # 计算边界框交并比
import pandas as pd # 整理原始预测检查表
from PIL import Image # 读取固定 RGB 图像
from torchvision.models.detection import FasterRCNN_MobileNet_V3_Large_320_FPN_Weights, fasterrcnn_mobilenet_v3_large_320_fpn # 确定轻量 Faster R-CNN 架构与权重枚举
# 优先使用仓库根目录随附图片,不存在时再复用章节缓存或公开下载。
detection_image_path = next((candidate_path for candidate_path in [Path('../profile.jpg'), Path('data/course/profile.jpg')] if candidate_path.exists()), Path('data/course/profile.jpg'))
if not detection_image_path.exists():
detection_image_path.parent.mkdir(parents=True, exist_ok=True)
urlretrieve('https://qiufei.site/web-slide-bigfinance/profile.jpg', detection_image_path)
detection_image = Image.open(detection_image_path).convert('RGB') # 统一为模型需要的 RGB 图像
detection_weights = FasterRCNN_MobileNet_V3_Large_320_FPN_Weights.DEFAULT # 使用 torchvision 明确版本的默认权重
detection_model = fasterrcnn_mobilenet_v3_large_320_fpn(weights=detection_weights).eval() # 加载预训练检测器并关闭训练态随机行为
detection_tensor = detection_weights.transforms()(detection_image) # 使用权重绑定的官方预处理说明
with torch.no_grad(): # 推理阶段不保留梯度图以控制内存
detection_output = detection_model([detection_tensor])[0] # 对单图执行真实 Faster R-CNN 推理
print({'输入': detection_image_path.name, '模型权重': str(detection_weights), '识别到的候选框数': len(detection_output['boxes'])})
{'输入': 'profile.jpg', '模型权重': 'FasterRCNN_MobileNet_V3_Large_320_FPN_Weights.COCO_V1', '识别到的候选框数': 6}
可执行检测检查:IoU、精确率与召回率
代码
manual_person_box = np.array([390.0, 490.0, 570.0, 700.0]) # 确定画面中人物的人工边界框真值
detection_threshold = 0.50 # 事先确定显示与评分阈值
detection_scores = detection_output['scores'].cpu().numpy() # 取得原始置信度序列
detection_labels = detection_output['labels'].cpu().numpy() # 取得原始 COCO 类别编号
detection_boxes = detection_output['boxes'].cpu().numpy() # 取得原始预测框坐标
person_mask = (detection_labels == 1) & (detection_scores >= detection_threshold) # 只评估阈值以上 person 检测
person_boxes = detection_boxes[person_mask] # 收集全部候选人物框
def calculate_box_iou(predicted_box, truth_box): # 计算单个预测框与人工真值的交并比
intersection_min = np.maximum(predicted_box[:2], truth_box[:2]) # 定位交集左上角
intersection_max = np.minimum(predicted_box[2:], truth_box[2:]) # 定位交集右下角
intersection_area = np.prod(np.clip(intersection_max - intersection_min, 0, None)) # 计算非负交集面积
predicted_area = np.prod(predicted_box[2:] - predicted_box[:2]) # 计算预测框面积
truth_area = np.prod(truth_box[2:] - truth_box[:2]) # 计算人工框面积
return float(intersection_area / (predicted_area + truth_area - intersection_area)) # 返回 IoU 供阈值判定
person_ious = [calculate_box_iou(person_box, manual_person_box) for person_box in person_boxes] # 检查全部人物候选
true_positive_count = int(any(person_iou >= 0.5 for person_iou in person_ious)) # 以 IoU 不低于 0.5 定义命中
detection_precision = true_positive_count / max(len(person_boxes), 1) # 报告阈值后人物检测精确率
detection_recall = float(true_positive_count) # 单一人工人物真值下召回率等于命中指示
raw_detection_table = pd.DataFrame({'label_id': detection_labels[:5], 'score': detection_scores[:5], 'x1': detection_boxes[:5, 0], 'y1': detection_boxes[:5, 1], 'x2': detection_boxes[:5, 2], 'y2': detection_boxes[:5, 3]}) # 保留前五条原始预测
print({'阈值': detection_threshold, 'person候选': len(person_boxes), '最大IoU': max(person_ious, default=0.0), '精确率': detection_precision, '召回率': detection_recall}) # 输出完整任务指标
display(raw_detection_table.round(3)) # 展示原始标签、分数与边界框
{'阈值': 0.5, 'person候选': 0, '最大IoU': 0.0, '精确率': 0.0, '召回率': 0.0}
- 必须保留的失败:权重无法取得、输入哈希变化、输出字段不全或人物召回率为 0。
- 禁止替代:不得用占位结果覆盖失败。
- 练习范围:只验证固定图像上的 COCO 迁移检测。
- 不能推出:中国零售商品识别能力或金融预测证据。
传统智慧:技术分析
长久以来,金融从业者都试图通过分析股市回报的图表 (Charts) 来预测未来走势,这被称为技术分析。
- 核心思想: 历史价格的模式会重复出现。
- 经典模式: 例如头肩顶、双底、金叉等。
新兴趋势:让CNN“看懂”股票图表
一个革命性的想法:我们能否将股票价格走势图本身当作一张图片,然后用CNN来分析它,从而预测未来的股票回报?
核心论文:Jiang, Kelly, and Xiu 的 “(Re-)Imag(in)ing Price Trends” (Jiang 等 2023年)。论文结果来自其特定市场、样本与图像构造,不自动外推到 A 股。
J.K.X. (2023) 的核心思想
- 数据转换: 将每只股票过去一段时间(如一年)的价格序列,渲染成一张标准化的价格走势图图片。
- 模型训练:
- 输入 (X): 股票价格图(.png 文件)。
- 标签 (Y): 该股票未来一个月的回报。
- 任务: 训练一个深度CNN模型,学习从“图的模式”到“未来回报”的映射关系。
J.K.X. (2023) 的样本内发现与迁移边界
- 市场迁移
- 可检验启示
- 图像编码值得在公开 A 股数据上按点时切分、朴素基线和成本后收益重新检验;未经复算不称为新 alpha 来源。
声音:另一个价值洼地
除了图像,声音——尤其是人类的语音——也包含了丰富的信息。处理声音数据主要有两条路径。
路径一:语音转文字 (Speech-to-Text)
- 核心任务: 将语音信息转化为文字信息。
- 候选接口: 确定版本的 Whisper 或其他 open-weight ASR;须登记版本、许可、检查日,并在中文金融域报告 WER/CER、说话人和噪声分层结果,未评测不作排名。
- 金融应用: 自动转录公司的业绩发布会、分析师电话会议、高管访谈等,将其转化为文本,然后就可以用我们之前学过的NLP技术进行情绪分析、主题建模等。
路径二:把声音情绪当作待检验测量假设
我们说话时,传递的不仅仅是文字内容,还有情绪。
- 核心任务: 从语音的声学特征(如音高、语速、音量、音色)中,直接分析说话者的情绪状态。
- 金融应用假设: 声学特征能否预测事先确定标签,必须给出来源、标签定义与外部验证。
- 混杂与审核: 语言、文化、性别、口音、录音设备、转录质量与说话场景均可能混杂;需说话人外部切分、校准、公平性与隐私审核。
声音的可视化:声谱图
如何让一个为图像设计的CNN模型来处理声音?
答案是:将一维的声音信号转换为二维的声谱图 (Spectrogram)。
声谱图就像是声音的“指纹”,CNN可以像分析普通图片一样,从声谱图中学习和识别声音模式。
公开中国数据任务:A 股分钟价格图像
- 固定输入:公开
stock/minbar/600276.XSHG.h5 的 data 数据集。
- 图像构造:将固定 60 分钟窗口栅格化为图像。
- 验证设计:按时间保留最后 20% 为最终测试,训练微型 CNN,并与多数类基线比较。
- 提交输出:混淆矩阵、窗口流量与结果不理想时的解释。
- 结论边界:“末价高于初价”只验证图像流程,不是未来收益或 alpha。
练习:先完成再查看答案:图像流程作业结果
- 提交内容:文件/数据集/字段、切窗规则、训练—测试边界、CNN 与基线指标、非 alpha 声明。
- 重做条件:缺少时间最终测试,或把当前窗口方向写成预测信号。
- 完成后:再查看参考答案。
参考答案(1/4):固定分钟切片
代码
from pathlib import Path # 管理公开 A 股分钟数据路径
from urllib.request import urlretrieve # 复用本章已安装的浏览器标识下载器
import h5py # 对非 Pandas HDF5 数据集做选择性切片
import matplotlib.pyplot as plt # 将真实价格序列渲染为图像输入
# 按 Linux 共享数据、Windows 共享数据、项目缓存的顺序选择分钟行情文件。
minute_path = next((candidate_path for candidate_path in [Path('/home/ubuntu/r2_data_mount/data/stock/minbar/600276.XSHG.h5'), Path('C:/qiufei/data/stock/minbar/600276.XSHG.h5'), Path('data/course/600276.XSHG.h5')] if candidate_path.exists()), Path('data/course/600276.XSHG.h5'))
if not minute_path.exists():
minute_path.parent.mkdir(parents=True, exist_ok=True)
urlretrieve('https://assets.qiufei.site/data/stock/minbar/600276.XSHG.h5', minute_path)
with h5py.File(minute_path, 'r') as minute_store: # 只读打开公开 HDF5 文件
minute_count = minute_store['data'].shape[0] # 获取总分钟记录数而不全量载入
minute_slice = minute_store['data'][minute_count - 240:minute_count] # 只读取最后 240 条固定切片
minute_close = minute_slice['close'] # 提取绘图所需收盘价字段
fig, axis = plt.subplots(figsize=(7, 3)) # 创建适合 1280×720 投影的紧凑画布
axis.plot(minute_close, color='#174F87', linewidth=1.5) # 绘制真实公开分钟价格路径
axis.set(title='恒瑞医药:固定 240 分钟切片', xlabel='分钟顺序', ylabel='价格') # 标注输入对象与坐标含义
plt.tight_layout() # 收紧边界避免图形压住页脚
plt.show() # 输出单幅可检查的图像输入
print({'文件': minute_path.name, '数据集': 'data', '总记录': minute_count, '切片记录': len(minute_slice)}) # 输出数据来源与样本数量变化
{'文件': '600276.XSHG.h5', '数据集': 'data', '总记录': 1227600, '切片记录': 240}
边界:上图固定输入来自公开真实行情。下面把多个历史窗口栅格化,训练一个固定版本的微型 CNN 识别“本窗口收盘价终点是否高于起点”。这是人工可核对的当前图形方向标签,不是未来收益标签,也不是 alpha 证据。
完整验证(1/3):固定窗口、图像与人工真值规则
代码
import numpy as np # 将真实分钟价格窗口栅格化为灰度图
import pandas as pd # 形成最终测试期人工检查表
import torch # 用固定PyTorch版本训练微型卷积网络
from sklearn.metrics import balanced_accuracy_score, confusion_matrix # 比较CNN与多数类基线
window_length = 60 # 固定每幅图包含60分钟
window_count = min(240, minute_count // window_length) # 使用数据版本末端最多240个不重叠窗口
with h5py.File(minute_path, 'r') as minute_store: # 再次只读打开固定公开数据版本
chart_slice = minute_store['data'][minute_count - window_count * window_length:minute_count] # 选择性读取建模区间
price_windows = chart_slice['close'].reshape(window_count, window_length) # 按时间顺序切成固定窗口
price_minimums = price_windows.min(axis=1, keepdims=True) # 计算每窗绘图下界
price_ranges = np.maximum(price_windows.max(axis=1, keepdims=True) - price_minimums, 1e-8) # 防止平价窗口除零
pixel_rows = np.rint((1 - (price_windows - price_minimums) / price_ranges) * 15).astype(int) # 映射到16行像素坐标
chart_images = np.zeros((window_count, 16, window_length), dtype=np.float32) # 创建固定灰度图张量
chart_images[np.arange(window_count)[:, None], pixel_rows, np.arange(window_length)[None, :]] = 1.0 # 逐分钟点亮价格比较结果
direction_labels = (price_windows[:, -1] > price_windows[:, 0]).astype(np.int64) # 以终点高于起点定义人工可核对标签
split_position = int(window_count * 0.8) # 按时间最终测试最后20%图像
print({'PyTorch版本': torch.__version__, '文件': minute_path.name, '窗口数': window_count, '训练/测试': (split_position, window_count - split_position), '人工真值': '末价>初价'}) # 输出输入与标签说明
{'PyTorch版本': '2.11.0+cpu', '文件': '600276.XSHG.h5', '窗口数': 240, '训练/测试': (192, 48), '人工真值': '末价>初价'}
完整验证(2/3):固定微型 CNN
代码
import torch.nn as nn # 组合卷积、池化与分类层
torch.manual_seed(2026) # 固定权重初始化与训练顺序
class PriceChartCNN(nn.Module): # 定义仅用于当前方向识别任务的微型CNN
def __init__(self): # 注册固定网络结构
super().__init__() # 初始化PyTorch模块状态
self.features = nn.Sequential(nn.Conv2d(1, 8, 3, padding=1), nn.ReLU(), nn.MaxPool2d(2), nn.Conv2d(8, 12, 3, padding=1), nn.ReLU(), nn.AdaptiveAvgPool2d((1, 1))) # 提取局部线段特征
self.classifier = nn.Linear(12, 2) # 输出上涨/非上涨两类得分
def forward(self, chart_batch): # 定义图像到类别得分的前向路径
return self.classifier(self.features(chart_batch).flatten(1)) # 汇总卷积特征并分类
chart_tensor = torch.tensor(chart_images[:, None, :, :]) # 增加单通道维度
label_tensor = torch.tensor(direction_labels) # 转换人工真值标签
chart_model = PriceChartCNN() # 从固定种子初始化网络
chart_optimizer = torch.optim.Adam(chart_model.parameters(), lr=0.01) # 确定课堂最小训练配置
chart_loss = nn.CrossEntropyLoss() # 使用二分类交叉熵
for training_epoch in range(30): # 使用短预算完成最小验证
chart_optimizer.zero_grad() # 清除上一轮梯度
training_scores = chart_model(chart_tensor[:split_position]) # 只读取较早图像训练
training_objective = chart_loss(training_scores, label_tensor[:split_position]) # 计算训练期分类损失
training_objective.backward() # 反向传播卷积网络梯度
chart_optimizer.step() # 更新当前网络参数
完整验证(3/3):预测、基线与人工检查
代码
chart_model.eval() # 确定网络进入最终测试评估模式
with torch.no_grad(): # 测试阶段不更新参数
sealed_chart_predictions = chart_model(chart_tensor[split_position:]).argmax(1).numpy() # 生成时间较晚图像预测
sealed_chart_truth = direction_labels[split_position:] # 读取最终测试期人工真值
majority_chart_label = int(np.bincount(direction_labels[:split_position]).argmax()) # 只由训练期确定多数类
majority_chart_predictions = np.repeat(majority_chart_label, len(sealed_chart_truth)) # 建立同窗朴素基线
cnn_balanced_accuracy = balanced_accuracy_score(sealed_chart_truth, sealed_chart_predictions) # 计算CNN平衡准确率
baseline_balanced_accuracy = balanced_accuracy_score(sealed_chart_truth, majority_chart_predictions) # 计算多数类平衡准确率
manual_audit = pd.DataFrame({'窗口': np.arange(split_position, min(split_position + 5, window_count)), '初价': price_windows[split_position:split_position + 5, 0], '末价': price_windows[split_position:split_position + 5, -1], '人工真值': sealed_chart_truth[:5], 'CNN预测': sealed_chart_predictions[:5]}) # 列出五窗供人眼核对标签
print({'CNN平衡准确率': cnn_balanced_accuracy, '多数类平衡准确率': baseline_balanced_accuracy, '混淆矩阵': confusion_matrix(sealed_chart_truth, sealed_chart_predictions).tolist()}) # 报告同窗任务指标
display(manual_audit.round(3)) # 展示预测与可手算真值
{'CNN平衡准确率': 0.5, '多数类平衡准确率': 0.5, '混淆矩阵': [[30, 0], [18, 0]]}
形成性检查
- 人物检测召回率为 0、CNN 未胜多数类或测试期只有一个类别,都必须保留失败结果。
- 分别说明失败环节,以及为何两项任务都不能证明未来回报或成本后 alpha。
反馈
- 检测失败:定位输入域、类别集合、阈值或权重迁移。
- CNN 未胜基线:当前图像化与微型网络没有增量分类证据。
- 概念错误:把当前窗口方向写成未来收益预测,或删除失败结果。
阶段小结:另类数据处理的未来
今天,我们打开了一扇通往新世界的大门。我们学习了:
- 另类数据的价值
- 它提供候选增量信号;是否改善预测或形成成本后风险调整收益,必须由样本外证据决定。
- CNN的强大
- CNN 是图像候选测量工具之一;当前证据仅支持固定图像检测检查和同窗方向分类,不支持未来收益预测。
- 声音信息的潜力
- 转录或声学特征可形成待验证测量;价值取决于标签有效性、样本外增量、成本、隐私与合规。
- 核心竞争力
- 非结构化数据流程只有在授权、点时构造、基线、稳定性与成本后增量同时通过时,才可能形成可用能力。
课后思考与习题
- 检测失败判读:固定图像在阈值 0.5 下
person 候选为 0、召回率为 0。说明这项结果能与不能支持什么,并提出一个不得改动测试真值的下一步。
- 基线比较:公开分钟图像 CNN 的最终测试平衡准确率为 0.5,与多数类基线相同。写出增量价值结论,并说明为什么不能把当前窗口方向识别解释为未来收益预测。
- 迁移设计:若要把检测器迁移到获授权的中国门店货架图像,列出输入授权、人工真值、类别集合、阈值选择、最终测试划分和失败报告六项说明。
课后习题参考答案与评分标准
1. 检测失败
- 阈值 0.5 下没有人物命中证据,必须保留失败。
- 这不证明图中无人,也不证明检测器普遍无效。
- 可在独立验证集预先定阈值或做目标域微调;不得看过测试真值后改阈值并覆盖原结果。
2. 基线比较
- CNN 未胜同窗多数类,当前样本与结构没有证明增量分类价值。
- 标签只描述同一窗口的方向,不含未来目标,不能外推为收益预测或 alpha。
3. 迁移评分
- 输入授权与哈希 20%,人工框/类别真值 20%,开发集定阈值 15%。
- 时间或对象最终测试 15%,IoU/精确率/召回率 15%,失败与隐私边界 15%。
- 任一缺项或用占位结果替代失败,均需重做。
本章小结
本章先用公开课程图片练习 Faster R-CNN 与 IoU,再用公开的恒瑞医药分钟行情练习按时间顺序划分训练与最终测试。两项练习都保留简单基线;图像识别结果不能直接外推为未来收益或风险调整 alpha。
- 学完后应能:能复算输出尺寸、区分 logits/概率,并检查最终测试期模型与基线。
- 选择条件:授权、MNPI、隐私、标签、切分与阈值说明必须同时成立。
- 未建立:声音示意和当前窗口图像都不证明情绪、未来收益或 alpha。
- 下一站:进入第 18 章,把大体量行情任务改写为 Dask 分区、惰性执行、运行时间和内存与同口径归约检查。