有一次, 我妈妈在电话中问我, 现在国内工作的人都一直在学习, 你们在美国, 应该更需要学习, 怎么只听见你在打桥牌, 从来没听见你在学东西. 老太太说的是对的, 估计老人家已经憋好久了.我说物理中有近代物理和经典物理, 前者可说是日新月异, 真是三天不学习, 赶不上刘少奇. 即使你不搞研究, 只在大学里教书, 不学新东西也很难混日子. 至于那些前沿学科, 电脑, 工程, 医学, 生物等, 就更不用说了. 但这经典物理, 却是很少再有新东西了.至于金融行业, 我也把它分为现代金融和经典金融. 你儿子运气好, 做的正是经典金融. 工作十几年, 确实一直在吃老本. 在可以预见的将来, 吃到退休应无大问题. 但新东西多少还是学了一些, 在较高的层次上, 有C++, VBA, Oracle 等等. 这些是我原来完全不懂的. 前一篇《不厌其”烦”》也是一例,但属于较低层次, 说出来是懂的, 但自己就是没想到 . 我以前的研究是做严格解的, 相对而言, 数值计算不是我的强项, 所以进公司后学的新东西, 计算方面占很大比例.这篇是另一个例子, 就是用分段线性函数 (Piecewise Linear Function) 来近似模型中的曲线. 尽管程序看上去繁多了, 但CPU节约很多, 建立模型也比以前容易得多, 好控制, 修改也方便. 如果曲线变化较大, 就多用几段, 反之就少用几段. 每段的起始点和斜率由回归或经验决定.这样尽管模型的一阶导数不再连续, 但可以很方便地使曲线更接近实际数据. 我最开始看到的一段关于分段线性函数的程序, 看上去很简洁, 实际上极不合理. 假定函数小于某值(X1)是个常数, 大于某值(XN)是最后两点的线性延伸. 那程序是这样的. 凡涉及程序, 我只写逻辑, 不牵涉具体语言. 这逻辑对C, Fortran, SAS, Pasco, … 应该都适用. Y = Y1 K = 1 if X > XK and X < XN then Y = YK + (YK+1 – YK) (X – XK) / (XK+1 – XK) K = K + 1 end 这段程序的循环中, 真正有用的计算只有一次, 既最后一次. 如果运气好, 这无用循环只走了一两次, 如果运气不好就要走遍N-1 次了. 我重写如下. if X < X1 then Y = Y1 else if X > XN-1 then Y = YN-1 + (YN – YN-1) (X – XN-1) / (XN – XN-1) else do i = 1 to N – 2 if Xi < X <= Xi+1 then Y = Yi + (Yi+1 – Yi) (X – Xi) / (Xi+1 – Xi) end 我测试了 N = 8 的 1,000,000 个随机数, 新旧程序的时间比大约是 4:5. 我还注意到, 这(Yi+1 – Yi) / (Xi+1 – Xi) 实际上是个常数, 其中还有一次昂贵的除法. 所以这程序还可进一步优化. 在整个计算之前, 我们先算一下这 N – 1 个常数. Zi = (Yi+1 – Yi) / (Xi+1 – Xi), i = 1, 2, 3, …, N – 1 然后前面这优化过的程序就可写成 if X < X1 then Y = Y1 else if X > XN-1 then Y = ZN-1 (X – XN-1) else do i = 1 to N – 2 if Xi < X <= Xi+1 then Y = Yi + Zi (X – Xi) end 原来的程序中, 除了占时极少的判别语句及左边边界的赋值语句, 每次要 5 次加法(加减乘 CPU 相同), 1 次除法, 共 7.3 次加法. 现在只用 3 次加法. 初始计算的 CPU 是可以忽略的. 和最初的”简洁”程序相比, CPU 只有 33%. 如今, 计算机硬盘越来越大, 速度越来越快, 大家听到的都是 Hard disk is cheap. 但在我们公司, 数据文件动辄40-50G, 同事们很快发现, 我做的优化确实有重大实际意义, 节约的时间可对模型进行更多的测试和改进. 尤其当项目很紧急时, 这些优化的意义就不是CPU能够衡量了. 对大部分工业界的朋友, 这篇中的雕虫小技并无太大实际意义. |