<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>OnionSec</title>
    <link>https://wechat2rss.xlab.app/feed/71d830505c0eb2d4e2627dbf1dfc2b2971bc240b.xml</link>
    <description>恶意软件研究与分析，机器学习接触者；赛博郎中；不做生活的旁观者；&#xA;(wechat feed made by @ttttmr https://wechat2rss.xlab.app)</description>
    <managingEditor> (OnionSec)</managingEditor>
    <image>
      <url>https://wx.qlogo.cn/mmhead/Q3auHgzwzM5rTIy4VqIdE8nWuhb03D0ndDg8iaicGibvTK2AMicID9e7Wg/0</url>
      <title>OnionSec</title>
      <link>https://wechat2rss.xlab.app/feed/71d830505c0eb2d4e2627dbf1dfc2b2971bc240b.xml</link>
    </image>
    <item>
      <title>不一样的体会</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485767&amp;idx=1&amp;sn=c881554cf7c1159380771a0c793da590</link>
      <description></description>
      <content:encoded><![CDATA[<p>原创 <span>jishuzhain</span> <span>2026-05-17 17:50</span> <span style="display: inline-block;">广东</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=da69051d&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FfNR1ygo0YuVzoek35RNUNCJqz5icwdAP32rxjrr6GTNx6GbhuEUH6ZbHwFp9dDfQiaNXBzM1EtjcibJwIGCxicBpk2OjnYcok6e6uFPjbOZWc4Y%2F0%3Fwx_fmt%3Djpeg"/></p>
  
  <p style="line-height: 2em;margin-bottom: 32px;"><span style="font-size: 16px;letter-spacing: 0.034em;">最近两个月待在深圳，做了很多不一样的事情，感觉上像过了半年。以下是我的个人生活经历体会，记录一下，说不定几年后看看还挺有感触。<br/>前一个月主要是投入面试活动，有面试就做面试准备，没有就正常生活学习一下，一方面等待机会，另一方面主动搜索一下信息看看有没有合适的岗位。不过这种生活久了确实会无聊，因为人会空虚会陷入东想西想的状态，不过无聊不是坏事，从一个忙碌的阶段转换到时间富裕阶段，心理与情绪和精神层面必然需要经历的一个阶段。<br/>对国内的休息与负罪感的体会比较深刻，只有到周末才感觉到休息与负罪感的天平有了波动，因为这个时间段负责招聘的人也休息了，业务部门的人也休息了，不会筛选简历或者投入招聘面试。工作日的时候呢就会偶尔想到这会是不是应该去上班？偶尔情绪会低落几分钟，不过很快就消失了。像比如今天一起来就感觉到情绪低落，感觉到无聊了。无聊就无聊吧，不在意情绪，不关注情绪就还好，这个方法也是听从张朝阳以及与前同事大佬聊天时获得的经验。“随便它，不在意情绪”。<br/>投递简历的时候发生了一些事情，通过第一次面试获得了一些信息，主要是给企业推荐过去的简历里，另一个是深信服在职的安全运营专家，不过这两份简历，我的通过了，对方没有通过。说实话我有点吃惊，不过想了一下我的简历都是实打实地经历和成果，没有弄虚作假，虽然我也知道现在劳动力就业市场里总归是有造假的简历，但诚实还好，说明我还是有点竞争力的吧。<br/>第三次终面问我为啥会离职，我很紧张，怕雷区出现，如何证明自己的稳定性与潜在能力呢？就给面试官试着解释了一下，后面面试官继续追问“也可以不离职的那种骑驴找马地找工作的呀？”。我就又诚实地解释了一遍，不知道能不能不要踩雷。整体上我的核心还是避免说谎，毕竟一个谎言需要更多的谎言弥补。最后的结果是终面也通过了，还好没有猜中雷区。</span></p><p style="line-height: 2em;margin-bottom: 32px;"><font size="3">最大的体会是无聊确实是治愈心灵的好方法❤️，最近也开始听爵士乐和日本 80 年代摇滚乐，感觉很有意思。另外再次认为冷萃冰咖啡特别好喝☕️(≧▽≦)，反思是不是以前把自己绷得太紧了，现在每天晚上散步的中途坐在咖啡店里发呆就特别舒服，估计还是深信服强度太大了，经年累月下来受不了，或许我太有责任心了吧，内耗严重。</font></p><div><p style="display: inline-block;"><img data-ratio="1.778125" style="height: auto !important;" data-type="jpg" data-w="1280" src="https://wechat2rss.xlab.app/img-proxy/?k=3e603337&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FfNR1ygo0YuWziaPsSl2tCEF4A4SU2w6VTGyf0lfslfpNU0udRiaTawL2sluyhow3VB7anvlknCUJk2JYaHe9Wvq7JxGibA9jIuvwvmuQ3zQmrI%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="line-height: 2em;margin-bottom: 32px;"><span style="font-size: medium;">昨天散步的时候看到了这棵树，去年台风预警提前下班回家，被切割过的树（避免吹倒而提前切割了枝干）。今年依然春意盎然，旺盛的生命力👏。</span></p><div><p style="display: inline-block;"><img data-ratio="1.778125" style="height: auto !important;" data-type="jpg" data-w="1280" src="https://wechat2rss.xlab.app/img-proxy/?k=1324c6b9&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2FfNR1ygo0YuXicJN7raIXDcoQukIE9wRqIE3dqkAl7asQCh6Za7P8l768OAxFic4x7x3jcGM3iblNibgLkO48HHzaiaKqicfXkAH3ufbBiaxia15PnVA%2F640%3Fwx_fmt%3Djpeg"/></p></div><div><p style="display: inline-block;"><img data-ratio="1.778125" style="height: auto !important;" data-type="jpg" data-w="1280" src="https://wechat2rss.xlab.app/img-proxy/?k=1858c174&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FfNR1ygo0YuXZqibVQgj5h9Yiay5WUX5N8NlNDHD8icn8Wwqa5ynqkBWo7xLJJiafTUIUuoq2TGYnt56DHkmZg1GX01tG9UeAevyAWu8fE4sPPd4%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>



<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=573dd51f&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485767%26idx%3D1%26sn%3Dc881554cf7c1159380771a0c793da590">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Sun, 17 May 2026 17:50:00 +0800</pubDate>
    </item>
    <item>
      <title>专职逆向岗位面试的复盘与体会</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485763&amp;idx=1&amp;sn=5fedf2ee5d59e638c4609b5dd761bae1</link>
      <description></description>
      <content:encoded><![CDATA[<p>原创 <span>jishuzhain</span> <span>2026-05-16 20:29</span> <span style="display: inline-block;">广东</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=6200c43a&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FfNR1ygo0YuVvA4Q1cqibla8TshnG4y5qMicuhiclxLY32mw3FEodquvwv7jdjMu9kVuEkGvDpicNuMBrv71olNLRicibbLflERP8xzsMrbazBaEpQ%2F0%3Fwx_fmt%3Djpeg"/></p>
  
  <p style="line-height: 2em;margin-bottom: 32px;"><span style="font-size: 16px;letter-spacing: 0.034em;">最近也没啥合适的机会，想看看排第三的求职意向，【专职逆向】方向怎么样，这类岗位就是按照能力定薪了，所以需要机试，但和网络安全方向关系不大了。以前微步招聘的时候也会要求写一份木马分析报告，后面才考虑安排面试。道通科技人事说完全能覆盖我在深信服的薪资，他们的薪资是有竞争力的。😂先试试吧……</span></p><p style="line-height: 2em;margin-bottom: 32px;"><span style="font-size: 16px;">小插曲就是接到 hr 的电话是晚上快九点了，也说明这类公司加班严重。加班确实特别消耗身体和精气神，久而久之人就废了，对此我深有感触😭。</span></p><p style="line-height: 2em;margin-bottom: 32px;"><span style="font-size: 16px;letter-spacing: 0.034em;">机试的题目是逆向一个MFC 程序的核心算法逻辑，并尽量还原思路，时间要求是半天时间内完成。我拿到题目后花费了两个小时左右完成了逆向工作，并记录过程以及算法实现细节和Python 代码验证细节整理成文档提交给了hr。hr 随后转给了业务负责人，后续反馈我有资格可以参加面试。</span></p><p style="line-height: 2em;margin-bottom: 32px;"><span style="font-size: 16px;letter-spacing: 0.034em;">面试这类岗位属于技术岗，纯看技术的反馈挺快的，能行就行，不行就不行，也没法PPT吹牛。凡事一体两面，没有绝对。😆还好吧，和前辈们交流一下，看看专职逆向现在在企业环境里面是啥情况，本着多学习多接触的目的展开的。</span></p><p style="line-height: 2em;margin-bottom: 32px;"><span style="font-size: 16px;letter-spacing: 0.034em;">好久没面试了，面试一下找找感觉，与部门经理进行的第一面，问了我过往“AI +自动化逆向”的项目经历，没咋问逆向相关的问题，整场面试都是一些基础常识。面试的最终结果就是没有通过，但对我有用了解到的信息如下：<br/>这类专职逆向岗位是甲方里面的乙方，离产品很远，是公司的最后一道技术防火线，如果这个部门的人解决不了公司也就解决不了了。平时要逆向自家公司产品做好防护，逆向竞品产品，把核心的东西通过某种手段拿到。有10%涉及服务器安全，代码review，不过不是重点，兼顾一下，有购买的安全产品支持，逆向的这个部门是公司内部的资源部门。</span></p><p style="line-height: 2em;margin-bottom: 32px;"><span style="font-size: 16px;letter-spacing: 0.034em;">以上就是本次面试后的复盘与体会，主要内容来源于个人的朋友圈汇总。</span></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>



<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=50f20542&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485763%26idx%3D1%26sn%3D5fedf2ee5d59e638c4609b5dd761bae1">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Sat, 16 May 2026 20:29:00 +0800</pubDate>
    </item>
    <item>
      <title>多次面试后的复盘与体会</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485761&amp;idx=1&amp;sn=5a63a6ba45a8938d55f2825bfa4b14ee</link>
      <description></description>
      <content:encoded><![CDATA[<p>原创 <span>jishuzhain</span> <span>2026-05-03 20:54</span> <span style="display: inline-block;">广东</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=6200c43a&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FfNR1ygo0YuVvA4Q1cqibla8TshnG4y5qMicuhiclxLY32mw3FEodquvwv7jdjMu9kVuEkGvDpicNuMBrv71olNLRicibbLflERP8xzsMrbazBaEpQ%2F0%3Fwx_fmt%3Djpeg"/></p>
  
  <p style="line-height: 2em;margin-bottom: 32px;"><span leaf=""><span textstyle="" style="font-size: 16px;">这几天在复盘反思与前辈的聊天，有一个观点我们是可以达成认可的，就是不要去加班严重的公司。第一方面是非常累，第二方面是会影响身体健康。给我的建议就是现阶段不用考虑去大型互联网公司，第二个就是不要再去安全公司了。😂<br/>我是一个很听劝的人，也不敢把思维固化下来，过往经历虽然有用，但也有可能是思维包袱，还是愿意随着环境和经历而改变。想起来了这 6 年在深信服的能力中台部门的晃悠经历，遇到过几次选择，当时是这样做的。<br/>2021 年末 APT 研究追踪方向比较火，微步有考虑招人，负责人找了一下我。当时在深信服评估了一下，以为可以继续做下去就没有考虑外部机会，但后来以为可以做下去，但其实业务变动比较大，管理侧认为没有什么价值，后来就转方向了，2022 年是我的艰难时期，当年沟通绩效前几个月就找我谈话说我年度绩效会很差，我会承担团队的差绩效指标，意味着没有调薪机会与任何年终奖。暗示我先提前找工作，后来就对外找了一下工作，没有成功，想等着 2023 年初对外看看。后来了解到微步的深圳团队撤掉了，目前只有北京有岗位。<br/>在 2022 年这类艰难时期里 edr 产品部门想要人，edr 主管和运营经理面谈了一下我，我结合我当时获取到的信息，这个部门加班比较严重，我就后来拒绝了，我当时已经做好了最坏的打算。想起了是我做过的比较正确的决定了，始终把身体健康放在优先级第一位。😆<br/>除了怎么做选择外，一旦有机会就重塑以往的心态与想法，人没法像机器人一样保持“初心”，所以只能尽量保持优秀的心态与习惯，对抗人性里的惯性，学习接纳自己也是维持良好心理健康的的好方法。最近在备考CISSP，原本计划某天下午外出待会，顺便把第一套模拟题快速过一下复习一下难题错题就可以了，海边逛逛吹吹海风就可以回家了，放松为主。因为备考计划时间是充足的，我有过评估时间，但是内心里那种长期压力下养成的急功近利，急急急，快快快，多多多的想法促使了新的行动，一下子就多看了几十题，看起来是“多”了，但我“少”了一些东西。最终的结果就是心里会有点急躁的情绪，而且会有点累（不是体力劳动的累），果然急功近利，急急急，快快快的情绪很消耗自己的生命力呀，所以后续就会要纠正一下自己。</span></span></p><p style="line-height: 2em;margin-bottom: 32px;"><span leaf=""><span textstyle="" style="font-size: 16px;">心态与想法得到纠正后就可以与周围环境的朋友或者网友进行交流了，这是改变以往技术一条路走到底的困境需要做一下的行动，在保持边界感不打扰别人的前提下与周围人产生一些联系。最近一段时间有帮助四位网友（主要是现在没上班，时间富裕，情绪基本上很稳定，卡皮巴拉，心平气和，还想聊聊天），第一位是深圳甲方做企业安全的，涉及到一个反病毒问题，我简单解答了一下，给了一个解法。第二位以前是同行，如今转行了，可能在创业，问了我一下“AI+自动化逆向”的问题，我简单解答了一下。第三位是山西那边驻场的安全从业者，有些迷茫（行情不好的时候是酱汁的，都能理解与体会感同身受），聊了一会给拆解了对方的一些问题，给了点解法。第四位北京网友遇到点面试的问题，愿意相信我，看了一下对方简历没啥问题，给了点建议，我也给了点回答。只能说生活百态，各有各的特色与烦恼吧。有时候问题或者困境走不出来的时候感觉可以提升自己的思维维度，高维度的想法也许就能覆盖掉低维度的困难。</span></span></p><p style="line-height: 2em;margin-bottom: 32px;"><span style="font-size: 16px;letter-spacing: 0.034em;">不敢只局限于国内就业环境，最近一段时间</span><span style="font-size: 16px;letter-spacing: 0.034em;">开始编写英语版本的简历，第一次做这样的事情，感觉很不错，又接触到了不一样的东西，如果每天都能接触到有趣的事物还挺有意思的吧哈哈😂。花了点时间完成了初版，原则还是先保证没有语法错误和词汇拼写错误，专业与行业术语要求一定要准确无误，不然就出丑了。利用的辅助工具是GPT5.5，目前最强的模型，不过免费账号的额度越来越少了，用一会就提示需要4个小时后才能继续使用最新最强大的模型。</span></p><p style="line-height: 2em;margin-bottom: 32px;"><span style="font-size: 16px;letter-spacing: 0.034em;">以上就是多次面试后的复盘与体会，主要内容来源于个人的朋友圈汇总。</span></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>



<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=5de71719&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485761%26idx%3D1%26sn%3D5a63a6ba45a8938d55f2825bfa4b14ee">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Sun, 03 May 2026 20:54:00 +0800</pubDate>
    </item>
    <item>
      <title>找工作后的体会</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485759&amp;idx=1&amp;sn=e79fcfc86d298b50803f478d5218a397</link>
      <description></description>
      <content:encoded><![CDATA[<p>原创 <span>jishuzhain</span> <span>2026-03-28 12:28</span> <span style="display: inline-block;">广东</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=6200c43a&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_jpg%2FfNR1ygo0YuVvA4Q1cqibla8TshnG4y5qMicuhiclxLY32mw3FEodquvwv7jdjMu9kVuEkGvDpicNuMBrv71olNLRicibbLflERP8xzsMrbazBaEpQ%2F0%3Fwx_fmt%3Djpeg"/></p>
  
  <p style="line-height: 2em;margin-bottom: 32px;"><span leaf=""><span textstyle="" style="font-size: 16px;">今年2月从深信服离职了，自己综合权衡后做出的决定。从2020年3月持续到2026年2月，确确实实在一家乙类网安类企业从事安全类工作这么久。抛开打工是出卖时间来获取生存资源的基本面，如果要说做出了什么值得认可的成果或者成就。我觉得有两点，第一点是2020年至2023年初，在安全蓝军团队（高级威胁研究组）从事APT挖掘与追踪研究方向，那一年需要投入这块的研究与积累，期待做出成果，后面就保持使用传统方法的同时也启发思考，实践了基于资产测绘方法来辅助挖掘APT组织情报线索的方法，2021年产出的效果不错，主动发现了很多起部署的安全设备未能发现告警的APT入侵事件，获得了公司的认可。基于这类思考继续扩展挖掘了多起常使用钓鱼攻击获得的有组织的攻击事件，能提前发现攻击者部署的钓鱼资产，在往“防御优先”思维靠近。</span></span></p><p style="line-height: 2em;margin-bottom: 32px;"><span leaf=""><span textstyle="" style="font-size: 16px;">安全蓝军（高级威胁研究组）由北京与深圳两个小组组合成一个团队，后面团队变动以及业务重心改变，资源逐步倾斜到北京的团队，深圳组逐步没落，最终解散。</span></span></p><p style="line-height: 2em;margin-bottom: 32px;"><span leaf=""><span textstyle="" style="font-size: 16px;">第二点是2023年初因威胁情报团队确认需要投入“云杀毒”方向，机缘巧合来到了该团队，通过自身丰富的病毒逆向研究与检测的相关技能，搭建起云端纵深文件检测系统的能力基座取得效果，在沙箱释放能力和未知文件检测模型上均做出重要贡献。积极拥抱 AI，持续引入大模型（LLM）能力，例如让 IDA 结合 AI IDE 实现分析辅助研判，实现的能力能达到接近安全专家的水平，极大地提高了整个部门的运营效率。持续不断地追踪与分析终端安全领域最新威胁，多次预研并设计安全检测防护方案后能成功落地。</span></span></p><p style="line-height: 2em;margin-bottom: 32px;"><span leaf=""><span textstyle="" style="font-size: 16px;">业务变动和重心越来越对自身的发展造成影响以及评估当前与周围劳动力市场的情况发现竞争力提升有限，持续地在舒适区久了会增加沉没成本，选择换个环境也是当下比较合适的选择。</span></span></p><p style="line-height: 2em;margin-bottom: 32px;"><span leaf=""><span textstyle="" style="font-size: 16px;">为了能成功换环境，评估了自己的技能栈以及方向和意向，最终确定求职意向更偏向于终端安全检测与防御，反病毒类，安全建设落地，安全运营等这类岗位。当然想与实际能成之间不存在明显的路线（每个人在不同的年龄段以及场景下都会有自己独有的苦恼吧），找工作对大部分人来说是痛苦的，但这种痛苦未来必定会发生，只是当下将其拉到了现在来提前感受，避免未来年龄到了33、34岁的时候面对变化时候的迷茫以及因固化而来的痛苦。</span></span></p><p style="line-height: 2em;margin-bottom: 32px;"><span leaf=""><span textstyle="" style="font-size: 16px;">思维的转变是最近的体会（这里不会写AI新引入业务后的安全建设问题），从1月份到现在面试了4次，把握把安全技术真正落地建设应用的路径。面试甲类企业的时候体会到的是防御以及架构和方案，视野上一定要大，在成本和收益合理的情况下，问题一定要解决，不管是什么技术，自嗨没有用。昨天读到一篇文章《谁来保护你的安全设备？》觉得有点体会了，由于要准备面试，阅读了一些偏甲类企业安全建设方面的书籍，提到了安全结构以及可信链。比如安全设备能被入侵且难以根除后门，这里涉及到的是理念是安全可信，以及安全配置这块没做到位，信任链，安全架构的设计问题。但其实还是预算与投入的问题，重要的肯定要一层层防御，确保信任链可追溯，不过业务不值钱不重要的，就算了，基于小概率事件直接接受了这种风险。至于边界设备，这么多年APT事件处置推送也被推了好几次了，说明不是小概率事件。企业的体量以及需要保护的资产的价值也决定了对安全的投入程度，当然这是老生常谈的共识了，甲类企业的安全建设如果没有权衡多方利益，最终很难落地安全防御，并不是技术主导一切。</span></span></p><p style="line-height: 2em;margin-bottom: 32px;"><span leaf=""><span textstyle="" style="font-size: 16px;">面试了几次，确实面试可以学到一些新想法以及前沿的问题，例如“防御检测思维的转变”。通过比较能得到体会，我比较中意，那种面试前面试官给介绍一下具体问题，以及团队情况，以及可能需要解决的问题与任务流程和职业发展规划。对面试者来说，确实有好感度，至少比文字的岗位描述太有用了。</span></span></p><p style="line-height: 2em;margin-bottom: 32px;"><span leaf=""><span textstyle="" style="font-size: 16px;">一点点体会，继续慢慢找工作。</span></span></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>



<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=4e61272e&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485759%26idx%3D1%26sn%3De79fcfc86d298b50803f478d5218a397">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Sat, 28 Mar 2026 12:28:00 +0800</pubDate>
    </item>
    <item>
      <title>思考一下终端安全的现状与防御</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485755&amp;idx=1&amp;sn=d2c14f08e98f4ee4c23b136f9b489040</link>
      <description>自从接触到威胁检测方向以来，我就一直在思考如何设计出一款强大的检测系统，能否实现比较完美且有效的效果。</description>
      <content:encoded><![CDATA[<p>原创 <span>jishuzhain</span> <span>2026-02-10 17:58</span> <span style="display: inline-block;">广西</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=e316733f&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0h464kSQsqF1ialSvePJe0JjvQP85yOzczFoDQ0zBNk5WsUzQ8WdXujD8T4ohKuH9XoaMyUe26EgdQ%2F0%3Fwx_fmt%3Djpeg"/></p>
  
  <p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span style="font-size: 17px;"><span leaf=""><span textstyle="" style="font-size: 16px;">自从接触到威胁检测方向以来，我就一直在思考如何设计出一款强大的检测系统，能否实现比较完美且有效的效果。一方面受限于资源投入与试错成本，另一方面网络安全行业得持续投入才可能有回报，选定一个新颖方法后投入半年但成果不够，最终就会造成人员产出不够，基于末尾淘汰的机制就会流失，所以短时间投入很难明显看到成果。基于此，我就以往的思考进行一些简短总结。</span></span></span></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span style="font-size: 17px;"><span leaf=""><span textstyle="" style="font-size: 16px;">2022年末至今这几年，主要是黑灰产恶意软件一直充斥着普遍的办公环境，例如发送钓鱼链接后下载了恶意程序，恶意程序执行后会导致产生“拉群”行为，进一步暴露出办公环境的脆弱，也说明这么多年对终端安全的投入和PPT类市场营销下依然做的很拉垮。</span></span></span></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span style="font-size: 17px;"><span leaf=""><span textstyle="" style="font-size: 16px;">财务或者金融业人员中招后，由于天然的金融属性，离钱越近所受影响程度会更高，例如2023年期间某企业因发生钓鱼的恶意程序而最终能造成几千万人民币损失，至于各类小型损失则肯定已有发生。</span></span></span></p><p style="text-align: left;line-height: 2em;margin-bottom: 8px;"><span leaf=""><span textstyle="" style="font-size: 18px;color: rgb(47, 118, 195);font-weight: bold;">一、回归本质来应对</span></span></p><p style="text-align: left;line-height: 2em;"><span style="letter-spacing: 0.034em;font-size: 17px;"><span leaf=""><span textstyle="" style="font-size: 16px;">先抛开各类花里胡哨的防御技术，因为越过度宣传制造恐慌越容易让客户买单，这主要是因为安全效果很难量化，回归该类钓鱼事件的本质进行思考可以得到如下结论或者启发。办公安全的本质依然还是管理问题，钓鱼的恶意程序必定需要入口，这个入口的防御就是办公安全领域或者更具体去分类的终端安全需要面对的。泄洪的时候不从入口处封堵，而直接放开把全部举措落实到后面是最不明智的选择，成本高，风险大。我们把入口点管理住了，这类基于钓鱼的恶意程序的遏制也能收获很大的效果。</span></span></span></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span style="font-size: 17px;"><span leaf=""><span textstyle="" style="font-size: 16px;">正常企业不可能有人每天都需要安装新的程序，鉴于此，可以设定管控机制，在建设好基线数据后，对于安装新的程序需要进行二次审核确认才能通过，在二次审核确认通过的这个环节里需要思考如何才能低成本尽量零误报的实现，如果效果远远大于成本支出那么肯定落实到位。一旦能完善管理机制，落实到位，对于现在活跃的钓鱼程序基本能实现遏制。坏处就是需要有很强的执行力才可以，例如老板等直接授权定义制度，不然仅靠信息安全部门总归是权力不够，效果很差，这类不是技术风险问题范畴。</span></span></span></p><p style="margin-bottom: 8px;line-height: 2em;text-align: left;"><span style="font-weight: bold;color: rgb(47, 118, 195);font-size: 17px;"><span leaf=""><span textstyle="" style="font-size: 18px;">二、避免“猫鼠游戏”</span></span></span></p><div style="margin-bottom: 24px;line-height: 1.92;text-align: left;"><p style="text-align: left;line-height: 2em;"><span style="font-size: 17px;"><span leaf=""><span textstyle="" style="font-size: 16px;">随着国产化的进程推进，办公环境已经完全与传统的Windows系统产生了隔离，例如银河麒麟系统+华为交换机+浪潮服务器+奔图打印机+浪潮台式电脑+紫光扫描+内置国产应用WPS，奇安信浏览器，火绒杀毒，安装软件还得管理员用中孚安装配置。这类情况一发生后，对于这类平台的钓鱼恶意程序会完全无害，因为基于Win的恶意程序很难运行在国产操作系统上。活跃的黑灰产恶意程序很少在这类平台完成入侵活动吧？同理各类不同系统设定应用市场也是如此的道理，利用管理机制来尽可能避免对恶意程序的持续对抗。攻防本质是不对等的，不管如何利用各类新技术（例如AI）来实现防御，攻击者总归可以在成本合理的情况进化从而达成目标，而防御者在成本与平台以及其他方面疲于奔命，还面临末尾淘汰压力。</span></span></span></p></div><p style="text-align: left;line-height: 2em;"><span style="font-size: 17px;"><span leaf=""><span textstyle="" style="font-size: 16px;">所以，对于威胁检测来说，善于跳出传统思维是很重要的，由于跳出传统思维困难重重，因此这类想法在现实情况下很难落地，从哲学的角度思考，如果整个网络安全行业由于防御实施到位，近5到10年都没有恶劣事件，那么，还需要持续加大投入安全预算吗？这确实是一个值得思考的问题。</span></span></span></p><p style="text-align: left;line-height: 2em;margin-bottom: 8px;"><span style="color: rgb(47, 118, 195);font-weight: bold;font-size: 17px;"><span leaf=""><span textstyle="" style="font-size: 18px;">三、结语</span></span></span></p><p style="text-align: left;line-height: 2em;"><span style="font-size: 17px;"><span leaf=""><span textstyle="" style="font-size: 16px;">当前的解决方法以及各类现象存在肯定是合理的，但可能并不是最优解。网络安全的各类现象以及问题本质还是投资问题，威胁检测的设定或者完善也是一样的。</span></span></span></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>


<p><a href="%27%27">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=7d1f617b&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485755%26idx%3D1%26sn%3Dd2c14f08e98f4ee4c23b136f9b489040">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Tue, 10 Feb 2026 17:58:00 +0800</pubDate>
    </item>
    <item>
      <title>基于样本层面的痕迹挖掘关联研究</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485753&amp;idx=1&amp;sn=2dba23f2f68721d9901e3ed92b03a056</link>
      <description>这篇文章主要是基于样本作为支点实现对攻击团伙或者特定属性的组织实现一些痕迹挖掘，最终目标主要是持续发现新的攻击</description>
      <content:encoded><![CDATA[<p>原创 <span>jishuzhain</span> <span>2026-02-05 15:51</span> <span style="display: inline-block;">广东</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=d8a27239&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2FfNR1ygo0YuX9Z3FJUeQcgVAuWJH90HFZQNKn4OWpz1UMiaIutpvIAL8W6W39uBTibFwbK97dBN8PoiaeQ0QC93J6REUTUOKYyNS1A4IucIibah0%2F0%3Fwx_fmt%3Djpeg"/></p>
  
  <p style="line-height: 2em;text-align: left;"><font style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 16px;">这篇文章主要是基于样本作为支点实现对攻击团伙或者特定属性的组织实现一些痕迹挖掘，最终目标主要是持续发现新的攻击痕迹或者趋势，在防御上能有侧重或者实现“情报先行“的理念。写文的基础来源于之前工作需要对此类攻击活动进行持续挖掘跟踪，尽量或者尽快在攻击成功后能及时遏制攻击者的行动。这块的思路不限制，比如可以结合图算法或者数据挖掘算法来完成类似的目的也可以，主要是受限于个体想法与可支配的资源所决定最终的效果。在此，我仅仅只是抛砖引玉说明一下。</span></span></font></p><p style="text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">样本是实现攻击者目的的一个重要载体，必然携带有不少攻击者所属的基因，在最理想的情况下，我们可以基于样本获取到攻击者的意图。本文的样本聚集在Window平台下，其余平台或者架构当前并未涉及，但从理想状态来汇总，攻击者并不会仅仅限于利用Window平台实现攻击目的，只要防御者所必然依赖的设备都可能成为攻击面。</span></span></p><p style="text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">以下内容是整个研究与分析过程，会从多个特征维度进行分析与举例说明。</span></span></p><p style="margin-bottom: 8px;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 18px;font-weight: bold;">奇特字符串</span></span></p><p style="text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">在对捕获的恶意样本分析完毕后，我们注意到了样本里包含了比较奇特的字符串内容，如下为“HAIBJCK”字符串。</span></span></p><p style="text-align: left;"><span style="font-size: 16px;"><span leaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.652321630804077" data-type="png" data-w="883" width="887" data-imgfileid="100002095" src="https://wechat2rss.xlab.app/img-proxy/?k=90bb7686&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FfNR1ygo0YuU1f6zvX0Y2s7h9JuHDWibX3ibNwbBf7LJGKJUzdw3ZxmvicD2IJAayYSkmPicDFCQS5Q7YibeRrV17goibTtTuNrqG6icMOicWmuNMTQg%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></span></p><p style="text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">为了捕获到相关联的样本，通过VT官方提供的搜索语法找到了如下结果，通过结果数量可以发现这个匹配的数据不多，正好可以手工验证下。由于“HAIBJCK”为特殊字符串，为减少搜索的范围，我们直接搜索过滤出dll文件结果，此时返回的结果比之前的结果要多一些。搜索命令：content:&#34;HAIBJCK&#34; AND entity:file tag:pedll，简单验证后可以明显发现很多相关联的样本。</span></span></p><p style="text-align: left;"><span style="font-size: 16px;"><span leaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.5361111111111111" data-type="png" data-w="1080" data-imgfileid="100002096" src="https://wechat2rss.xlab.app/img-proxy/?k=89169619&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FfNR1ygo0YuXf2YdPCWicNNUjmAMcomXg8VPnUYlmUMibicOIfCCV0QuICAGNhAYqIJARdgHKevK5SwUTB1Tfjy7U9pAoy4UleTRUHjTmcSRvgw%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></span></p><p style="margin-bottom: 8px;text-align: left;"><span style="font-weight: bold;"><font style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 18px;font-weight: bold;">vhash关联匹配</span></span></font></span></p><p style="text-align: left;"><span style="font-size: 16px;color: unset;"><span leaf=""><span textstyle="" style="font-size: 16px;">根据VirusTotal的说法，vhash是一种内部相似性聚类算法值，基于简单的结构特征哈希可以找到相似的文件。目前没有关于vhash的更多信息，VirusTotal没有公开vhash的算法细节。不过我们可以适当地在关联时进行利用，</span></span></span><span style="font-size: 16px;font-family: unset;color: unset;"><span leaf=""><span textstyle="" style="font-size: 16px;">通过该样本（3452471158ED7E6BDE3D66141B08CEA4）的vhash结果进行关联搜索，我们得到了另一个相似恶意文件样本。</span></span></span></p><p style="text-align: left;"><span style="font-size: 16px;"><span leaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.5174035747883349" data-type="png" data-w="1063" width="1067" data-imgfileid="100002097" src="https://wechat2rss.xlab.app/img-proxy/?k=11b687df&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FfNR1ygo0YuUibnRXoYSd1DcfudKOib8wHvkpesSkd5PzjgicPVcRgmemcBcVPLg3riaibibU4IwDPp1vVIeicrXscj7ibtk7OpUskaCicSqmwLGuQkgc%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></span></p><p style="text-align: left;"><font style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 16px;">搜索命令：</span></span></font><span style="font-size: 16px;color: unset;"><span leaf=""><span textstyle="" style="font-size: 16px;">vhash:135056651d75151az42jz2jz，</span></span></span><span style="font-size: 16px;color: unset;"><span leaf=""><span textstyle="" style="font-size: 16px;">搜索结果如下。</span></span></span></p><p style="text-align: left;"><span style="font-size: 16px;"><span leaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.21666666666666667" data-type="png" data-w="1080" width="1328" data-imgfileid="100002098" src="https://wechat2rss.xlab.app/img-proxy/?k=0c8fede1&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FfNR1ygo0YuXWJb7b04jIs6tGf6bNb2DGG7akqUjoz0jOPTOWeHkvZew8LuNt8ibibK1fNARBsag7907ML5QNq3cQGpHApMzlKshHUYXF5WE9Y%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></span></p><p style="text-align: left;"><span style="font-size: 14px;"><span leaf=""><span textstyle="" style="font-size: 16px;">本地进行简单的分析，发现两个文件确实具备一定的相似性。</span></span></span></p><p style="text-align: left;"><span style="font-size: 16px;"><span leaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="1.2319277108433735" data-type="png" data-w="664" width="666" data-imgfileid="100002099" src="https://wechat2rss.xlab.app/img-proxy/?k=d702fbc6&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FfNR1ygo0YuVBON0HrTTgLeD4wYszK7TjSPrDibCZnicsAFu84hcXa1Qic11Sa7UsFvNLdBsLZJGZHc8tmxAj184uc2bZEOoB3pCB4y26rHibZ2c%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></span></p><p style="text-align: left;"><span style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 16px;">通过调试新关联文件也发现他们之前判断母体加载文件名称的逻辑是一致的，但是经过数据比对两个文件之后的shellcode部分是不同的，属于不同攻击样本。</span></span></span></p><p style="text-align: left;"><span style="font-size: 16px;"><span leaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.5231481481481481" data-type="png" data-w="1080" width="1328" data-imgfileid="100002100" src="https://wechat2rss.xlab.app/img-proxy/?k=8dffc762&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2FfNR1ygo0YuW9f9CljBIgv7mfq6PErM80na1FiaTAz9ecHXma3u6BQWTyyMFnLV0HpnlR57J5JawDnfNReBXWksnmoQR8FY6klOTS38CnkKiaM%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></span></p><p style="margin-bottom: 8px;text-align: left;"><span style="font-weight: bold;"><font style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 18px;">导入表哈希值imphash关联匹配</span></span></font></span></p><p style="text-align: left;"><font style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 16px;">通过对其导入表哈希值imphash进行关联搜索，我们也可以得到另外一些关联结果。</span></span></font><span style="color: unset;font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 16px;">搜索命令：</span></span></span><span style="font-size: 16px;color: unset;"><span leaf=""><span textstyle="" style="font-size: 16px;">imphash:9d9fd850ae414cf4cef6e0521cddb88d</span></span></span></p><p style="text-align: left;"><span style="font-size: 16px;"><span leaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.275" data-type="png" data-w="1080" width="1328" data-imgfileid="100002101" src="https://wechat2rss.xlab.app/img-proxy/?k=2fdcf1ac&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FfNR1ygo0YuX0KsiaAGDgeYWLkSp6JicMG4s528YAAUTPcqPbHQaeib4uuYtO8Wukr5Za9e7xQvibr9qaL7aDJibj27UnQqthsLiczeWq9Z4AzpkbY%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></span></p><p style="text-align: left;"><font style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 16px;">PE文件的元数据Rich header哈希值一致则表明这是利用相同的编译环境构建的恶意文件，为了获取到更多攻击样本集，这一特征也可以作为关联技巧，PE文件的元数据Rich header解释如下。</span></span></font></p><p style="text-align: left;"><font style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 16px;">Rich header是一种未公开的结构，它出现在微软使用“LINK.EXE”工具生成的大多数 PE 文件中。实际上，使用标准的Visual Studio工具集构建的任何二进制文件都包含此标头。目前互联网上没有描述这种结构的官方文档，但是可以在互联网上找到足够多的公开信息，并且还可以逆向 LINK.EXE 本身获取更多细节信息。</span></span></font></p><p style="text-align: left;"><font style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 16px;">不过由于该特征比较单一，所以在进行样本归因来源时需要与其他特征结合才能得到较高的可信度，</span></span><span style="color: unset;font-family: unset;"><span leaf=""><span textstyle="" style="font-size: 16px;">实践案例：</span></span></span><span leaf=""><span textstyle="" style="font-size: 16px;"><a href="https://securelist.com/the-devils-in-the-rich-header/84348/" target="_blank">https://securelist.com/the-devils-in-the-rich-header/84348/</a></span></span></font></p><p style="margin-bottom: 8px;text-align: left;"><span style="font-weight: bold;"><font style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 18px;">Rich header哈希值关联匹配</span></span></font></span></p><p style="text-align: left;"><span style="font-size: 16px;"><span leaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.2833333333333333" data-type="png" data-w="1080" width="1328" data-imgfileid="100002102" src="https://wechat2rss.xlab.app/img-proxy/?k=c73b2058&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fmmbiz_png%2FfNR1ygo0YuVJm93icBIVF7EV7fFwf1W0jT3aMHx50vGiatnsS1zgYrqHnc0SaEAg7MwX6Lw9mYGjRic2qzkveUsZnpDea0YpIGszZlDLsV7alw%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></span></p><p style="text-align: left;"><font style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 16px;">将匹配的样本下载到本地后，人工对三个样本进行了静态分析与调试，发现上述三个样本的相似性太高了，所以导入表哈希一致也是很自然的，可以判定确实是同一个组织针对受害者定制开发的恶意文件，由于出自同一组织，自然大概率下构建环境在一定程度上是一致的，这也符合这些样本的Rich header哈希值是一致的。</span></span></font></p><p style="text-align: left;"><font style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 16px;">想法是基于特定的问题而诞生的，对于痕迹挖掘关联来说也是如此，在符合逻辑的条件下，不限思路即可。</span></span></font></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>


<p><a href="%27%27">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=57c56e84&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485753%26idx%3D1%26sn%3D2dba23f2f68721d9901e3ed92b03a056">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Thu, 05 Feb 2026 15:51:00 +0800</pubDate>
    </item>
    <item>
      <title>时间贫困</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485741&amp;idx=1&amp;sn=6e51e28167a3f99a1219e4c240e731ea</link>
      <description>2025年12月6号准备写下这些文字，不过后来发生一些事情需要处理，无奈把这个念头搁置下来。今天我的事项处理得差不多了。</description>
      <content:encoded><![CDATA[<p>原创 <span>jishuzhain</span> <span>2026-02-03 15:31</span> <span style="display: inline-block;">广东</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=bc1f660d&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0iaUHWWw5TbIgVJr3ahxlQ9zQU1xTdLC4KNFEpKukrBDlfdLhBfsK9Ivo3G6nqFSIibqg7YLIk5VcHg%2F0%3Fwx_fmt%3Djpeg"/></p>
  
  <p style="line-height: 2em;"><font style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 16px;">2025年12月6号准备写下这些文字，不过后来发生一些事情需要处理，无奈把这个念头搁置下来。今天我的事项处理得差不多了。打开了笔记准备补充完文字，这篇草稿留在我的笔记里，直到今天重新开始写完想写的内容，附带一些对之前经历的思考。</span></span></font></p><p style="line-height: 2em;"><span style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 16px;">在正确的路线以及规划下，尽心地投入进去，人是充满乐趣的，在烂环境中持续挣扎不过是消耗个体宝贵的生命力。个人的生命力是不可再生资源（如果硬要反驳说有一茬茬永远年轻的年轻人，我也没有话说，因为环境是复杂的，每个人的观点在特定条件要求下都是正确的。），活在社会时钟里的状态是痛苦的，原因有如下一些体会。</span></span></span></p><p style="line-height: 2em;"><span style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 16px;">时钟是必须时刻波动向前的，一旦落后就会被抛弃，认定为失败。如果没有容错空间，个体就需要承受这类来自群体的挤压，痛苦是持续的，并非快照式的一瞬间。</span></span></span></p><p style="line-height: 2em;"><font size="3"><span leaf=""><span textstyle="" style="font-size: 16px;">加班其实是会剥夺创造力，至于真不真只能由每个人自己的体会来决定，身体好就可以多试试，身体差确实没有办法继续了，但是仍然没有一个非常标准的答案。在这个过程中人会逐渐适应环境，美名其曰融入大家庭，久而久之就忘记了人的劳动力是会波动贬值的，一旦到了价值被榨干的时候，毫不犹豫的丢弃会是普遍现象。虽然没有办法“拒绝”加班，但是也需要多思考如何不陷入加班之中。人最宝贵的时间一般来说仅仅只有10年左右，例如24岁到32岁这个时间段，为什么没有35岁？因为笔者身处IT科技行业，35岁以上的人群常年会出现在如何让年度财务报告很好看的优先位置。40岁以上往往面临着疾病风险以及其余风险的困扰（如果去研究保险知识就能发现这个明显存在的年龄风险分段趋势），而太年轻又面临着经验不足，初生牛犊不怕虎，难以形成比较有深度的思考，从失败的事项上也可以学到东西，而这个10年左右的时间段也是人能真正在经历一些事情后有机会去思考去努力选择的过程。</span></span></font></p><p style="line-height: 2em;"><font size="3"><span leaf=""><span textstyle="" style="font-size: 16px;">个人改变不了环境，而环境可以改变人。当一个人处于一个人浮于事的群体时，自然而然就会受其影响。原本不需要加班就可以很好地推进进展的工作规划，来到人浮于事（或者说是表面效率）的环境时就免不了需要刻苦的加班才能应对。过分地强调追求效率实质是对当下环境的恐惧，因为当人处于充满安全感的环境时是不会过分夸张表达自己的想法的。</span></span></font></p><p style="line-height: 2em;"><span style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 16px;">把自己宝贵的时间抽离出来进行规划，表面上通过延长个体时间的投入可以获得一些回报，但人的生命力在被消耗，而且速度肯定加快了，很难直接证明出来，只能说极端案例是有的，例如“过劳死”。对时间贫困或者缺失时间的恐惧来源于事项的繁多，超过了个人所能承担的极限。久而久之，慢性压力聚集，消极情绪会越积越多，脾气也会被其影响，我有段时间常常爱发脾气或许也来源于此吧。我觉得吧，真理就在自己心中，例如自己是自己身心健康的第一负责人。</span></span></span></p><p style="line-height: 2em;"><span style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 16px;">因为</span></span></span><span style="font-size: 16px;"><span leaf=""><span textstyle="" style="font-size: 16px;">事项的繁多，超过了个人所能承担的极限。最终在人拥有比较好的责任心时就会导致</span></span></span><font size="3"><span leaf=""><span textstyle="" style="font-size: 16px;">过分关注时间，认为缺少时间，久而久之就会影响睡眠，影响睡眠的结果是很恐怖的，例如最终会掉很多头发，不过刚开始就会慢慢多一些白头发，继续则会身体免疫力变化，原本不会长痘痘的脸也会慢慢多几颗痘痘，而且痘痘好了后，休息后过几天随着压力继续又会继续长几颗。实质问题是什么？问题是对个体劳动不合理地压榨，超出了个人劳动所能承受的上限。</span></span></font></p><p style="line-height: 2em;"><font size="3"><span leaf=""><span textstyle="" style="font-size: 16px;">如果是个体是真正想实现梦想或者“伟大事业”的话，忙有忙的好，但对于劳苦大众来说，并不是每个人都是运气极好，闲有闲福也是一种选择，我也没有办法证明这个观点是对的，我很害怕去猜测这种未来无法预测的话题。只能说，如果某一类环境影响了自己的身心健康，必要时一刀两断，该溜就溜估计也不是啥坏事情。</span></span></font></p><p style="line-height: 2em;"><font size="3"></font></p><p style="line-height: 2em;"><font size="3"><span leaf=""><span textstyle="" style="font-size: 16px;">毕竟人生苦短，美好的日子与回忆极少，但拥有一个健康的生活体验也是一件幸福的事情。</span></span></font></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>


<p><a href="%27%27">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=56724925&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485741%26idx%3D1%26sn%3D6e51e28167a3f99a1219e4c240e731ea">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Tue, 03 Feb 2026 15:31:00 +0800</pubDate>
    </item>
    <item>
      <title>从“检测恶意”到“发现异常”：基于 Novelty Search 的威胁检测新范式</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485736&amp;idx=1&amp;sn=a4986915799fd777dcbcbe5f839a6c95</link>
      <description></description>
      <content:encoded><![CDATA[<p>原创 <span>jishuzhain</span> <span>2026-01-31 16:58</span> <span style="display: inline-block;">广东</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=e316733f&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0h464kSQsqF1ialSvePJe0JjvQP85yOzczFoDQ0zBNk5WsUzQ8WdXujD8T4ohKuH9XoaMyUe26EgdQ%2F0%3Fwx_fmt%3Djpeg"/></p>
  
  <p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">一年前有个想法，当初仅仅只是简单记录了粗糙的文字，随着对威胁检测领域地不断思考，基于认知优先与跨领域理论反证推导的思路持续对当初自己的想法进行了进一步的扩展与论证，记得2023年初自己一开始不知道威胁检测是如何实现的，也不知道它最终能真正做出效果所需要的路径是什么，我就想呀想，失败一次又得到一些经验。我现在明确得到的要诀还是基于哲学完备的前提下针对特定问题的解法所提出的想法可以天马行空甚至于脑洞大开，但是要快速实践去验证。我有这个动作还是因为有不断地思考练习，形成自己的习惯。本文不是工程落地的最佳实践指导，千万不要对号入座。</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">一提到威胁检测就会过分关注检出率，就像考试一样，分数明明白白可以实现排名。比如我以前一上来就是关注检出率，直接关注恶意性，我要一次性就能检出恶意软件且误报率极低。一次次的尝试最终的结果一定是失败的，以下是我对失败原因的深度思考，失败原因的本质如下：</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">绝大多数真实系统中，“正常”本身不可定义、不可收敛、不可稳定。今天看到的主流威胁检测表面上是检测恶意，实际上是在受控条件下，用异常或相似性替代“正常”。正常行为是时间依赖的、环境依赖的、个体依赖的，“正常”本质上是：人 + 业务 + 时间 + 历史 + 机器 的函数。这意味着没有全局正常模型，仅依赖AI算法的威胁检测系统仅仅只是一个子集，现实情况是根本没有办法完整模拟出所有的全局正常的弥合函数，那必定100%无法分割出“正常”与“恶意”的明显边界，不完美的结果意味着肯定存在无法避免的误报，直接用于实时威胁检测的情况下随着时间推移肯定会出现误报隐患。</span></span></p><p style="text-align: left;line-height: 2em;"><span style="font-size: 16px;"><span leaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.2712962962962963" data-type="png" data-w="1080" data-imgfileid="100002087" src="https://wechat2rss.xlab.app/img-proxy/?k=929277c7&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0jgmpLUMWDUrB3rFMHmZL7AqH77lPNWPJSVe0vaL3MojAgZH5icibiafgPwg77K2g8A0rA7Bk6gdu1dg%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">威胁检测的难度可以分类为容易的、一般的、困难的，容易的应当基于传统路径实现覆盖（主流杀毒软件一直在持续投入的事项），一般的可以付出一些成本后使用先进方法实现覆盖，至于困难的，在实现问题抽象建模以及哲学完备后我会优先选择本文提到的思路进行实践指导，更多地将其应用于高级威胁发现或者主动狩猎APT型恶意软件，对实时性要求偏低可以有更多的资源用于实验。</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">在当前主流的恶意软件检测体系中，无论是基于特征的杀毒引擎、基于规则的检测系统，还是近年来被广泛讨论的 AI / 深度学习检测模型，其核心建模方式几乎高度一致：</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">——将恶意软件检测问题视为一个“分类问题”。</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">然而，在真实的对抗环境中，这种建模方式正在系统性失效。攻击者不再追求功能创新，而是以“最大限度接近正常”为目标，通过混淆、虚拟化、语义保持变换等手段，使样本在统计分布上不断向良性样本靠拢。最终的结果是：模型越来越复杂，但确定性却越来越低。</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">本文尝试跳出“是否恶意”的二元判断框架，借鉴 Novelty Search（新颖性搜索）算法的核心思想，从认知机制、统计建模和工程可落地性三个层面，系统性地重构威胁检测问题的定义方式。</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;color: rgb(2, 30, 170);font-weight: bold;">一、人脑是如何判断“这是恶意的”？</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">在实际分析工作中，经验丰富的分析人员往往并不是通过“是否命中某条规则”来判断恶意性，而是基于长期积累的经验形成一种近似直觉的判断：</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">“这个文件看起来不对劲。”</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">这种判断并非玄学，而是高度依赖以下三点：</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">1. 对“正常行为”的深度内化；</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">2. 对历史恶意样本的相似性记忆；</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">3. 在特定上下文中对概率的偏向性判断。</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">换句话说，人脑并不是先判断恶意，而是先排除正常。</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;color: rgb(2, 30, 170);font-weight: bold;">二、为什么工业界很少“从正常出发”？</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">一个常见的疑问是：既然正常行为更稳定，为什么威胁检测系统不直接以正常性建模为核心？</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">答案并不在于“不可行”，而在于“历史工程路径依赖”。</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">正常行为空间是高维、开放且不断演化的；而恶意样本在统计上往往更加结构化，更容易被标注、被训练、被评估。</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">但这是一种工程妥协，而不是理论最优解。</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;color: rgb(2, 30, 170);font-weight: bold;">三、Novelty Search 的核心思想</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">Novelty Search 最早提出于进化计算领域，其目标并非寻找最优解，而是持续探索“与已知不同的解”。</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">这一思想与恶意软件检测存在天然的契合点：</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">我们真正关心的，并不是“它是否属于某个已知家族”，</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">而是“它是否显著偏离了我们对正常世界的认知”。</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;color: rgb(2, 30, 170);font-weight: bold;">四、从分类问题到发现问题</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">在新的建模范式下，恶意检测不再是一个输出标签的函数，而是一个持续累积证据的过程：</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">1.构建正常性数据</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">通过历史良性样本，构建稳定、低维、可解释的正常行为空间（人脑并不存储“正常全集”，人脑只存储“危险模式的压缩表示”）。</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">2.新颖性梯度评估</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">任何未知文件都被视为对该流形的扰动，其“异常程度”是连续量，而非二值。</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">3.概率偏向累积</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">当一个样本在多个独立视角下持续表现为高新颖性（这里定义为不合理性），其被归类为恶意的后验概率迅速上升。</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;color: rgb(2, 30, 170);font-weight: bold;">五、这种方法为什么有可能是“可落地的”？</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">与黑盒 AI 模型不同，该体系具备以下工程优势：</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">- 不依赖精确标签；</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">- 可与现有规则、模型、沙箱并行部署；</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">- 输出的是“异常证据”，而非不可解释的分数。</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;color: rgb(2, 30, 170);font-weight: bold;">六、结语</span></span></p><p style="text-align: left;line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">恶意软件检测的核心难题，从来不是“模型不够复杂”，而是“问题被错误建模”。当我们不再执着于“是否恶意”，而是专注于“是否异常”，恶意样本反而会自然地浮现出来。这或许不是一条最热闹的道路，但极有可能是一条更接近问题本质的道路。</span></span></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>


<p><a href="%27%27">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=11b0357b&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485736%26idx%3D1%26sn%3Da4986915799fd777dcbcbe5f839a6c95">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Sat, 31 Jan 2026 16:58:00 +0800</pubDate>
    </item>
    <item>
      <title>剥离威胁检测的AI“泡沫”</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485733&amp;idx=1&amp;sn=7d1efe89407a8eb09792be981789f9b7</link>
      <description>我有资格写一点自己对于威胁检测领域涉及AI赋能的看法，主要是源于最近三年在威胁检测方向的接触与思考。</description>
      <content:encoded><![CDATA[<p>原创 <span>jishuzhain</span> <span>2026-01-30 16:28</span> <span style="display: inline-block;">广东</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=e316733f&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0h464kSQsqF1ialSvePJe0JjvQP85yOzczFoDQ0zBNk5WsUzQ8WdXujD8T4ohKuH9XoaMyUe26EgdQ%2F0%3Fwx_fmt%3Djpeg"/></p>
  
  <p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">我有资格写一点自己对于威胁检测领域涉及AI赋能的看法，主要是源于最近三年在威胁检测方向的接触与思考。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">首先抛出文章的主旨或者说是“结论”，</span><span textstyle="" style="font-size: 16px;color: rgb(255, 0, 0);">AI在威胁检测方向的应用多数是泡沫</span><span textstyle="" style="font-size: 16px;">，更多时候是为了硬蹭AI这棵大树而选择的结果，比如竞争对手的公司有推出类似产品，而作为竞争者无形中也需要“拥有”，至于效果好不好，因为有盲区所以很难得到真实的能力结果，技术差短时间不影响营业额。比如决定你的威胁检测系统的AI检测赋能有没有价值的人往往不是最早真实遇到痛点的客户，而是所在组织的更高层级的管理人群，唬弄得过去就认可价值满满，呈现的方案与效果未能满意就继续修改尝试，不在乎能不能落地，人满意就行。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">虽然有这类普遍现象的发生，但肯定有达成平衡的AI检测应用在落地与解决现实里真实的痛点，网络安全行业是个特殊的行业，软件产品开发完成后基本上长时间不需要投入大量的维护，当时当下就已经解决了需要解决的问题，如果不能解决问题那么该软件产品就不会存在。而网络安全领域就不同了，需要持续变化，这是比较头疼的事情，能力不进步或者不迭代就等于没有能力，就比如5年前离线的网络安全产品现在还能使用吗？目前仅有少部分方向或者任务在拥有AI技术或思想加持的情况下，与以往的路径或者成本以及效果相比得到了飞跃，但远远还没有达到质的飞跃，如果说已经有质的飞跃与苗头，那么当前只能将其归功于大型语言模型（LLMs）的进步，在数据文本理解层面，比之前的威胁检测（传统AI或新型AI算法）更胜一筹，这是有目共睹的，完全经得起考验，并不是一篇外发的宣传文章或者市场营销的PPT材料所能伪造的。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">市场的残酷在于成本，例如人的时间以及劳动力的投入，每一种因素或者要素都是成本与投入的数学公式，这个公式玩明白了就能活下来。虽然大型语言模型（LLMs）的任务理解能力已经接近于接受过特定技能训练的人员面对的特定任务时所需的知识汇总与信息决策能力，但是经济账是一定要算的。威胁检测领域如果采用大型语言模型（LLMs）的成本超过了原本的人力投入但收获的效果却又与传统路径所达成的效果并没有拉开很明显的差距，此时还能高呼这是颠覆网络安全行业的威胁检测范式吗？答案肯定是不会，它现阶段也仅仅是满足特定要求的前提下去解决已经在用传统方法解决的“旧问题”而已，抛开成本谈贡献是耍流氓。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">这里的旧问题指的是经常在社会活动中出现的承载数字资产的机器被入侵事件或者是被破坏影响完整性的事件，这里传统路径与新型技术的贡献占比肯定不是55开的局面，甚至于大部分问题都已经由传统路径解决了，而极少部分难题可以由新型技术解决。那些传统路径解决起来比较麻烦或者成本投入很大的难题，由新型AI技术解决了才是值得肯定的应用。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">所以这里的结论是如果传统路径都没有解决好的旧问题，妄想依赖新型AI技术（例如大型语言模型）来彻底解决大概率是痴人说梦，一方面是经济账一算下来还比当初方案更贵，另一方面购买产品或者服务的客户满心欢喜使用了厂商新型的产品，据说效果惊人，实际使用下来该漏的漏，原本传统路径可防御的问题在新型产品上竟然无效了，即使是偶然发现新型攻击被防御，整体而言，使用起来依然是胆战心惊，保不齐哪天就露馅了，这是不注意建设底层稳健防御系统层的后果，企图依赖于新型技术解决旧问题做到一鸣惊人，而实质是类似于竹子外强中干，脆弱问题得不到解决。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;color: rgb(2, 30, 170);">过度的捧高新型AI技术在威胁检测领域的地位与作用，直接忽视了强大且稳健的威胁检测防御系统是依赖多层或者多级别防御的，强调的是协同作战，单兵作战已经被现实的网络安全威胁证明了无疑是痴人说梦。因此基础不牢地动山摇，忽视的后果无疑是浮沙筑高台，这是想要表达的第一个在威胁检测内的AI“泡沫”。</span></span></p><p style="line-height: 2em;"><span style="font-size: 16px;"><span leaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="1.5" data-type="png" data-w="1024" data-imgfileid="100002082" src="https://wechat2rss.xlab.app/img-proxy/?k=c4ed9744&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0h2AApZg6qyH8x0N3QXwEZs72u7zge2YVmTLcUbacAJXvcNtW8ibxkJmEgUPYkhVkZCw4cqZiaNDK1Q%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;color: rgb(2, 30, 170);">第二个在威胁检测内的AI“泡沫”是误报率，</span><span textstyle="" style="font-size: 16px;">如果一款威胁检测系统（AI赋能）真正在现实里发生的误报率没法足够低，例如病毒查杀需要低于万分之一的误报率（看组织对误报的容忍程度），而网络流量检测时的误报率则要更低。误报率不达标随之而来的就是运营灾难，每天一上班打开威胁检测页面，发现一大堆的告警信息，此时你慌了，所在的公司被入侵也表明自己的工作（饭碗）不保了。内心慌得一批，但其实绝大部分都是误报，持续对工作充满责任心一个个处理告警信息花去了大半天时间，最终还是放弃了，牛逼的甲方企业可以摇来乙方技术支持屁颠屁颠解决售后问题，而一般的企业只能认倒霉了，默想着现在买个安全产品即使放着心里也安心吧。威胁防御的本质是让企业更专心提高生产，相反成本比以前投入更大了。最终又变成了人海战术处理的信息灾难，旧威胁持续泛滥的情况下继续开发新服务售卖给客户，打着高级的标签，让人一看自己现在拥有的安全产品好像比较low，确实差那么点意思呀。内心里憧憬着好像一旦购买了该服务，以后威胁防御就不用自己犯愁了吧，美滋滋。</span><span textstyle="" style="font-size: 16px;color: rgb(2, 30, 170);">不管是什么目的需要建设威胁防御体系或者系统，最重要的一点凡是抛开误报率谈效果的威胁检测（AI赋能）都是耍流氓，谁用谁难受。</span></span></p><p style="line-height: 2em;"><span style="font-size: 16px;"><span leaf=""><img class="rich_pages wxw-img" data-aistatus="1" data-imgfileid="100002083" data-ratio="1.5" data-w="1024" data-type="png" src="https://wechat2rss.xlab.app/img-proxy/?k=5e621191&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0h2AApZg6qyH8x0N3QXwEZsibke2KAWGmpic63fgz2LW9NtQnhCMiaiakAUD3B3ibSic2BciapSQkeTXkt0Q%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;color: rgb(2, 30, 170);">第三个在威胁检测内的AI“泡沫”是新的技术一定是最好的，而旧技术是必然需要抛弃的，我们要做独一无二的，“创新”的事情，别人有的我嗤之以鼻，我做别人没有的才能新开出一条路。</span><span textstyle="" style="font-size: 16px;">我对此不予置评，我的观点依然还是在现阶段的条件下，成本与资源配比的条件下能选择的技术就是最好的，能真正解决问题并达到最大确定性程度的才是最合适的。原本就是解决问题作为核心指导思想的路径，却把新的、创新常常放在第一位，一味地强调某个对象意味着本身极度缺乏这个对象。这个现象的本质是什么？行业上升期的投机取巧在以前被证明可以容易获利而已，一招鲜吃遍天的下行期也总有一天吃不动了，这类变化往往需要10年左右的窗口。新型AI技术是如何来的？是解决它们那个具体难题而发展出来的，当这类技术一出现就表明当前那个方向的最难的难题已经有了新的解法，至于能不能更好更合适地解决其余行业的难题需要细致分解问题并开始实验，投机取巧或者说技术投机分子只有极少数能真正吃到红利，大部分都被追赶趋势或者不关注核心问题本质的发展所淘汰了。</span></span></p><p style="line-height: 2em;"><span style="font-size: 16px;"><span leaf=""><img class="rich_pages wxw-img" data-aistatus="1" data-imgfileid="100002084" data-ratio="1.5" data-w="1024" data-type="png" src="https://wechat2rss.xlab.app/img-proxy/?k=239622d8&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0h2AApZg6qyH8x0N3QXwEZsdiaOAcLiaL9ydb8f5pjLkticDnEE7icZSeWYsrg1dFyDxl8vq5yibSAMgQQ%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">有感写点碎碎语</span></span></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>


<p><a href="%27%27">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=5e2fa39d&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485733%26idx%3D1%26sn%3D7d1efe89407a8eb09792be981789f9b7">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Fri, 30 Jan 2026 16:28:00 +0800</pubDate>
    </item>
    <item>
      <title>想思考一下“误报”</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485728&amp;idx=1&amp;sn=15fff33382460dd92d5983002d83b8ab</link>
      <description>我是有资格谈论误报的，毕竟这三年经历了好几起存在影响的误报。一遭遇误报事件，我就会全身发麻，毕竟不是什么好事情。</description>
      <content:encoded><![CDATA[<p>原创 <span>jishuzhain</span> <span>2026-01-26 17:43</span> <span style="display: inline-block;">广东</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=e316733f&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0h464kSQsqF1ialSvePJe0JjvQP85yOzczFoDQ0zBNk5WsUzQ8WdXujD8T4ohKuH9XoaMyUe26EgdQ%2F0%3Fwx_fmt%3Djpeg"/></p>
  
  <p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">我是有资格谈论误报的，毕竟这三年经历了好几起存在影响的误报。一遭遇误报事件，我就会全身发麻，毕竟不是什么好事情。</span></span></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">误报在各种各样的系统里都会存在，在这里我仅仅谈论威胁检测系统里会出现的误报对象。</span><span textstyle="" style="font-size: 16px;color: #f00;font-weight: normal;">为什么会出现误报，这是一个非常值得深入思考以及研究的问题。如果不对误报的本质进行思考或者研究，即使威胁检测方向出现新技术解决旧问题的时候依然还是难逃误报的影响。</span><span textstyle="" style="font-size: 16px;">接下来写一写误报的本质是什么，尽量以简单的话语进行描述。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">误报的本质是人脑对处理信息后发生的决策错误，威胁检测系统是人脑对信息决策任务的另一种复现。人脑对事物规律进行总结的时候最理想的状态是能抽象成1个函数，这个函数细节可能非常复杂，但是一旦给定输入，那么它的输出一定是对应函数功能的。而回到现实，威胁检测系统仅仅是人脑的另一种部分复现，自然无法完整抽象出这个复杂函数系统。于是乎，函数细节里就会存在裂纹，这些裂纹就会引起输入与输出的不对应。慢慢地随着信息决策完成后输出就会偏离正确的输出，这个结果就是误报。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">既然理论上可抽象出1个函数完整复现信息决策过程，但基于现实情况，就不可能存在完整完美的函数，误报是必然会发生在现实各种各样的系统里的，威胁检测系统也不例外。误报的本质简单梳理完成后，当前就可以做到心中有数了。误报是会存在的，躲都躲不掉，没有办法拥有完整完美抽象的信息决策函数，任何系统只能在往减少误报的这个方向上前进。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">举个例子便于理解，交通信号灯可以建模一个非常简单的方程式函数，闯红灯一定对应于违规行为。也可以再添加1个变量输入，变成一个多元方程式，如果有紧急事件，车主只能闯红灯，此时也可以解决这个现实模拟抽象成函数的问题。而地铁里安检行为，手拿着扳手或者工具，此时如何才能不依赖直接拒绝乘车的行为方法而利用其余方法快速定性乘客是否有影响公共安全的行为呢？答案是很难，这类情况的建模难度已经超过了上述交通信号灯案例，很可能是一个多元复杂性方程，因为抽象现实问题建模会复杂，所以就会有“误报”，结果往往会偏离实际正确的结果。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;color: #021eaa;">误报会存在，无法避免，但是依然可以基于误报对象构建一套漏斗式模型解决出现误报的可能性</span><span textstyle="" style="font-size: 16px;">。注意这里写的是“可能性”，这一套抽象的漏斗式模型也是1个没有完整完美的抽象函数，不过对于解决现实问题其实已经够了。</span></span></p><p style="line-height: 2em;"><span style="font-size: 16px;font-weight: bold;"><span leaf=""><img class="rich_pages wxw-img" data-aistatus="1" data-imgfileid="100002079" data-ratio="0.6666666666666666" data-w="1080" data-type="png" src="https://wechat2rss.xlab.app/img-proxy/?k=cb880b15&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0hspmEiayntiaXcqq1jlia3fO0bYG4jP0fFqn3h6DyPEhDFpSDEENmhOfgDaygiaiagsSBIiaI2HnyPssRg%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></span></p><p style="line-height: 2em;"><font style="font-size: 16px;"><span leaf="">漏斗模型的本质是过滤，比较容易理解，威胁检测系统给出了1000个结果，此时送入漏斗模型，发现可以逐层减少到20个结果，此时就说明初期解决误报有了效果。举个例子，1000个结果初期发现大部分已经在白文件库内，当然可以去除大部分结果（白文件数据库放前还是放后可以根据需要调整）。剩余的部分发现文件存在一定“热度”值，也可以根据合适的策略过滤掉这部分。最终进入“降误报”系统，继续过滤掉部分结果，最终威胁检测系统给出了它的最终结果。</span></font></p><p style="line-height: 2em;"><font style="font-size: 16px;"></font></p><p style="line-height: 2em;"><font size="3"><span leaf=""><span textstyle="" style="font-weight: bold;">误报的本质以及为了解决误报而抽象构建的思维模型已经完成了，接下来就是实际应用时会遇到的情况。</span></span></font></p><p style="line-height: 2em;"><font size="3"><span leaf="">误报无法避免，这个本质已经论证过了，但是误报知名软件厂商的文件会不会很离谱？例如微软系统的正常文件或者谷歌软件的一些组件文件。<span textstyle="" style="color: #021eaa;">每次遇到这类情况都会头皮发麻，出现此类事件的本质是违背事物发展规律造成的结果。</span>数据安全防护机制会存在对数据重要性进行数据分级处理，而针对“发生误报”这个对象时却没有任何预先演练定级，反推出威胁检测系统里可能会出现的误报事件等级来源在哪里？哪些是最不应该发生的误报？哪些是可以允许发生的误报等等，这些分级并没有认真投入导致了惨痛教训。</span></font></p><p style="line-height: 2em;"><font size="3"><span leaf="">吃过亏不一定有经验，因为教训引起的成本比较低，不够痛。但我经历了此类事件后确实对这类现象有了深刻的认识，发现了本质是什么。对误报现象的处理不仅仅是技术与工程方向的难题，同时也是个体所处环境影响共同作用的结果。</span></font></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>


<p><a href="%27%27">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=7fd0a2fa&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485728%26idx%3D1%26sn%3D15fff33382460dd92d5983002d83b8ab">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Mon, 26 Jan 2026 17:43:00 +0800</pubDate>
    </item>
    <item>
      <title>利用数字签名增强杀毒效果</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485725&amp;idx=1&amp;sn=feaa65d11a9293674e0c9b0a97ea9bdf</link>
      <description>最近三年投入在威胁检测与杀毒能力建设方向，喜欢思考如何能解决最实际的网络安全问题，尽极大可能地提高检测系统的杀</description>
      <content:encoded><![CDATA[<p>原创 <span>jishuzhain</span> <span>2026-01-22 17:36</span> <span style="display: inline-block;">广东</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=e316733f&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0h464kSQsqF1ialSvePJe0JjvQP85yOzczFoDQ0zBNk5WsUzQ8WdXujD8T4ohKuH9XoaMyUe26EgdQ%2F0%3Fwx_fmt%3Djpeg"/></p>
  
  <p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">最近三年投入在威胁检测与杀毒能力建设方向，喜欢思考如何能解决最实际的网络安全问题，尽极大可能地提高检测系统的杀毒能力与效果。为此基于现实情况将以往思考过程以及想法成文记录下来，一方面是可以记录保存，另一方面时间是最好的检验手段，经得住时间考验的想法以及快速实践落地才是最符合当时当下的最佳实践。想法可以不拘一格，但是一定要快速实践，不然就是空中楼阁。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">关于数字签名这个对象，我以前已经写过几篇文章进行了记录，不过趋向于碎片化，行文不成体系。在这里我主要关注解决现实问题，利用对象是“数字签名”。数字签名的出现本身就是为了解决信息安全的本质问题，信息安全三要素（CIA三要素）指的是机密性（Confidentiality）、完整性（Integrity）和可用性（Availability），是信息安全领域的基石模型，旨在确保信息不被未授权访问、不被篡改，并能被授权用户及时获取，而数字签名解决的就是完整性这个维度。具体是利用密码学手段验证文件或者程序是否完整，是否被恶意篡改。一旦数字签名验证流程通过，那么说明当时当下该文件是未曾被篡改的，当前状态它是“可信”的。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">一种手段的出现必然引起新的攻击面，用数字签名保护自己的文件不被篡改也是如此，基于可信这个表征信息，自然也会出现被用于其余恶意目的的案例。例如如下：</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">1、合法的数字签名被盗取，这类数字签名就可以给恶意程序加上有效可被信任的数字签名了。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">2、冒领数字签名，尽力伪装成具有合法的数字签名的各类信息，人一不留神就会认为这个是合法的官方来源签名。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">3、密码学漏洞，用于数字签名的密码学算法存在缺陷，可以被绕过，实际变成数字签名流程全部通过且合法，但是最终保护的文件并不是当初合法的文件。此类案例过于罕见，按照概率来说基于等同于不可能事件。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">在主流操作系统里，MacOS只有存在数字签名才能安装App，Windows有些宽松，只针对权限与破环力更高的驱动文件要求具备数字签名才能正常安装（老版本另外说），而Linux系统不管这些，完全给用户拥抱细节，只要用户愿意就可以随意折腾，所以攻击者还没有开始实施破坏就需要面对数字签名这道关。既然数字签名是“天然”地如此重要，那么肯定要利用好这个工具才可以。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;color: #f00;">威胁检测系统顾名思义是要检出威胁的，检出威胁表明有概率是威胁，为什么是有概率，当前就没有一个检测系统能保证100%检出的威胁是真正的威胁，没有任何误报可能，可以说能无限地逼近这个理论值，但是受限于现实条件不能完全逼近甚至于等于这个值。</span><span textstyle="" style="font-size: 16px;">我们正向思考一下，既然数字签名的作用就是表明该文件不曾被篡改，那么基于可信链路，如果该文件的最初公开源头也是可信的，是不是就可以基于可信链路将其归类到正常文件呢？此时它距离威胁文件有很远的边界。现在将问题进一步抽象，问题是公开的源头是否可信？如果能证明公开的源头可信，那么基于该数字签名所签署有效并被关联的所有文件均可被认为是可信文件，属于正常文件。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">好了，这一条链路理清楚之后。现在对于威胁检测系统来说就是构建自己的“白库”，也就是正常文件数据库。为什么需要“白库”，举一个例子，现实世界里计算机软件必然存在三种状态，一种是纯恶意的计算机软件，也就是大家常说的病毒木马等威胁。第二种是纯解决现实问题而编写的计算机软件，它们不符合法律里对计算机病毒的定义，那么它就可以被归类为正常计算机软件范畴，也就是我们刚刚提及的“白库”。第三种就是非黑非白，都涉及一点，处于灰色地带。因为法律明显落后于现实的案例（不然流氓软件如何能持续活跃这些多年？），所以为了对现实对象进行抽象，大家就会选择将其作为灰色软件。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">既然现实世界所有的计算机软件都是三种状态组合而成，那么如果我们将白库做得很大且准确，对于发现纯恶意或者灰色软件来说是不是就会变得容易一些呢？这是前提假设。这里举一些正向案例，例如MacOS系统里被公开的恶意软件其实不多，因为受限于一些系统限制与安全机制，攻击MacOS系统实施破坏比Windows系统要困难。没有数字签名认证就没有在MacOS系统里安装软件的资格，自然也会相对Windows平台少了很多恶意软件案例。第二个正向案例就是现实情况恶意软件很少，前提条件是除去蠕虫以及可修改内容改变自身哈希的同类恶意软件，一家大型企业里每天或者每年能出现的恶意软件是不多的，而正常文件是庞大的且增长速度更快的。这是可以统计摸索出来的，如果仅仅观察网络安全领域的市场宣传文档的信息就会被夸大的词汇或数量给带偏，每年新增500万个恶意软件，但总是不给出真正的前提条件，故意误导网民。既然黑白灰状态组成的软件占比如此悬殊，构建庞大的“白库”是不是效果会很好？这是肯定的。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">举个例子，1万个未知文件，其中有真正恶意软件的数量可能只有不到10个，如果构建的白库足够大（构建白库的思考或者思路下面会写），那么至少可以去除掉8000个文件，剩余2000个文件会被送入威胁检测系统。从1万个会被送入威胁检测系统的数量到缩减到2000个，系统性能是不是会提升？同时分母变少了，计算出现误报的概率是不是会降低？基于相同的误报率条件下，威胁检测系统产生的告警信息是不是会降低？如果一个威胁检测系统产生大量的告警无疑是失败的，因为现实情况下真正的威胁与攻击活动明显是不多的，不符合现实规律。其次是大量的告警对于运营人员来说是噩梦，相当于引入了新的“安全风险”，告警事件处理不过来等于没有处理。如果做不到这两类现象，威胁检测系统无疑是失败的系统，可以直接弃用。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">“白库”的好处显而易见，但是事物都是相对的。建设白库“费时费力”，短期很难出现明显的效果，很难在周期内向上汇报团队成果。对于追求表面效率的组织来说肯定会优先丢弃掉，把资源投入在更高优先级的事项上，于是乎建设之路一拖再拖，“白库”建设遥遥无期，最终实在是火烧眉毛了需要建设了才会抓紧时间投入。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">“白库”建设思路基于我这三年的思考与体会：</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;color: #021eaa;">第一步肯定是基于数字签名这个优秀的世界体系进行构建基础“白库”。</span><span textstyle="" style="font-size: 16px;">思想来源是别人有的系统我投入资源后拥有了，也解决了自己遇到的现实问题，这是及格线。别人没有的系统，我思考构建后又解决了现实问题，这是核心竞争力。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;color: #021eaa;">第二步是基于文件相似度构建第二层“白库”</span><span textstyle="" style="font-size: 16px;">，相似度算法可以任意选择，例如SSDEEP或者TLSH，如果你搜索互联网信息，就会发现安天公司在十多年前就撰写了专利，专门提到在哈希杀毒的背景下如何利用相似度构建云端的文件库（对象是恶意软件库）。这里的思想是基于倒金字塔模型进行构建。我们基于统计与现实情况明显能得到一个结论，现实世界里的正常文件远远多于恶意软件，而这些正常文件都具备数字签名吗？很显然不全是，那么基于数量占比它一定是以倒金字塔形状分布的。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;color: #021eaa;">第三步是基于大数据，众人拾柴火焰高</span><span textstyle="" style="font-size: 16px;">，恶意软件先天会具备隐蔽性，那么既然不希望被曝光，它的出现在数据分析统计层面肯定是热度排名靠后的，机器学习里的随机森林具有的投票机制也是类似的思想。这里的思想是基于热度，除去有些破坏性恶意软件或者蠕虫能大规模造成破坏产生热度靠前的现象外，其余现实世界里的恶意软件无不是静悄悄地来到用户计算机，然后悄摸摸地离开，能不被发现就是它的最终使命。热度思想是如果一个文件在大量客户侧里出现，那么它是恶意软件的概率就会变得很低很低，那么它会归类到哪里呢？必然是正常文件或者灰色软件。是不是很简单啊？</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;color: #021eaa;">第四步是基于我们经过数学统计或者概率获得的知识</span><span textstyle="" style="font-size: 16px;">，现实世界里真正恶意软件的比例是不高的，如果检测系统检出大量地“恶意软件”，那么需要你筛选出正常文件，扩充“白库”了，就可以涉及各种各样的数据挖掘算法或者系统帮助我们实现对“白库”的扩充。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">行文先写到这里，想感慨一下，这确实是很有意思的一种思考路径。</span></span></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>


<p><a href="%27%27">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=044d9ea1&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485725%26idx%3D1%26sn%3Dfeaa65d11a9293674e0c9b0a97ea9bdf">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Thu, 22 Jan 2026 17:36:00 +0800</pubDate>
    </item>
    <item>
      <title>使用大模型提高安全分析工作效率</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485723&amp;idx=1&amp;sn=9d1be909b371adc14351c58247f5a10a</link>
      <description>网络安全领域或多或少都需要对未知文件进行判断，区别点在于投入的时间以及所需的结论不同而已，例如我只需要判断某文</description>
      <content:encoded><![CDATA[<p>原创 <span>jishuzhain</span> <span>2026-01-20 12:06</span> <span style="display: inline-block;">广东</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=e316733f&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0h464kSQsqF1ialSvePJe0JjvQP85yOzczFoDQ0zBNk5WsUzQ8WdXujD8T4ohKuH9XoaMyUe26EgdQ%2F0%3Fwx_fmt%3Djpeg"/></p>
  
  <p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">网络安全领域或多或少都需要对未知文件进行判断，区别点在于投入的时间以及所需的结论不同而已，例如我只需要判断某文件是黑或白即可，又或者这个文件对系统造成了什么影响？对恶意软件中涉及的技术进行还原提取并用于防御等等，获取这些结论的难度系数逐步提高。我开始思考了，能否因时因地改变我的工作模式？</span></span></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">目前基于大型语言模型（LLMs）的发展依然绕不开的困境是它具有存在幻觉的概率，所以减少幻觉或者消除幻觉是首要任务。如果一开始拿来干活肯定路走偏了，因为肯定不可控。我自己应当对各种需要特定技能的工作流程定义标准，让LLM来适应我，而不是去适应LLM。</span></span></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">好了，具体问题具体分析。接下来写一些LLM如何改变工作的流程，我平时需要研判未知文件，研判的输出肯定是两种结论，一种是恶意文件另一种是正常文件。基于这两种结论就会引申出两种场景，第一种是判断是否误报？如果不是误报那就是正报了，说明检测系统正常达到目标✅。</span></span></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">第一个场景是遇到acaddoc.lsp这类AutoCAD老病毒，一开始没有深度分析过。</span></span></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.7580971659919028" data-s="300,640" data-type="png" data-w="1976" type="block" data-imgfileid="100002069" src="https://wechat2rss.xlab.app/img-proxy/?k=056621ed&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0iasB5K3RAIxef5jSycrrVdRiatmlXZsSAE2VrgGunelF8yIUq9QypksXBIOdpfmAHJRavBh9O95x2w%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">但是检测系统检出了病毒，为了避免是误报，所以需要人工介入获取到举证信息证明没有误报。此类老病毒告警的场景我觉得还是有概率出现的，如果是以前没有LLM的时代，必然需要安全分析人员介入去获取检出病毒的举证信息，之后才能将此类事件进行闭环处理。而如今出现了LLM技术，很显然是可以尝试利用起来的。我的做法是</span></span><span leaf=""><span textstyle="" style="font-size: 16px;">查看 AutoLISP 脚本内容，将其</span></span><span leaf=""><span textstyle="" style="font-size: 16px;">输入 GPT5 后给出结论（时间位于2025年上半年，此时GPT5.2还未发布），简单研判给出的举证信息获得结论结束整个研判过程，我就不需要</span></span><span leaf=""><span textstyle="" style="font-size: 16px;">分析其中的代码逻辑了。此类动作平均节省时间从</span></span><span leaf=""><span textstyle="" style="font-size: 16px;">15 分钟 --&gt; 50 秒。</span></span></p><p style="text-align: left;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.9203703703703704" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002070" src="https://wechat2rss.xlab.app/img-proxy/?k=42bf53e4&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0iasB5K3RAIxef5jSycrrVdRDwQicmCIZdbbZ4Mqdq8RnGE0qwSTaJpF7Qd3sNKlQ0GAN3cFPTRaIibQ%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><div title="Page 2" style="text-align: left;"><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{&#34;style&#34;:&#34;margin-bottom: 24px; line-height: 2em; text-align: left;&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><span textstyle="" style="font-size: 16px;">第二个场景是反馈某邮件（</span></span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{&#34;class&#34;:&#34;page&#34;,&#34;title&#34;:&#34;Page 2&#34;,&#34;style&#34;:&#34;text-align: left;&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;},&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{&#34;style&#34;:&#34;margin-bottom: 24px; line-height: 2em; text-align: left;&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><span textstyle="" style="font-size: 16px;">xxxx.eml</span></span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{&#34;style&#34;:&#34;margin-bottom: 24px; line-height: 2em; text-align: left;&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><span textstyle="" style="font-size: 16px;">）文件被报毒，需要找到举证信息。根据报毒类型，利用积累的经验确定需要分析邮件里记录的网络交互响应数据。这里的经验无外乎是邮件看附件是否有问题，邮件正文是否有超链接，或者是安全设备告警邮件，里面会内嵌捕获的数据，而这些数据往往因为特征码而被再次报毒，核心点就是见过的恶意文件越多越有经验。现在确定是需要分析响应的数据是否有异常，直接复制响应头数据后交给 GPT5 分析给出结论。发现异常表明是正报，无异常表明是误报。</span></span><span leaf=""><span textstyle="" style="font-size: 16px;">检查 GPT5 发现的恶意痕迹代码，找到邮件内容中对应的代码片段确认无误后，结束整个研判工作，</span></span><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{&#34;style&#34;:&#34;margin-bottom: 24px; line-height: 2em; text-align: left;&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><span textstyle="" style="font-size: 16px;">平均节省时间从 10 分钟 --&gt; 10 秒。</span></span></p><p style="text-align: left;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.6648148148148149" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002071" src="https://wechat2rss.xlab.app/img-proxy/?k=58b0f0ab&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0iasB5K3RAIxef5jSycrrVdR9ppjRjqCmVGcUKxAyOh0O86cgcmeL6tcJSOu0ic6eUEs6q4Kd5iaic8dg%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{&#34;style&#34;:&#34;margin-bottom: 24px; line-height: 2em; text-align: left;&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><span textstyle="" style="font-size: 16px;">第三个场景上一点难度，现在工作中需要</span></span><span leaf=""><span textstyle="" style="font-size: 16px;">分析伪代码（IDA工具输出）或汇编代码。以前没有LLM的时候，需要利用人的经验或积累的知识案例，逐步排除来确定需要分析的核心代码，分析找到的核心代码确定代码的意图，汇总整个代码流程与意图得到最终结论，整体过程较为耗时繁琐，这就是一个纯人工手工作业过程。而现在变成了</span><span textstyle="" style="font-size: 16px;text-decoration: line-through;">利用分析人的经验或积累的知识案例，逐步排除确定需要分析的核心代码，分析找到的核心代码确定代码的意图，</span><span textstyle="" style="font-size: 16px;">输入 GPT 后给出信息，对举证信息进行校验得到最终结论，整体过程较为轻松。平均节省时间从 20 分钟 --&gt; 10 秒，无疑是巨大的进步，我就可以去思考探索解决更具有挑战更棘手的问题啦。</span></span></p><p style="text-align: left;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.9907407407407407" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002073" src="https://wechat2rss.xlab.app/img-proxy/?k=1c1b3910&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0iasB5K3RAIxef5jSycrrVdRMD70bqISbbQYTicfWibHQVMvOQUVnmTH7mZC8RyiaqNg4hSmYdMu0o3ew%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="text-align: left;" nodeleaf=""><img class="rich_pages wxw-img" data-aistatus="1" data-imgfileid="100002074" data-ratio="0.6953703703703704" data-s="300,640" type="block" data-type="png" data-w="1080" src="https://wechat2rss.xlab.app/img-proxy/?k=6811be4f&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0iasB5K3RAIxef5jSycrrVdR0A2xzSwVHqCaLuZR434rv33mCx1mtGzSM1zso3OPdEGV3OEZUJhgpA%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">拆分任务流程，让LLM来辅助我，而不是全权交给它。优先解决幻觉，而不是一股脑上线，重复的事项是浪费生命的。</span></span></p></div><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>


<p><a href="%27%27">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=027591a6&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485723%26idx%3D1%26sn%3D9d1be909b371adc14351c58247f5a10a">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Tue, 20 Jan 2026 12:06:00 +0800</pubDate>
    </item>
    <item>
      <title>EmEditor带毒事件的反思与应对</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485715&amp;idx=1&amp;sn=07c37457e380f5ef96b8d95ebcbf1f57</link>
      <description>2025年12月23日EmEditor官方发布了通告，表明官网安装包被替换成恶意安装包，如果有用户下载并安装使</description>
      <content:encoded><![CDATA[<p>原创 <span>jishuzhain</span> <span>2026-01-07 12:03</span> <span style="display: inline-block;">广东</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=dde72e34&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0gJGfQASzib4MrXysbPwgQcLf7hL81S4RibuGKGlpSbJutyytZ6gjwicHyYibanNianySqxTnED6Pgle5w%2F0%3Fwx_fmt%3Djpeg"/></p>
  
  <p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">2025年12月23日EmEditor官方发布了通告，表明官网安装包被替换成恶意安装包，如果有用户下载并安装使用会引起安全风险。</span></span></p><p style="text-align: left;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.5462962962962963" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002057" src="https://wechat2rss.xlab.app/img-proxy/?k=044ddbb2&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0gJGfQASzib4MrXysbPwgQcLjUKuIKMdMibcSoiaib2zbzz5yckoELCwK6P3ccnfh0JBcWvja7NzPAkMQ%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><div style="margin-bottom: 24px;line-height: 2em;text-align: left;"><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{&#34;style&#34;:&#34;margin-bottom: 24px;line-height: 2em;text-align: left;&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><span textstyle="" style="font-size: 16px;">我从奇安信的文章里得知后依据文章提供的文件哈希下载得到这个样例文件，准备认真查看下细节，供应链事件往往是最致命的信号，如果入侵根源未能确定，残留的风险依然存在，曾经对游戏公司进行应急响应发现黑客已经入侵潜伏长达3年时间，把我震惊到了。首先依据病毒分析经验，MSI类型文件要能被恶意利用，常使用的方式是利用CustomAction字段功能，这已经在近几年非常活跃的多类恶意文件中出现过。样例文件被本地分析后明显会看出CustomAction字段的值存在不寻常的命令执行，例如执行PowerShell命令访问未知域名。</span></span></p><p style="text-align: left;" nodeleaf=""><img class="rich_pages wxw-img" data-aistatus="1" data-imgfileid="100002058" data-ratio="0.7972222222222223" data-s="300,640" type="block" data-type="png" data-w="1080" src="https://wechat2rss.xlab.app/img-proxy/?k=6544f468&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0gJGfQASzib4MrXysbPwgQcLjnZjIuyDV2XrNxEleIuhTqHb4UtBbrZpZkE0Y25QqJWMRlDhnQYUsQ%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="text-align: left;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.6046296296296296" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002059" src="https://wechat2rss.xlab.app/img-proxy/?k=54e0ea66&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0gJGfQASzib4MrXysbPwgQcLBDgiaWUhzFCwdicBDcK1zeXibiaRVyVwDWIaZnP1Fm5JGggenR2xicaH8Og%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf="" data-pm-slice="1 1 [&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{&#34;style&#34;:&#34;margin-bottom: 24px;line-height: 2em;text-align: left;&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;},&#34;para&#34;,{&#34;tagName&#34;:&#34;section&#34;,&#34;attributes&#34;:{&#34;style&#34;:&#34;margin-bottom: 24px;line-height: 2em;text-align: left;&#34;},&#34;namespaceURI&#34;:&#34;http://www.w3.org/1999/xhtml&#34;}]"><span textstyle="" style="font-size: 16px;">从2025年12月30日提供的官方最新通告分析，可以定性属于一起入侵事件，由于涉及到Web服务器资产，因此大概率还是利用弱口令或者Web应用漏洞进入或者是其余的一些组件缺陷引起被入侵成功，不过攻击者入侵成功后并没有选择挂黑页而是选择采用替换安装包的方式给受害用户中木马而牟利，EmEditor软件受众较多价值很大，攻击者对此投入了不少成本，从购买两个有效的数字签名以及多个伪装的域名来核算所需要的成本就能得到这个结论，恶意安装包执行后实现窃密也符合这类牟利意图。</span></span></p><p style="text-align: left;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.5" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002060" src="https://wechat2rss.xlab.app/img-proxy/?k=97e2b52c&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0gJGfQASzib4MrXysbPwgQcLlf1JBxMQNI7mog9kCACOIDWUibNvHs9YVoftTyU6Gyjg2rl8hYwgziaw%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">其实发生这类入侵事件其实并没有多罕见，只要搜索互联网就能发现一些公开的案例信息，类似的事件都是存在一个共性，这也从侧面暴露出对系统或者业务防护的不够，对业务进行防护需要投入成本，但短期内又很难看出真正的“价值”，没有办法量化，于是会将其优先级放置在业务后面，遵循业务优先原则，毕竟业务是企业生存的基石。事件发生后需要立马开展应急响应，文章给出的应对与举措都是非常正常且正确的，清理后门，做好安全加固，排查出真正的入侵口并及时修补，最后是设置多层验证或提醒告知用户进行核查尽量防止被篡改事件。</span></span></p><p style="text-align: left;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.42962962962962964" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002061" src="https://wechat2rss.xlab.app/img-proxy/?k=c18916b8&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0gJGfQASzib4MrXysbPwgQcL2fuW1ZiaSibuVD7yPnfyt3ae1icCTHka34ZMzWFozWQdLpoqJG5EC7Gqw%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">在我写文章的时候，无意发现又出现非官方签名的安装包57bc24f923c92fc600c2ad47fe285074，签名者为GRH PSYCHIC SERVICES LTD，这个名称肯定不是官方的名称，回连的恶意域名为emeditorltd.com。</span></span></p><p style="text-align: left;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="1.010928961748634" data-s="300,640" data-type="png" data-w="732" type="block" data-imgfileid="100002063" src="https://wechat2rss.xlab.app/img-proxy/?k=57dc96f6&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0gJGfQASzib4MrXysbPwgQcLCtUOdUYgMticBPxWsAzrWtZsqChiakCym4mdics0vCOXzicBQRlBKPiby7Q%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="text-align: left;" nodeleaf=""><img data-aistatus="1" class="rich_pages wxw-img" data-ratio="0.6583333333333333" data-s="300,640" data-type="png" data-w="1080" type="block" data-imgfileid="100002064" src="https://wechat2rss.xlab.app/img-proxy/?k=bfa9b5dc&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0gJGfQASzib4MrXysbPwgQcLgKRUoCSOwatE60hN4EDIkaRSmgTczdd5WUfjWuCSPicbfHDpMv8P0mA%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p data-pm-slice="0 0 []" style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">凡事都设想最坏的情况，假设业务被入侵了怎么办？</span></span></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">1、安装包携带的有效数字签名的名称与基线安装包的名称存在明显差异</span></span></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">2、Web业务服务器出现异常代码文件（WebShell防护防篡改方案）</span></span></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">3、用户侧哈希二次检验提示（SHA256比对）</span></span></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">4、日常持续基于基线标准自动化运营，出现异常信号及时人工介入。</span></span></p></div><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>


<p><a href="%27%27">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=b5133ddf&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485715%26idx%3D1%26sn%3D07c37457e380f5ef96b8d95ebcbf1f57">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Wed, 07 Jan 2026 12:03:00 +0800</pubDate>
    </item>
    <item>
      <title>检测恶意子文件的困境与应对方法</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485703&amp;idx=1&amp;sn=c5a7dd0873494d4f0c5c44d6a77a34c2</link>
      <description>如果你经常观察各类网络安全事件，一定会发现其中会出现对应不同平台的恶意软件，而这些恶意软件呢又时不时会释放出子</description>
      <content:encoded><![CDATA[<p>原创 <span>jishuzhain</span> <span>2026-01-02 17:44</span> <span style="display: inline-block;">广东</span></p>






  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=e316733f&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0h464kSQsqF1ialSvePJe0JjvQP85yOzczFoDQ0zBNk5WsUzQ8WdXujD8T4ohKuH9XoaMyUe26EgdQ%2F0%3Fwx_fmt%3Djpeg"/></p>
  
  <p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">如果你经常观察各类网络安全事件，一定会发现其中会出现对应不同平台的恶意软件，而这些恶意软件呢又时不时会释放出子文件，往往会关联到不定数量的恶意子文件。于是乎一旦发生一件网络安全事件就会涉及多个恶意文件，理想的事后补救场景是我们需要及时把它们全部揪出来，同时彻底清除，让受影响的资产恢复如初，这部分要求快，越快越能证明安全防护的价值，完成这些步骤仅仅是合格的网络安全厂商的及格线。我这里会摒弃网络安全市场PPT形式的吹嘘风格，聚焦于现实与事物发展变化的普遍规律，因此不会写一定能防范于未然，没有人能敢打包票。由于网络安全行业比较特殊，最新的攻击往往是人与人之间的持续对抗，由人设计的防护系统始终无法实现最完美的防御。优秀且体现现实价值的做法是在入侵前期就能被防护机制遏制，且黑客不断攻击尝试时也面临不断失败，最终被安全运营团队发现后及时人工介入加强整体防护并复盘该组织已经出现的风险。基于可验证可比对的条件下，如果以上两类场景均不及预期，那么可以说提供的网络安全防御能力是不合格的。以上的体会与思考，我们心里有杆秤即可。</span></span></p><p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">黑客或者说网络安全爱好者选择多个恶意文件实施攻击行为的目的是什么呢？答案是现实所迫，攻击的目的是非法获得控制权实施任意意图，这部分能力依赖于各类操作系统平台所能提供的能力上限，本质上想要做的越多越需要更多地编写代码实现功能，每一类代码都携带有攻击者的个人属性或编写风格。对黑客来说入侵直至成功的过程中出现越多的步骤或者动作都会进一步加大被发现痕迹的概率，因为新动作或者步骤引入了新因素，新因素就带来了新概率。但是如果将动作或者步骤压缩至最少，那么最少的步骤下必然需要信息量极大的数据载体，信息量极大又会引出同样的问题，被发现的概率变大。综合起来，不断地摸索发现适中的步骤数量与多子文件结合能获得平衡，使得入侵过程显得比较安静，不会引起注意。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">为什么恶意子文件的检测会存在困境呢？</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">检测恶意文件的本质是判定任意程序是否具有恶意意图意义的语义特性，意图是一种经过人的数据分析抽象出来的概念，换言之它无法直接被显示出来，它只能被证明出来，例如我在走路，你无法基于我走路的这个照片判断我将走向哪个方向，只有我有稍微的转身动作后你才能猜测出我可能是有往某个方向走去的意图。一旦我们获取的有意义的意图信息越多越能实现低误报地检出恶意文件，反之则会存在大量误报。恶意子文件天然就缺失部分意图，这是攻击者希望实现的目的，多个子文件实现了信息的分离，信息数量一分离，单个文件的信息含量便会直接降低，相当于实现了减法。因此针对子文件的单独检测会天然存在恶意意图语义特性少等现象，最终影响对它的检测效果。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">子文件检测或查杀效果差的原因：</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">1、如果子文件属于本地Loader（加载器），当缺失必要的上下文信息（例如命令行参数）或文件（例如依赖加载同目录的加密载荷文件），在沙箱环境无法释放出完整行为，缺失必要行为来分析意图，进而影响检测。同理，事物实质上是正反对应的，当子文件被转移到新环境时由于缺乏必要的上下文信息，理论上对新环境是无害的。恭喜，又躲过一劫。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">2、如果子文件属于data（加密载荷）类型，那么当缺失必要的上下文信息（例如依赖被Loader加载），在沙箱环境无法释放出完整行为，影响检测。同理，当子文件被转移到新环境时由于缺乏必要的上下午信息，仅仅属于数据，理论上对新环境是无害的。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">3、如果子文件属于下载器（Downloader），与之通信交互的C2服务器一旦失效，在沙箱环境同样无法释放出完整行为，一旦缺乏关键的语义意图举证信息就会影响检测。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">可以说检测恶意子文件的条件比较苛刻，因此对它的检测天然就存在困境。那么我还是想检测并把它们揪出来怎么办？恭喜你，你现在正在思考的难题也是当前网络安全威胁每天都需要面对的难题，检测恶意文件如何又快又全又准确是一个充满了挑战的问题。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">回到最初的原点，我们希望能通过意图来精确检测恶意子文件，那么我们所有的目的都是围绕这个观点来实施。2025年初提出了基于关联关系来检测MSI类型的“打包”类文件，那么这里首要采用的思路也是如此。我们基于强关联关系证明其恶意意图来论证该子文件为恶意的，通过子文件找到强关联的父文件（或者说是母体文件），父文件大概率携带充分的信息量可以基于各类手段（不限制方法，动静结合都可）来通过数据分析获取意图，只要证明了父文件为恶意的，那么进一步可以证明子文件也是恶意的。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">如果想尽了各种方法或者受限于数据有限等因素，无法找到任何与子文件关联的父文件，那么此时该如何检出恶意子文件呢？比较能想到的方法是基于相似关系来辅助检测，基于相似方法的理论基础前提是这个世界并没有那么巧合的事情，恶意子文件与现实正常文件编写的代码风格一致，或者非常相似，在极低概率的条件下我们将其归类到不可能事件，那么只要两者相似就证明它们也应当是存在强关联关系。基于这种观点，一旦我们具有恶意子文件的基础数据库，那么基于相似就可以再次判断未知子文件是否为恶意。实现相似所需要的对象或者相似性算法，可以自行发散，这里提及一下常见的。例如利用ssdeep算法证明它们的导入表函数相似，可获取的可见字符串存在极高的相似性，二进制文件整体的ssdeep值相似，利用反编译工具对其整体反编译输出得到的数据也存在极高相似等。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">如果父文件找不到，恶意子文件的基础数据库也没有收集到位，任何想基于强关联关系的方法都失效的情况下，如何检出恶意子文件呢？我们还是要回到最初的原点，通过哪些方法能数据分析来证明它的意图？专家或者其余分析人员通过反编译工具对未知子文件实现分析，在阅读工具输出的伪代码后基于知识以及经验实现代码理解分析输出结论，如果能有把握直接证明其存在恶意意图那么该问题已经解决，可判断未知子文件为恶意文件。如果无法直接证明其存在恶意意图，那么只能基于历史分析经验在脑中分析其代码编写风格，评估其编写风格是接近恶意文件还是正常软件，这个评估过程在以往往往是基于数据统计分布的方法来证明，基于专家或分析人员所见过的恶意文件编写风格的数量来反映出判断的准确性，如果以前没有见过，那么该问题无解，因为没有见过所以无法判断。2022年11月前，理解代码意图一直是很困难的事情，即使这么多年机器学习深度学习强化学习一直在进步，致力于解决现实问题，但是对于代码任务去准确理解还是不够完美，随着11月后大型语言模型（LLM）产生落地，让这类代码任务的解决引来了转机，基于LLM理解代码意图的方法来证明子文件为恶意的，已经能被证明是可行的且能达到专家级别的理解力，它解决了两种专家没有办法同时满足或再增强的能力，第一种是它见过的代码风格多（人脑不擅长大规模记忆），第二种是它具备准确的代码理解能力，本质上是新手段解决旧问题。因此如何在低成本使用LLM解决代码理解任务进而推动对未知子文件的检测是需要不断探索的路径，之前写到让AI 与 AI IDE协作提高分析效率也是属于抛砖引玉了。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">以上的过程顺利的话能解决大部分恶意子文件的检测，但是现实情况是会遇到极端情况，极端情况也是由黑客不断摸索实验得到的防检测方法。假设它将小段恶意代码嵌入在巨量正常业务代码的正常软件中，那么如何检测这个子文件呢？能解决这类极端情况往往具备极大的价值，这个问题留给读者思考吧。</span></span></p><p style="line-height: 2em;"><span leaf=""><span textstyle="" style="font-size: 16px;">世界上并没有100%安全的防护系统，我们能做到的是不断思考摸索，持续去接触研究最新的攻击与威胁，这是事物发展的规律。</span></span></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>


<p><a href="%27%27">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=c80e97ac&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485703%26idx%3D1%26sn%3Dc5a7dd0873494d4f0c5c44d6a77a34c2">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Fri, 02 Jan 2026 17:44:00 +0800</pubDate>
    </item>
    <item>
      <title>让IDA与AI IDE协作提高分析效率</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485701&amp;idx=1&amp;sn=f52f013def97c43b8396769b95b2edf7</link>
      <description></description>
      <content:encoded><![CDATA[<p>原创 <span>jishuzhain</span> <span>2025-12-19 12:30</span> <span style="display: inline-block;">广东</span></p>




  
  <p><img src="https://wechat2rss.xlab.app/img-proxy/?k=e316733f&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0h464kSQsqF1ialSvePJe0JjvQP85yOzczFoDQ0zBNk5WsUzQ8WdXujD8T4ohKuH9XoaMyUe26EgdQ%2F0%3Fwx_fmt%3Djpeg"/></p>
  
  <p style="margin-bottom: 24px;line-height: 2em;text-align: left;"><span leaf=""><span textstyle="" style="font-size: 16px;">不管是因什么原因需要接触病毒逆向分析或者未知文件研判事项，就免不了需要人或专业人员手工或者半自动的方式利用既有的知识与经验完成特定的分析流程直至获得最终的结论，最终结论会体现出两种走向：</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">1、未知文件确定为恶意文件，并提供了可以举证的信息；</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">2、没有找到任何可以举证恶意的证据，需要研判的文件并非是恶意文件；</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">以上的过程涉及比较专业的知识背景与技能，以往需要经过实践与积累才能逐步提高速度或者分析的准确度。在如今（2022年11月至今）AI大模型（LLM）的全力发展与先驱者不断地以解决现实问题作为突破的目标下，AI发展的结果让我大为震撼，以前专业人员常常会遇到的通用且基础的问题现在解决起来变得简单多了，新方法解决旧问题一直是发展的基础，人可以将自己宝贵的时间投入到自己认为最有价值的事项上了。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">如下项目提供了一种思路，经过我的测试目前没有发现任何误判案例，可以说是极大地提高了解决通用问题的速度。使用的工具不限制，这其实给我的启发</span></span><span leaf=""><span textstyle="" style="font-size: 16px;">是如今AI发展与探索非常火热，随之AI大模型以及各种配套的工具链变得很多，现实世界里这些辅助技能是不缺乏的，但自己的想法变贫瘠了，少了，麻木了，慢慢地丧失了对解决问题的探索欲望。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">项目地址：</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;"><a href="https://github.com/P4nda0s/IDA-NO-MCP" target="_blank">https://github.com/P4nda0s/IDA-NO-MCP</a></span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;font-weight: bold;">简单介绍：</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">开源工具 &#39;IDA NO MCP&#39;，旨在简化AI逆向工程流程。该工具通过将IDA反编译结果导出为源码文件，直接适配AI IDE，优化了索引、并行和切片等功能。核心理念是回归代码本质，利用LLM原生语言（Text、Source Code、Shell）实现简单、快速、智能且低成本的逆向工程。工具无需额外配置，支持导出反编译C代码、字符串表、导入导出表及内存hexdump，并建议在IDB目录下添加更多上下文以增强AI辅助效果。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">IDA我选择了9.0版本，目的是需要导出反编译的代码作为输入，随后使用VScode+Copilot来实现简单的AI IDE功能。</span></span></p><p style="text-align: center;" nodeleaf=""><img data-imgfileid="100002041" class="rich_pages wxw-img" data-ratio="0.29635499207606975" data-s="300,640" data-type="png" data-w="631" type="block" src="https://wechat2rss.xlab.app/img-proxy/?k=d773c263&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0h464kSQsqF1ialSvePJe0JjlricTNMRuUDBRf4GbE7AEgqILMujKKnadN89PrN4NVzAvVLsUsLnXXg%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p style="text-align: center;" nodeleaf=""><span textstyle="" style="font-size: 16px;"><img data-imgfileid="100002042" class="rich_pages wxw-img" data-ratio="0.47846153846153844" data-s="300,640" data-type="png" data-w="650" type="block" src="https://wechat2rss.xlab.app/img-proxy/?k=86c644e5&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0h464kSQsqF1ialSvePJe0JjqthvE4V5Qq1bowL7sVaClKF4qzKep6uvPWtBykBfibLV83QiaHduhdJQ%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">Copilot是VScode的扩展插件，比较容易安装，需要注意的是需要使用自己的github账号登录，如果使用频繁最好付费增强可用性。</span></span></p><p data-pm-slice="0 0 []"><span leaf=""><span textstyle="" style="font-size: 16px;">prompt：分析所有代码的意图，最终给出整体意图？</span></span></p><p style="text-align: center;" nodeleaf=""><img data-imgfileid="100002043" class="rich_pages wxw-img" data-ratio="1.12483039348711" data-s="300,640" data-type="png" data-w="737" type="block" src="https://wechat2rss.xlab.app/img-proxy/?k=1edcedc7&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0h464kSQsqF1ialSvePJe0JjtNH1iaq78ib9yABLia1uibFmxZFNITiaNVm9Tibz65joa7n3mh07zzWMKyQg%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">对于非恶意文件的分析结果，处理时间为6分钟。我随后人工再次验证确定，无误判。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">整体意图总结：</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">这个程序的整体意图是作为C++标准模板库（STL）的配置测试，用于验证向量（vector）和关联容器（如map或set）的功能正确性、内存管理和算法优化。它是Qt5构建过程中的一个测试工具，通过模拟STL操作（如元素插入、搜索、平衡树操作和SIMD优化）来确保STL库在特定编译环境（Windows x64，使用vcpkg）中正常工作。如果测试通过（无异常返回0），则表明STL与编译器和运行时的集成兼容。</span></span></p><p style="text-align: center;" nodeleaf=""><img data-imgfileid="100002044" class="rich_pages wxw-img" data-ratio="0.4824074074074074" data-s="300,640" data-type="png" data-w="1080" type="block" src="https://wechat2rss.xlab.app/img-proxy/?k=4c2f9791&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0h464kSQsqF1ialSvePJe0JjmNwLibLOIOy9FxjfKkdCCEGcn4gj0KJGIFcPf8icRiawHcp2aE1dLQhgg%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">分析.NET未知程序</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">709b34688047b3c8aec82bf8efda0642 是.net平台程序，需要使用dnSpyEx导出反编译的源码。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">整体意图总结：</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">这是一个用于Windows系统的恶意软件，旨在隐秘运行、与远程服务器通信、解密并执行有效载荷，可能包括窃取数据、安装后门或部署勒索软件。它使用混淆技术规避反病毒软件和逆向分析。强烈建议不要执行此代码，并使用杀毒软件扫描隔离。如果是从未知来源获取，请报告给安全机构。</span></span></p><p style="text-align: center;" nodeleaf=""><img data-imgfileid="100002045" class="rich_pages wxw-img" data-ratio="0.4824074074074074" data-s="300,640" data-type="png" data-w="1080" type="block" src="https://wechat2rss.xlab.app/img-proxy/?k=d21e966b&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0h464kSQsqF1ialSvePJe0JjTX5hL0y0O6xxPHtPO9OF2KIVfShQD7kVL69XmdPzH30UZo1SXs2pVA%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">我随后人工再次验证分析是否误判？直至确定是恶意的，我也用GPT5.2分析了一下，分析结论确实比较准。</span></span></p><p style="text-align: center;" nodeleaf=""><img data-imgfileid="100002046" class="rich_pages wxw-img" data-ratio="0.649074074074074" data-s="300,640" data-type="png" data-w="1080" type="block" src="https://wechat2rss.xlab.app/img-proxy/?k=d243bb98&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0h464kSQsqF1ialSvePJe0JjCagXpDibg3ksENd460zv6wfiaKzFaBwiasIHHX1RWplHWcEA4eJ1du63A%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">携带的数字签名也关联了其余恶意文件，判定恶意的结论无疑问。</span></span></p><p style="text-align: center;" nodeleaf=""><img data-imgfileid="100002047" class="rich_pages wxw-img" data-ratio="0.45390625" data-s="300,640" data-type="png" data-w="1280" style="width:540px;height:245px;" type="block" data-croporisrc="https://mmbiz.qpic.cn/sz_mmbiz_png/dib9GLOoSY0h464kSQsqF1ialSvePJe0JjSUAHuC1GP1epnBuaxTVBDbYqHCMdeuvraovZ7sAMeJbzR4xePylGtA/0?wx_fmt=png&amp;from=appmsg" data-cropx2="1677.923875432526" data-cropy2="761.280276816609" src="https://wechat2rss.xlab.app/img-proxy/?k=36494b63&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0h464kSQsqF1ialSvePJe0JjQicjD7lSXqD4AuAoOEP3epq6qazRfWf1PMnNywWKYUZU5qyc3e3nRbg%2F640%3Fwx_fmt%3Djpeg"/></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">分析Rust编写的dll劫持的恶意文件，我随后人工再次验证确定，无误判。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">整体意图：</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">这个DLL已被恶意软件感染，伪装成合法的Sciter引擎，但实际充当后门或蠕虫：</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">恶意目的：窃取系统信息（如进程、注册表、网络数据）、建立持久访问（通过服务和注册表）、可能传播到其他系统（蠕虫行为）。循环通信逻辑表明它可能作为C2代理，向攻击者控制的服务器报告或接收命令。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">感染方式：通过替换或修改Sciter DLL，任何使用该DLL的应用（如桌面软件）都会触发恶意代码。导出函数被劫持，确保调用时执行恶意逻辑。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">风险：高风险恶意软件，可能用于间谍活动、数据泄露或进一步攻击。字符串和导入显示它针对Windows系统，滥用系统服务和网络。</span></span></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">如果这是安全分析，建议隔离文件、扫描系统，并报告给安全团队。代码高度混淆，许多部分反编译失败，表明精心设计以躲避检测。</span></span></p><p style="text-align: center;" nodeleaf=""><img data-imgfileid="100002049" class="rich_pages wxw-img" data-ratio="0.4824074074074074" data-s="300,640" data-type="png" data-w="1080" type="block" src="https://wechat2rss.xlab.app/img-proxy/?k=7c60c66b&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0h464kSQsqF1ialSvePJe0JjoAqWSNND9w7dTUUrOZg8ibbm8T2l4ObuFH0ZdaUv06gDEOSHgVhibDEw%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></p><p><span leaf=""><span textstyle="" style="font-size: 16px;">这几天需要研判一些样例，只要是非加壳或者非超大文件的样例我都通过IDA9.0 + AI IDE（VScode+Copilot）辅助分析，工具不限，只是测试了这种思路，分析时间在2-6分钟之间会给出结论，给出的结论是意图文字描述，可以后续结合安全语义知识映射来判断是否是恶意或者非恶意或者是找输出的关键字直接判断。对于基础且比较通用的样例去分析，确实省了一些人工分析所需要的时间。目前没有发现误报的情况，整体上是比较准确的。</span></span></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>


<p><a href="2247485701">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=c8bb33f5&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485701%26idx%3D1%26sn%3Df52f013def97c43b8396769b95b2edf7">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Fri, 19 Dec 2025 12:30:00 +0800</pubDate>
    </item>
    <item>
      <title>从减肥开始的思考</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485605&amp;idx=1&amp;sn=ac2b59fa0f9eb7e12e52e4618012d7d9</link>
      <description></description>
      <content:encoded><![CDATA[<p>
原创 <span>jishuzhain</span> <span>2025-07-19 17:46</span> <span style="display: inline-block;">广东</span>
</p>

<p></p>



<p>
<img src="https://wechat2rss.xlab.app/img-proxy/?k=57d9f409&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0gP7btNRrmibMN2Agjtic7eUFSrLXfafklibQUBQmqEUhCKkicNcbXRjKzkicdtfHHicqsnwTIcribUknQkw%2F0%3Fwx_fmt%3Djpeg"/>
</p>


<p style="text-align: left;line-height: 2.72;"><span style="font-size: 17px;">从4月22日到7月4日，身体体重减少了5.3公斤。为了避免是身体水分减少导致的体重变化，继续每日观察来期望排除这种可能。经过一段时间测量后没有变化，最终体重稳定在75公斤，目前处于标准体重范围。决定保持该体重指标，等待后续明年向下一个体重目标靠近。</span></p><p style="text-align: left;line-height: 2.72;"><span style="font-size: 17px;">对此，想把体会与经历写一写。</span></p><p style="text-align: left;line-height: 2.72;"><span style="font-size: 17px;">为什么如今大家都表现出想非常急迫地完成一件事呢？按理来说，每个人的体重与变化趋势不一样，每个人都存在着自己的节奏与习惯。早几千年前就有人已经提出了“因材施教，有教无类”，而如今在减肥的过程中大多数人很想寻找到一个标准答案，而往往真相是每个人的标准答案都是不同的。</span></p><p style="text-align: left;line-height: 2.72;"><span style="font-size: 17px;">一些网络上的帖子，内容是如何在一个月内减重10斤，这是一类求助帖。另一类帖子则是宣传引流或者是炫耀帖，“在一个月内成功掉秤10斤”，满满的炫耀感，又一次陷入了优绩主义的陷阱。为了数字的变化而变化，违背减肥的初衷，减肥的核心是消除影响健康的一个因素。如果已经处于健康的状态，那么减肥大可不必。如果又是一次竞赛，那么也是徒劳无益。因为存在代价，快速获得的事物必有代价，我不想收获代价。</span></p><p style="text-align: left;line-height: 2.72;"><span style="font-size: 17px;">在开始计划前，理清楚自身的需求，是要健康还是数字，是炫耀或者得到认可，还是内心获得健康后稳定踏实的心态。</span></p><p style="text-align: left;line-height: 2.72;"><span style="font-size: 17px;">我们都会询问的问题，减肥的核心方法是什么？有没有最有效的方法？真相是没有最有效的方法，只有最合适的方法，但减肥的核心是可以确定的，那就是每日的能量摄入在维持住日常所有活动后仍能够保持一点点热量摄入缺口，这部分缺口就是减肥的核心。目的明确，可采用的方法没有任何限制。</span></p><p style="text-align: left;line-height: 2.72;"><span style="font-size: 17px;">接下来写一些我的个人实践方式，最近5年一共减肥三次，前两次直接失败，最近一次成功保持住体重，我也很有信心长期保持。</span></p><p style="text-align: left;line-height: 2.72;"><span style="font-size: 17px;">第一次减肥，完全没有阅读相关书籍或者观看分享减肥经验的片段视频，就凭着经验购买了所谓的“减肥”食物，代替一天三餐内的任意一餐，坚持了一段时间后确实坚持不下来，原因是一下子饮食习惯改变太大，热量摄入波动太大，身体反应与适应会慢慢地产生排斥，表现出来会很饿，好想多吃东西。这类生理性排斥现象注定是无法坚持的，身体产生信号要多吃东西，人无时无刻都在接收着信号，不久就投降屈服了，本次减肥经历宣告失败，获得的经验是如果没法度过身体多吃东西的信号，请注意多吃东西的信号并不是坏事，而是身体在告诫需要维持必备的能量摄入，避免引起生命危险，但如果没法安全度过，那么减肥注定会失败。</span></p><p style="text-align: left;line-height: 2.72;"><span style="font-size: 17px;">第二次不采用减肥餐的方式，而是采用运动的方法。我有慢跑的习惯，刚开始只能坚持跑完三公里，后面随着出门运动的次数增加，身体逐渐适应了五公里的距离，除了运动完，每天正常吃饭，入睡前不吃任何零食，如果入睡前有点点饿，那么效果会更好。就这样每天早起去运动，一周五天下来，每周测量体重会降低400克左右，一个月坚持会降低4斤左右体重。看起来这个方法很美好，不过为啥我的方法最终失败了呢？原因有两点，第一点，我的日常工作比较忙碌，无法长期坚持早起运动，白天处理工作与生活琐事。人的精力与自身能量并不是长期恒定的，我是活生生的人，有作为人天然的本性，而是存在波动，一旦波动，体重便会上升，面对压力也需要多进食维持情绪平衡。这是我的个人情况，也可以作为参考，越轻松的情绪，往往也越容易完成减肥的计划，可以把有限的活力投入到减肥这类事项上。第二点原因是不注重科学的饮食摄入，缺乏理论学习与健康意识。比如举一个例子，连续五天工作日早起运动，正常吃饭摄入，最后在周末的时候对油脂或肉类的摄入需求非常明显，身体明显告警需要多摄入，但当时未能引起重视，只是做饭的时候多新增了一次排骨而已，吃完后觉得获得了满足，仅此而已，后续未能持续坚持，觉得做饭比较麻烦，懒惰是人的天性，这是好事，说明此时这是保护自己的最好方法。</span></p><p style="text-align: left;line-height: 2.72;"><span style="font-size: 17px;">饮食摄入与营养吸收不够均衡，导致与每日早起运动的身体消耗产生了矛盾，长此以往，此类活动也很难坚持下去，身体处于过度消耗的状态，效率越来越低，最终失败，回归了多吃多喝的生活状态，最终的结果是体重比第二次减肥时最轻的时候重20斤。</span></p><p style="text-align: left;line-height: 2.72;"><span style="font-size: 17px;">经过这两次减肥经历获得了经验教训，那就是对于我来说，科学的饮食摄入与适度的运动就可以完成我的减肥计划，说干就干。</span></p><p style="text-align: left;line-height: 2.72;"><span style="font-size: 17px;">减肥期间经过了好几天的实验找到了适合我的热量缺口，那就是把午饭换成吃肯德基的香辣鸡腿堡，搭配一杯冰美式咖啡。如果当天摄入不够，在午饭时间就新增一份吮指鸡与一个蛋挞。</span></p><p style="text-align: left;line-height: 2.72;"><span style="font-size: 17px;">坚持了两周，体重迅速下降了2斤，平均每天体重下降200克，脂肪一般是一半，也就是100克左右的脂肪，一个星期就可以减轻1斤左右。期间肯定也想多吃点东西，所以规定自己是工作日午饭改变摄入，而其余时间正常吃饭，不节食和挑食，周末不管，我想吃啥就吃啥，直接想吃就吃一些，不想吃就不吃零食，有空就去慢跑运动。坚持了一个月后，体重下降了很多，但我没有任何的压力感以及感受，觉得类似于“无感”减肥，这是最好的状态，目标往往意味着压力，而压力就会让身体产生应激反应。</span></p><p style="text-align: left;line-height: 2.72;"><span style="font-size: 17px;">原本我的计划是体重减轻到72公斤以下，后面发现减肥的前两个月体重下降过快，为了保持健康，于是主动把目标设定为75公斤，根据自身情况来调整，避免体重下降过快，我始终认为身体健康是我最终的目的，而身体体重只是一个数字，数字由我的需求来决定是否变动。</span></p><p style="text-align: left;line-height: 2.72;"><span style="font-size: 17px;">在快达到75公斤体重前，便不再决定要时刻保持工作日午饭吃汉堡，于是开始多吃碳水油脂以及蛋白质和蔬菜等食物，保持充足的营养摄入，期间根据自身情况选择调整运动方式为散步，不会纠结于需要每天早起运动，而是在身体舒服的时候可以利用工作日午饭后散步1个小时20分钟左右，保持热量消耗，以及维持身体正常代谢活动。顺便也可以晒会太阳，促进夜晚睡眠质量的改善。</span></p><p style="text-align: left;line-height: 2.72;"><span style="font-size: 17px;">就这么坚持了1个月，目前体重依然保持75公斤，说明成效明显，保证身体健康，代谢系统功能正常，也能通过散步或者慢跑促进身体关节健康和机能的恢复与提高，维持比较好的身体状态，同时内心里实实在在获得了健康带来的幸福感，不需要控制吃什么来丧失对生活的体会与热爱，而这一切都得归功于不断地失败后总结得来的经验教训，然后愿意花心思去实践，结合自己的实际情况来制定计划与调整计划。</span></p><p style="text-align: left;line-height: 2.72;"><span style="font-size: 17px;">减肥是一件开心的时候，不需要追求快速或者数字，开心的事情随时可以坚持下来。</span></p><div style="text-align: left;line-height: 2.72;"><p style="display: inline-block;font-size: 17px;"><img data-ratio="2.1684518013631937" data-type="jpg" data-w="1027" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=20488da9&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0gP7btNRrmibMN2Agjtic7eUF2d7XSNGlR1a3gAejF8Drg4PjMgkOuWibwNaOHaqnobmwlvKp0SmsHibw%2F640%3Fwx_fmt%3Djpeg"/></p></div><p style="display: none;"><mp-style-type data-value="10000"></mp-style-type></p>



<p><a href="2247485605">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=8f7c9024&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485605%26idx%3D1%26sn%3Dac2b59fa0f9eb7e12e52e4618012d7d9">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Sat, 19 Jul 2025 17:46:00 +0800</pubDate>
    </item>
    <item>
      <title>江南漫步记2 | 记南京旅行有感</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485591&amp;idx=1&amp;sn=9bcae63da6726263816d371476691638</link>
      <description>阅读了明代的历史，对南京（金陵，古称石头城）便多了一份了解。当去往一个新城市或者较为陌生的城市时会忐忑，这类感受往往是开启一段新旅途的起点。</description>
      <content:encoded><![CDATA[<p>
原创 <span>jishuzhain</span> <span>2025-06-26 20:54</span> <span style="display: inline-block;">广东</span>
</p>

<p>阅读了明代的历史，对南京（金陵，古称石头城）便多了一份了解。当去往一个新城市或者较为陌生的城市时会忐忑，这类感受往往是开启一段新旅途的起点。</p>
<p></p>



<p>
<img src="https://wechat2rss.xlab.app/img-proxy/?k=c3e43b3c&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0hzhKWsBCr885WLra3ke9sRTo3hsQr4kTFU4D0NiayzpGTX4T5B4cQFLCgibXHtXylMZ3nG90ugicTdg%2F0%3Fwx_fmt%3Djpeg"/>
</p>


<p data-pm-slice="0 0 []" style="text-align: left;line-height: 3em;"><span leaf="">阅读了明代的历史，对南京（金陵，古称石头城）便多了一份了解。</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">当去往一个新城市或者较为陌生的城市时会忐忑，这类感受往往是开启一段新旅途的起点。落地南京禄口机场后，比较自然地跟着指示牌前进，“南京欢迎你”的巨型广告牌历历在目，我也见到了很多行人驻足留影，并不是需要多少美丽的摄影作品才是值得留下的，有时候在你举起手机里那一刻你觉得美的便是美的，照片作为一种记忆快照术，往往在以后的时刻里随意翻阅，那么一瞬间，那张照片便会给你带来无尽的遐想，多么美好呀。</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">南京禄口机场距离市区相对较远，长达几十公里的距离，想着以前没有电子导航设备的时候，那时的人们出行多是问路以及购买地图为主，辨识方位与方向的能力是很厉害的，在一座新城市里，手拿着地图环顾四周，前往下一个地图小点，类似于现在的盲盒体验。太稀疏平常的事物让人感觉到了一切自然而来，没有再次想到手里的这块小屏幕竟然有如此强大的能力，不由得幸福感溢出。现代人的出行无外乎会选择地铁或公共巴士等这类公共交通，因为便宜也便捷，便宜就是当前出行的内核，从功利角度去看待我们大部分人的时间没有那么值钱，时间也与人的自由有关，你能掌握自己的时间也渐渐有了自己的自由，有时候路途中乘坐公共交通所花费的时间相对也能接受。</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">从导航软件给出的路线是可以选择机场巴士，慢慢步行来到了出口位置，路过接机的人群，当我以前没有过接机体验的时候往往是带着有些不好意思的感觉匆匆而过，逐步走向我的目的地。后面在2024年5月假期期间接机了从国外旅行回来的对象后才明白了这类体会。在期待中见到喜欢的人走过来，那种感觉很美妙。正因为有期待，等待的时光才那么难以忘记。经历与体验相当于一种素材，在未来的某个时刻被使用了。咦，感慨一下，原来一切是这么回事。</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">一眼望去，出现比较醒目的巴士服务与售票点。脑子里恰巧盘算着怎么买票的事情，突然想到还是先去看看情况。让我来试试，来到售票点没什么人，有个热情的售票员给我解答了疑问，我根据最后的下车点选择了具体发车线路。对了，票价是25元，平均算下来一公里都远没有达到1块钱。</span></p><p style="text-align: left;line-height: 3em;"><span leaf=""><img class="rich_pages wxw-img" data-ratio="1.3333333333333333" data-type="png" data-w="1080" data-imgfileid="100001937" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=de996c66&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0hzhKWsBCr885WLra3ke9sRTrymicXhDyIJJwIG64SOq8CUZzUqeXpkNpXzFr6bTgUlzQywf7lmbpw%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></p><p style="text-align: left;line-height: 3em;"><span leaf="">票价这个事情是一个比较敏感的事情，公共交通的优势确实是相对便宜，我也在期待本次巴士的体验如何。</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">如果说乘坐地铁去往目的地，那么可能会经历比较长时间的交通时间以及换乘时间，在熙熙攘攘的人群里穿梭前进。如果是打车前往目的地，那么花费的金额着实会让人感觉到好贵，毕竟从机场前往目的地还需要经过20-30公里的路程，这部分路程折算下来的费用也不会低。整体来说，这是我感觉非常折中的出行体验。当写下文字的时候，我也经历了半夜飞机落地宝安国际机场，考虑如何回家的情况，起初也是按照以往的方式想打网约车回家，后面也是在出口处看到了巨大且醒目的指示牌，提示“优点巴士”服务，带着好奇走向了那里，确认了下没啥问题后果断购买了车票，花费20元，不过会依据拼车的乘客来就近送达，因此到达时间有时候真的看运气，住的近能早送达嘞，有时候还能和乘客聊聊天，挺有意思，大家也多是旅行回来，整体上是处于放松状态，防备心得到了纾解，对陌生人比较友好，气氛融洽。</span></p><p style="text-align: left;line-height: 3em;"><span leaf=""><img class="rich_pages wxw-img" data-ratio="0.4703703703703704" data-type="jpeg" data-w="1080" data-imgfileid="100001936" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=5d53a448&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0hzhKWsBCr885WLra3ke9sRYqLGX65OvBosVGTTqa1iaozutQPUyI62sq2z85ibYmzCicVewTicSwyuLQ%2F640%3Fwx_fmt%3Djpeg%26from%3Dappmsg"/></span></p><p style="text-align: left;line-height: 3em;"><span leaf="">与陌生人的交流需要注意的事项，但凡涉及到金钱的话题及时远离并主动切割，不予理睬。</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">利字右边刀，伤人也伤己。但凡有主动攀谈交流的场景，提高警惕避免受骗。</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">接下来写一写我遇到的一个情况，在等待巴士的间隙，候车室内遇到一个中年人或者是年纪比较大的老人，慢慢地走向我这边的座位。当然如果大家都保持沉默，这部分文字内容便不会出现了。出门在外，整个人都处于比较放松的状态，自然对周围的人事物变得比较柔和，不会过多地排斥。对于这类主动引出话题慢慢引导你进入特定场景的事情我也是第一次遇到，整个过程比较简单的描述就是老人是一个行走在外的风水师（算命），待人和善的我接住了老人的话，于是这就开始了。随着我们的聊天，对方慢慢地引导我，聊到易经与风水，以及根据被交谈人相关的信息引申到熟悉的地区与经历，逐步加深亲密感，最后进入老人设定的框架里，最终将话题引入了付点钱积香火的意图，原本我就对这类看命与风水保持怀疑，加之最终暴露了意图（利），我就后续不再说话，不予理睬，整个事情就结束了。</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">只要牢牢守住钱袋子，其他的风险基本为零，无需担忧。从这类非常简单的骗术也可以引申到更大的视角里，一个人的年纪这么大了，一辈子以骗为生，老了会不会追悔？我觉得不会，这些骗子渐渐习惯了抛开那些世俗枷锁（道德）的日子了。除此之外一定还有更高级或者更高明的骗子，那么它们的“交谈对象”可能就不会是我这类普通的出行者了。欺骗与防御也是必修课，更高明的骗术也行对我来说未必能及时识破，往往我还深陷其中。</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">控制每篇文章字数在2000字以下，便于阅读。</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">未完待续，下一篇书写南京的所见所闻与体味，期待与大家分享。</span></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>


<p><img src="https://wechat2rss.xlab.app/img-proxy/?k=b1656633&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0hzhKWsBCr885WLra3ke9sRTrymicXhDyIJJwIG64SOq8CUZzUqeXpkNpXzFr6bTgUlzQywf7lmbpw%2F640%3Fwx_fmt%3Dpng"/></p>
<p><img src="https://wechat2rss.xlab.app/img-proxy/?k=3a83ebb5&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0hzhKWsBCr885WLra3ke9sRYqLGX65OvBosVGTTqa1iaozutQPUyI62sq2z85ibYmzCicVewTicSwyuLQ%2F640%3Fwx_fmt%3Djpeg"/></p>



<p><a href="2247485591">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=44e98bd5&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485591%26idx%3D1%26sn%3D9bcae63da6726263816d371476691638">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Thu, 26 Jun 2025 20:54:00 +0800</pubDate>
    </item>
    <item>
      <title>江南漫步记1 | 记南京旅行有感</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485583&amp;idx=1&amp;sn=d368d62be98d6afdd08f8f9b509af3b0</link>
      <description>旅行搭子L：“南京的美龄宫特别好看”我：“是嘛，那我得计划一下今年要去一次。</description>
      <content:encoded><![CDATA[<p>
原创 <span>jishuzhain</span> <span>2025-06-17 21:06</span> <span style="display: inline-block;">广东</span>
</p>

<p>旅行搭子L：“南京的美龄宫特别好看”我：“是嘛，那我得计划一下今年要去一次。</p>
<p></p>



<p>
<img src="https://wechat2rss.xlab.app/img-proxy/?k=64844c9d&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0iaAD781DoGV205cNqUQ7jUZbWjUq1LPib8UY2dcEogdCibDaUmuw0F3bmejnlPq04BLofexicbiczSyTg%2F0%3Fwx_fmt%3Djpeg"/>
</p>


<p data-pm-slice="0 0 []" style="text-align: left;line-height: 3em;"><span leaf="">旅行搭子L：“南京的美龄宫特别好看”</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">我：“是嘛，那我得计划一下今年要去一次。我之前去过南京两次，时间是2019年8月与9月，当时是由于出差得从上海达到南京，原来时间过去这么久了。”</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">临近清明节假期，友人从上海赶来深圳，准备游玩几天，于是乎和之前去日本旅行的搭子共四个人约好下班后在公司附近吃一顿潮汕风味大排档。考虑到明天就可以与部门团队前往四川成都九寨沟等地旅行，所以独自走往目的地的心情也是自由自在的。</span></p><p style="text-align: left;line-height: 3em;"><span leaf=""><span textstyle="" style="font-weight: bold;">压抑了很久，决定鼓起勇气出门一次。</span></span></p><p style="text-align: left;line-height: 3em;"><span leaf="">近几年，环境在变化。每每遭遇来到工位便会浑身不舒服，甚至于紧张焦虑的感受。虽然缓一缓确实消失不见，但久而久之这类体验无法完整消除，仍旧处于治标不治本的状态。我觉得这是一种共同现象，但苦于知识匮乏，困惑于找不到合适的解释来印证此类现象。回顾往昔，多阅读后才得知该类现象如今可称之为“躯体焦虑化”虽然是非常轻微的情况，但还重视还得重视，做好自己健康的第一责任人是我一直以来的坚守。</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">知道原因才能有所变化，所以我决定实现自己的第一次远行，虽然我是男生，但肯定有些害怕。</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">并不是第一次出门，但第一次独自旅行确实如此。首先我需要理清楚自己的行李清单，结合之前和对象或者朋友一起远行时制定的计划攻略的经验，也是依据所预定的酒店为中心，沿着地图进行大概地判断位置是否合适，诸如此类，大致选定了位于玄武区的南京山水大酒店作为我4天3夜的落脚点。</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">这里我附上了我的打包行李清单，为了避免遗漏重要物品，在出发前会依据物品收纳然后给对应的项目打勾表示物品已成功收集。为这次旅行着实下了一些功夫，目的还是为了保障旅途的顺利。</span></p><p style="text-align: left;line-height: 1em;"><span leaf=""><span textstyle="" style="font-weight: bold;">行李清单</span></span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    大背包</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    军绿色单肩包</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    一条牛仔裤</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    三条内裤</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    三双袜子</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    三件长袖</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    一件外套</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    充电宝</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    手机充电器和数据线</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    相机充电线</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    索尼相机与两块电池</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    尼康相机与一块电池</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    尼康充电器</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    雨伞</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    剃须刀</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    门卡</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    存储卡读卡器</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    身份证</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    耳机</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    手表与充电线与头</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    盒马两个小欧包，买点牛肉干</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    现金</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    抽纸</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    湿纸巾</span></p><p style="text-align: left;line-height: 1em;"><span leaf="">    ✓    印章本</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">基于这类公共物品清单，也能方便我下次出门时比较顺利且高效地获取我所需要的物品，做到有条不轨。</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">为了省钱，预定了一趟深圳宝安机场6点50起飞停留南京禄口机场的飞机，虽然得早起收拾吃点东西然后出门去往机场，但是来到机场后我依然是处于一个好奇且兴奋的状态。也许是远离了自己熟悉的环境，加之假期来临时候的自由感，这两种感觉糅合后直达我的内心，坐在登机口附近的位置上，我的体验从这一刻开始了，一种说不上来但又很美好的体验。我看到了有乘客在入睡着（此时天还未亮），也有精神抖擞的中年人在四周张望，也有满眼疲惫的年轻人在步行，每个人都较为轻松地做着自己需要去做的事情，人来人往广播不绝，随后找到座位坐下来，顿时得到了喘息。</span></p><p style="text-align: left;line-height: 3em;"><span leaf=""><img class="rich_pages wxw-img" data-ratio="0.75" data-type="png" data-w="1080" data-imgfileid="100001931" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=e484cf75&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0iaAD781DoGV205cNqUQ7jUZj5rsNwY79kRrPjb8wwcKk61cf628c9LazzHYGyVNZHQ76l4MGIuCeg%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></p><p style="text-align: left;line-height: 3em;"><span leaf="">机场的宽大与设施，总是让人步行其中会有种特别的体味。对于我们不常使用飞机这类交通工具的人群来说，每次机场的去往仿佛是一种暂时逃离的栖息地，井然有序的人群，高耸的穹顶。适宜的温度，特别是夏季从外入内，凉风习习让人舒服。我有好久没有体验过乘坐飞机的经历了，从上次4月初前往成都，再往前就可追溯到2021年10月去往上海参会。在这期间，出行往往依赖铁路或大巴。时间太久都快忘记深圳机场的设施与布局了，还好随着出行的次数与经验的积累，往往对于年轻人来说这都不是问题，读一会标志或者指示便可秒懂。</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">有人说，一个人的旅行比较异类，或者会无趣，其实当怀着这样的想法出门的时候那一刻已然忘了，每个所遇到的风景或者事物总是会在当时的眼前联想出远比平时更多的记忆与体会，收获的也存有勇敢。</span><span style="color: unset;font-family: unset;font-size: unset;"><span leaf="">看到了坐我座位旁边拿出玩偶在合拍飞机窗外的女生的动作，我突然意识到我已经很久没有关注周围年轻群体的日常了，原来会这么有意思，我的日常还是比较无趣的。我猜想，想必大家也是有远方正在等待着。飞行前发现了旁边的乘客对系安全带没有那么熟练，对方寻找了一会还是未能成功，我抱着助人为乐的心态果断主动地上前帮忙，不管了我就得锻炼下自己的行动力，最终解决了。有时候做的好事虽然渺小，但意义确不一样，于人生困难中得一份安宁，有人撑伞的时光总是那么美好。在这样的体会下，鼓起勇气让坐在窗边的乘客使用我的手机随拍了一张早晨阳光穿过云层的景色，以给自己留作纪念。</span></span></p><p style="text-align: left;line-height: 3em;"><span leaf=""><img class="rich_pages wxw-img" data-ratio="1.3342592592592593" data-type="png" data-w="1080" data-imgfileid="100001930" style="height: auto !important;" src="https://wechat2rss.xlab.app/img-proxy/?k=952ade2f&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0iaAD781DoGV205cNqUQ7jUZicguGHvtEFUsFVnBDQ58j8vFuhaFqs43Q5RVjgrXCmSRcEnPRARErnQ%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></span></p><p style="text-align: left;line-height: 3em;"><span leaf="">出门前特意测量了一下体重，79公斤，比一周前轻了1公斤，如今当写下这些文字的时候体重来到了75.6公斤。有计划或者想法就立马行动，自从第一次出门后便深深影响了我。</span></p><p style="text-align: left;line-height: 3em;"><span leaf="">未完待续，下一篇书写南京的所见所闻与体味，期待与大家分享。</span></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>


<p><img src="https://wechat2rss.xlab.app/img-proxy/?k=a3f5ec17&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0iaAD781DoGV205cNqUQ7jUZj5rsNwY79kRrPjb8wwcKk61cf628c9LazzHYGyVNZHQ76l4MGIuCeg%2F640%3Fwx_fmt%3Dpng"/></p>
<p><img src="https://wechat2rss.xlab.app/img-proxy/?k=96fcf511&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0iaAD781DoGV205cNqUQ7jUZicguGHvtEFUsFVnBDQ58j8vFuhaFqs43Q5RVjgrXCmSRcEnPRARErnQ%2F640%3Fwx_fmt%3Dpng"/></p>



<p><a href="2247485583">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=b6d1a05f&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485583%26idx%3D1%26sn%3Dd368d62be98d6afdd08f8f9b509af3b0">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Tue, 17 Jun 2025 21:06:00 +0800</pubDate>
    </item>
    <item>
      <title>对MSI类型恶意文件检测的思考</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485577&amp;idx=1&amp;sn=a0c58f8324f04a24c1f2e79a2446daa6</link>
      <description></description>
      <content:encoded><![CDATA[<p>
原创 <span>jishuzhain</span> <span>2025-02-26 18:29</span> <span style="display: inline-block;">广东</span>
</p>

<p></p>



<p>
<img src="https://wechat2rss.xlab.app/img-proxy/?k=63efd020&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0gFiaVQAUNcr6N7FyyQydC1eiaoUKfeTqicUGXX9LicyxtukJrJNdgJyxWLdwWpbpudynNfmG8oDTPfVA%2F0%3Fwx_fmt%3Djpeg"/>
</p>


<p style="text-align: left;"><span leaf="">这几年工作的方向与恶意文件检测密切相关，踩坑与接触新的思路，期间也有了新的体会和想法，还是得在适当的时间里能记录下来自己的一些思考，方便未来回顾。</span></p><p><span leaf=""><br/></span></p><p style="text-align: left;"><span leaf="">这两年的时间里银狐类木马出现的频率较高，在这些恶意文件里msi类型文件出现的概率也高，作为网络安全方向里的防御检测方向，自然也需要面对这个问题。</span></p><p><span leaf=""><br/></span></p><p style="text-align: left;"><span leaf="">最近几个月大部分msi类型恶意文件出现了无法被沙箱系统跑出核心行为的情况，同时基于静态维度的杀毒引擎对其检测效果很差。在这些因素下，这类样本检测存在困难，因此可以说当前又出现了一类较难检测的恶意文件。为了检测这类难检测的恶意文件，需要付出努力思考应对的解决方案。</span></p><p><span leaf=""><br/></span></p><p style="text-align: left;"><span leaf="">MSI是Microsoft Installer的简写，它使用微软提供的标准安装卸载界面，本质上MSI就是一个数据库，包含该软件的所有必要数据。</span><span style="font-size: unset;color: unset;font-family: unset;"><span leaf="">此时MSI类型文件相当于给核心恶意文件加装了一层“壳”，攻击者使用MSI类型文件作为恶意文件投递本质上是利用了系统提供的正常的静态隐藏手段来隐藏自己核心恶意文件的特征，因此对于基于静态特征维度的杀毒引擎来说检测效果会受到影响。</span></span></p><p><span style="font-size: unset;color: unset;font-family: unset;"><span leaf=""><br/></span></span></p><p style="text-align: left;"><span leaf="">作为分析人员，通过分析这类样本发现主流云沙箱均无法获取到必要的完整行为。在不直接动手逆向分析的前提下得到了这个结论，结论是这类样本存在反虚拟化策略，不过不存在反调试策略，因此基于虚拟化环境而构建的沙箱行为分析系统遭遇了对抗。结果是跑完沙箱后行为无法释放出来，作为分析人员也拿不到对应的IOC数据，想扩展威胁情报数据的目的也受到了阻碍。</span></p><p><span leaf=""><br/></span></p><p style="text-align: left;"><span leaf="">从防御的角度观察，我们需要应对威胁，如果仅仅通过手工去分析这类样本，得到了一些明显的异常行为或者回连的C2地址等信息，最后像八股文一样写一个简短的文章就结束了，那么实质是解决不了这类威胁的，分析与写文章仅仅是手段，我们的目的是应对最新的威胁，然后尽量低成本的解决威胁，避免遭受损失，不能本末倒置，而且样本是死的，威胁是持续变化的，应对的策略要尽量考虑成本与投入。</span></p><p style="text-align: left;"><span leaf="">根据自己的经验，首先还是得从内心上认为自己能想出办法解决这类威胁，一个人充满自信是比较重要的。其次是得锤炼出适合自己的方法论。</span></p><p><span leaf=""><br/></span></p><p style="text-align: left;"><span leaf="">如下是自己思考的一个过程：</span></p><p style="text-align: left;"><span leaf="">1、立足快速检测的策略，当前有没有低成本的解决方法？</span></p><p style="text-align: left;"><span leaf="">2、基于攻击者的角度，频繁选择msi类型文件的目的是什么？</span></p><p style="text-align: left;"><span leaf="">3、回到自身角度，我们的目的是检测，我们不可能同时拥有足够的资源和优秀的检测系统，那么如何在已拥有的检测系统的环境下实现这类威胁的检测呢？</span></p><p><span leaf=""><br/></span></p><p style="text-align: left;"><span leaf="">其实这些问题就是我一直在思考或者实践的过程，接下来比较细致地思考记录下来。</span></p><p><span leaf=""><br/></span></p><p style="text-align: left;"><span leaf="">如果要快速检测，那么去优化沙箱系统就是当前不合适的动作，对于这类存在反虚拟化策略的样本，其内部必定有对应的代码逻辑实现，那么必须得人工去细致分析得到反虚拟化的原因是什么？这个过程非常耗时，没法快速解决对抗问题并提升沙箱系统的应对能力，该方法应当不是首选的。</span></p><p><span leaf=""><br/></span></p><p style="text-align: left;"><span leaf="">攻击者选择msi类型文件实现投递恶意文件，其本质还是基于将核心恶意特征无损隐藏到正常程序或流程中的目的而产生的，一个恶意文件的表现越正常越接近于正常文件的行为或特征，那么它被检测出恶意文件的可能性就会越来越小，同理也是如此。由于行为上我们无法获取到更多有用信息，因此还是得立足于特征这个维度。</span><span style="color: unset;font-family: unset;font-size: unset;"><span leaf="">采用比较经典的思路就是解包的策略，这部分以往是属于对加壳文件的检测所应用的，一个恶意文件有了壳，避免了恶意特征的暴露，但壳本身就是一个异常信息，这也导致攻击者在伪装恶意文件为正常文件的历程中会选择msi类型作为“壳”的载体。检测的哲学在于精准找到恶意文件的本质，“</span></span><span leaf="">专门设计用于破坏、损坏或获得未经授权的访问计算机系统的软件</span><span style="color: unset;font-family: unset;font-size: unset;"><span leaf="">”</span></span><span leaf="">。</span></p><p><span style="color: unset;font-family: unset;font-size: unset;"><span leaf=""><br/></span></span></p><p style="text-align: left;"><span leaf="">有了思路，就可以验证，这部分涉及到效果与如何有效检测达到目标并确保误报率符合要求和每个人所处的检测系统的环境有关，这里就不展开了。</span></p><section style="text-align: left;" nodeleaf=""><img data-imgfileid="100001928" class="rich_pages wxw-img" data-ratio="1.727034120734908" data-s="300,640" data-type="png" data-w="381" type="block" src="https://wechat2rss.xlab.app/img-proxy/?k=d5919227&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0gFiaVQAUNcr6N7FyyQydC1esEOeTNCQjXJGY1vqb05ftKCFiaCkC3jDRb3QlytN5271jt3MBULgx2w%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></section><p><span leaf=""><br/></span></p><p style="display: none;"><mp-style-type data-value="10000"></mp-style-type></p>



<p><a href="2247485577">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=2c21d4d2&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485577%26idx%3D1%26sn%3Da0c58f8324f04a24c1f2e79a2446daa6%26subscene%3D0">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Wed, 26 Feb 2025 18:29:00 +0800</pubDate>
    </item>
    <item>
      <title>尝试用CNN解决MNIST数据集经典分类问题</title>
      <link>https://mp.weixin.qq.com/s?__biz=MzUyMTUwMzI3Ng==&amp;mid=2247485571&amp;idx=1&amp;sn=d51aa8f4c841386d80202428a0d598e9</link>
      <description>使用CNN做些小实验</description>
      <content:encoded><![CDATA[<p>
原创 <span>jishuzhain</span> <span>2025-02-22 17:26</span> <span style="display: inline-block;">广东</span>
</p>

<p>使用CNN做些小实验</p>
<p></p>



<p>
<img src="https://wechat2rss.xlab.app/img-proxy/?k=3a363b33&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_jpg%2Fdib9GLOoSY0goUMY2myz52nqibiaRWUGrKTut3k10mSCbC9z7Ub7bm4JiciachQn7tHEpibIKBAU7jciathLOJTzHrzJw%2F0%3Fwx_fmt%3Djpeg"/>
</p>


<p style="text-align: left;"><span leaf="">MNIST 数据集对应的任务是手写数字识别，属于图像分类任务。具体是对0~9 的手写数字分类，能够达到接近人脑的图像识别能力。这次选择CNN算法进行小实验，卷积神经网络已经被证明对图像类任务是合适的。</span></p><p style="text-align: left;"><span leaf="">MNIST 数据集在下载时已经预先划分好了训练集和测试集：</span></p><p style="text-align: left;"><span leaf="">训练集（train=True）包含 60000 张手写数字图片，用于模型训练。</span></p><p style="text-align: left;"><span leaf="">测试集（train=False）包含 10000 张图片，用于模型评估。</span></p><p style="text-align: left;"><span leaf="">思路是根据经验首先确定模型的架构，从最简单的网络结构开始。第二步使用超参数优化 (Hyperparameter Optimization)，以下训练的代码使用 Optuna 进行超参数优化，Optuna 是一个流行的库，用于高效的超参数优化。同时还利用了数据增强策略，例如对训练数据新增数据增强：随机旋转10度和随机平移（最大10%的图像移动）。主要是让模型“见到”更多数据，提升能力。</span></p><p style="text-align: left;"><span leaf="">最终训练模型（代码1）得到的最佳超参数如下：</span></p><p style="text-align: left;"><span leaf="">conv1_out_channels：第一个卷积层的输出通道数（特征图的数量）。88</span></p><p style="text-align: left;"><span leaf="">conv2_out_channels：第二个卷积层的输出通道数。237</span></p><p style="text-align: left;"><span leaf="">fc1_out_features：全连接层的输入特征数（即第一层全连接层的输出特征数）。389</span></p><p style="text-align: left;"><span leaf="">Best hyperparameters: {&#39;conv1_out_channels&#39;: 88, &#39;conv2_out_channels&#39;: 237, &#39;fc1_out_features&#39;: 389}</span></p><p style="text-align: left;"><span leaf="">Training final model with best hyperparameters...</span></p><p style="text-align: left;"><span leaf="">Epoch 1, Loss: 0.2567, Accuracy: 91.88%</span></p><p style="text-align: left;"><span leaf="">Epoch 2, Loss: 0.0815, Accuracy: 97.48%</span></p><p style="text-align: left;"><span leaf="">Epoch 3, Loss: 0.0653, Accuracy: 97.95%</span></p><p style="text-align: left;"><span leaf="">Epoch 4, Loss: 0.0557, Accuracy: 98.26%</span></p><p style="text-align: left;"><span leaf="">Epoch 5, Loss: 0.0508, Accuracy: 98.46%</span></p><p style="text-align: left;"><span leaf="">Final test accuracy with best hyperparameters: 99.03%</span></p><p style="text-align: left;"><span leaf="">Best model saved as best_deep_cnn_model.pth</span></p><p style="text-align: left;"><span leaf="">示例代码1如下：</span></p><table><tbody><tr><td data-colwidth="576" width="576"><pre style="font-family: &#34;JetBrains Mono&#34;, monospace;font-size: 9.8pt;text-align: left;"><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">torch</span><span leaf=""><br/></span><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">torch.nn </span><span style="color:#cf8e6d;"><span leaf="">as </span></span><span leaf="">nn</span><span leaf=""><br/></span><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">torch.optim </span><span style="color:#cf8e6d;"><span leaf="">as </span></span><span leaf="">optim</span><span leaf=""><br/></span><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">torchvision</span><span leaf=""><br/></span><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">torchvision.transforms </span><span style="color:#cf8e6d;"><span leaf="">as </span></span><span leaf="">transforms</span><span leaf=""><br/></span><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">optuna</span><span leaf=""><br/></span><span style="color:#cf8e6d;"><span leaf="">from </span></span><span leaf="">torch.utils.data </span><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">DataLoader</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">数据增强与预处理</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">对训练数据新增数据增强：随机旋转</span></span><span style="color:#7a7e85;"><span leaf="">10</span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">度和随机平移（最大</span></span><span style="color:#7a7e85;"><span leaf="">10%</span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">的图像移动）</span><span leaf=""><br/></span></span><span leaf="">train_transform = transforms.Compose([</span><span leaf=""><br/></span><span leaf="">    transforms.RandomRotation(</span><span style="color:#2aacb8;"><span leaf="">10</span></span><span leaf="">),                </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">随机旋转</span></span><span style="color:#7a7e85;"><span leaf="">10</span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">度</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">transforms.RandomAffine(</span><span style="color:#aa4926;"><span leaf="">degrees</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">0</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">translate</span></span><span leaf="">=(</span><span style="color:#2aacb8;"><span leaf="">0.1</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">0.1</span></span><span leaf="">)),  </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">随机平移</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">transforms.ToTensor(),</span><span leaf=""><br/></span><span leaf="">    transforms.Normalize((</span><span style="color:#2aacb8;"><span leaf="">0.5</span></span><span leaf="">,), (</span><span style="color:#2aacb8;"><span leaf="">0.5</span></span><span leaf="">,))</span><span leaf=""><br/></span><span leaf="">])</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">测试数据只做标准化</span><span leaf=""><br/></span></span><span leaf="">transform = transforms.Compose([</span><span leaf=""><br/></span><span leaf="">    transforms.ToTensor(),</span><span leaf=""><br/></span><span leaf="">    transforms.Normalize((</span><span style="color:#2aacb8;"><span leaf="">0.5</span></span><span leaf="">,), (</span><span style="color:#2aacb8;"><span leaf="">0.5</span></span><span leaf="">,))</span><span leaf=""><br/></span><span leaf="">])</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">数据加载：训练集使用数据增强，测试集不使用</span><span leaf=""><br/></span></span><span leaf="">trainset = torchvision.datasets.MNIST(</span><span style="color:#aa4926;"><span leaf="">root</span></span><span leaf="">=</span><span style="color:#6aab73;"><span leaf="">&#39;./data&#39;</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">train</span></span><span leaf="">=</span><span style="color:#cf8e6d;"><span leaf="">True</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">download</span></span><span leaf="">=</span><span style="color:#cf8e6d;"><span leaf="">True</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">transform</span></span><span leaf="">=train_transform)</span><span leaf=""><br/></span><span leaf="">testset = torchvision.datasets.MNIST(</span><span style="color:#aa4926;"><span leaf="">root</span></span><span leaf="">=</span><span style="color:#6aab73;"><span leaf="">&#39;./data&#39;</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">train</span></span><span leaf="">=</span><span style="color:#cf8e6d;"><span leaf="">False</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">download</span></span><span leaf="">=</span><span style="color:#cf8e6d;"><span leaf="">True</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">transform</span></span><span leaf="">=transform)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">trainloader = DataLoader(trainset, </span><span style="color:#aa4926;"><span leaf="">batch_size</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">64</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">shuffle</span></span><span leaf="">=</span><span style="color:#cf8e6d;"><span leaf="">True</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">testloader = DataLoader(testset, </span><span style="color:#aa4926;"><span leaf="">batch_size</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">64</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">shuffle</span></span><span leaf="">=</span><span style="color:#cf8e6d;"><span leaf="">False</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------------------------</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">定义具有深度卷积层的网络结构</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------------------------</span><span leaf=""><br/></span></span><span style="color:#cf8e6d;"><span leaf="">class </span></span><span leaf="">DeepCNN(nn.Module):</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#cf8e6d;"><span leaf="">def </span></span><span style="color:#b200b2;"><span leaf="">__init__</span></span><span leaf="">(</span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">, conv_layers, fc_layers):</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#5f826b;font-style:italic;"><span leaf="">&#34;&#34;&#34;</span><span leaf=""><br/></span></span><span style="color:#5f826b;font-style:italic;"><span leaf="">        </span></span><span style="color:#5f826b;font-style:italic;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">构造深度卷积神经网络</span></span><span style="color:#5f826b;font-style:italic;"><span leaf=""><br/></span></span><span style="color:#5f826b;font-style:italic;"><span leaf="">        conv_layers</span></span><span style="color:#5f826b;font-style:italic;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">：包含卷积层输出通道数的列表</span></span><span style="color:#5f826b;font-style:italic;"><span leaf=""><br/></span></span><span style="color:#5f826b;font-style:italic;"><span leaf="">        fc_layers</span></span><span style="color:#5f826b;font-style:italic;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">：包含全连接层神经元数量的列表</span></span><span style="color:#5f826b;font-style:italic;"><span leaf=""><br/></span></span><span style="color:#5f826b;font-style:italic;"><span leaf="">        &#34;&#34;&#34;</span><span leaf=""><br/></span></span><span style="color:#5f826b;font-style:italic;"><span leaf="">        </span></span><span style="color:#8888c6;"><span leaf="">super</span></span><span leaf="">(DeepCNN, </span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">).</span><span style="color:#b200b2;"><span leaf="">__init__</span></span><span leaf="">()</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">构建卷积层</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">        </span></span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.conv_layers = nn.ModuleList()</span><span leaf=""><br/></span><span leaf="">        in_channels = </span><span style="color:#2aacb8;"><span leaf="">1</span><span leaf=""><br/></span></span><span style="color:#2aacb8;"><span leaf="">        </span></span><span style="color:#cf8e6d;"><span leaf="">for </span></span><span leaf="">out_channels </span><span style="color:#cf8e6d;"><span leaf="">in </span></span><span leaf="">conv_layers:</span><span leaf=""><br/></span><span leaf="">            </span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.conv_layers.append(nn.Conv2d(in_channels, out_channels, </span><span style="color:#aa4926;"><span leaf="">kernel_size</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">3</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">padding</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">))</span><span leaf=""><br/></span><span leaf="">            in_channels = out_channels</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">计算卷积层和池化层输出的尺寸</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">        </span></span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">._calculate_conv_output_size()</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">构建全连接层</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">        </span></span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.fc_layers = nn.ModuleList()</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.fc_layers.append(nn.Linear(</span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.conv_output_size, fc_layers[</span><span style="color:#2aacb8;"><span leaf="">0</span></span><span leaf="">]))</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#cf8e6d;"><span leaf="">for </span></span><span leaf="">i </span><span style="color:#cf8e6d;"><span leaf="">in </span></span><span style="color:#8888c6;"><span leaf="">range</span></span><span leaf="">(</span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">, </span><span style="color:#8888c6;"><span leaf="">len</span></span><span leaf="">(fc_layers)):</span><span leaf=""><br/></span><span leaf="">            </span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.fc_layers.append(nn.Linear(fc_layers[i - </span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">], fc_layers[i]))</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.fc_layers.append(nn.Linear(fc_layers[-</span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">], </span><span style="color:#2aacb8;"><span leaf="">10</span></span><span leaf="">))  </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">输出层，</span></span><span style="color:#7a7e85;"><span leaf="">10</span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">个类别（</span></span><span style="color:#7a7e85;"><span leaf="">MNIST</span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">）</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span style="color:#cf8e6d;"><span leaf="">def </span></span><span style="color:#56a8f5;"><span leaf="">_calculate_conv_output_size</span></span><span leaf="">(</span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">):</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">假设输入尺寸为</span></span><span style="color:#7a7e85;"><span leaf=""> 28x28</span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">（</span></span><span style="color:#7a7e85;"><span leaf="">MNIST</span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">）</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">        </span></span><span leaf="">dummy_input = torch.zeros(</span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">28</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">28</span></span><span leaf="">)  </span><span style="color:#7a7e85;"><span leaf=""># 1</span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">个样本，</span></span><span style="color:#7a7e85;"><span leaf="">1</span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">个通道，</span></span><span style="color:#7a7e85;"><span leaf="">28x28</span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">的图像</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">        </span></span><span leaf="">x = dummy_input</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">逐层通过卷积和池化层计算输出尺寸</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">        </span></span><span style="color:#cf8e6d;"><span leaf="">for </span></span><span leaf="">conv </span><span style="color:#cf8e6d;"><span leaf="">in </span></span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.conv_layers:</span><span leaf=""><br/></span><span leaf="">            x = torch.relu(conv(x))</span><span leaf=""><br/></span><span leaf="">            x = torch.max_pool2d(x, </span><span style="color:#2aacb8;"><span leaf="">2</span></span><span leaf="">)  </span><span style="color:#7a7e85;"><span leaf=""># 2x2 </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">池化</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">        </span></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">计算最终展平后的大小</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">        </span></span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.conv_output_size = x.view(</span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">, -</span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">).size(</span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">)  </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">展平后尺寸大小</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span style="color:#cf8e6d;"><span leaf="">def </span></span><span style="color:#56a8f5;"><span leaf="">forward</span></span><span leaf="">(</span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">, x):</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">卷积层和池化层</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">        </span></span><span style="color:#cf8e6d;"><span leaf="">for </span></span><span leaf="">conv </span><span style="color:#cf8e6d;"><span leaf="">in </span></span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.conv_layers:</span><span leaf=""><br/></span><span leaf="">            x = torch.relu(conv(x))</span><span leaf=""><br/></span><span leaf="">            x = torch.max_pool2d(x, </span><span style="color:#2aacb8;"><span leaf="">2</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">展平</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">        </span></span><span leaf="">x = x.view(x.size(</span><span style="color:#2aacb8;"><span leaf="">0</span></span><span leaf="">), -</span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">全连接层</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">        </span></span><span style="color:#cf8e6d;"><span leaf="">for </span></span><span leaf="">fc </span><span style="color:#cf8e6d;"><span leaf="">in </span></span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.fc_layers[:-</span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">]:</span><span leaf=""><br/></span><span leaf="">            x = torch.relu(fc(x))</span><span leaf=""><br/></span><span leaf="">        x = </span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.fc_layers[-</span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">](x)  </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">最后一层全连接输出</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">        </span></span><span style="color:#cf8e6d;"><span leaf="">return </span></span><span leaf="">x</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------------------------</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">定义训练函数</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------------------------</span><span leaf=""><br/></span></span><span style="color:#cf8e6d;"><span leaf="">def </span></span><span style="color:#56a8f5;"><span leaf="">train_model</span></span><span leaf="">(model, trainloader, testloader, epochs=</span><span style="color:#2aacb8;"><span leaf="">5</span></span><span leaf="">):</span><span leaf=""><br/></span><span leaf="">    criterion = nn.CrossEntropyLoss()</span><span leaf=""><br/></span><span leaf="">    optimizer = optim.Adam(model.parameters(), </span><span style="color:#aa4926;"><span leaf="">lr</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">0.001</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    device = torch.device(</span><span style="color:#6aab73;"><span leaf="">&#34;cuda&#34; </span></span><span style="color:#cf8e6d;"><span leaf="">if </span></span><span leaf="">torch.cuda.is_available() </span><span style="color:#cf8e6d;"><span leaf="">else </span></span><span style="color:#6aab73;"><span leaf="">&#34;cpu&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    model.to(device)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#cf8e6d;"><span leaf="">for </span></span><span leaf="">epoch </span><span style="color:#cf8e6d;"><span leaf="">in </span></span><span style="color:#8888c6;"><span leaf="">range</span></span><span leaf="">(epochs):</span><span leaf=""><br/></span><span leaf="">        model.train()</span><span leaf=""><br/></span><span leaf="">        running_loss = </span><span style="color:#2aacb8;"><span leaf="">0.0</span><span leaf=""><br/></span></span><span style="color:#2aacb8;"><span leaf="">        </span></span><span leaf="">correct = </span><span style="color:#2aacb8;"><span leaf="">0</span><span leaf=""><br/></span></span><span style="color:#2aacb8;"><span leaf="">        </span></span><span leaf="">total = </span><span style="color:#2aacb8;"><span leaf="">0</span><span leaf=""><br/></span></span><span style="color:#2aacb8;"><span leaf="">        </span></span><span style="color:#cf8e6d;"><span leaf="">for </span></span><span leaf="">images, labels </span><span style="color:#cf8e6d;"><span leaf="">in </span></span><span leaf="">trainloader:</span><span leaf=""><br/></span><span leaf="">            images, labels = images.to(device), labels.to(device)</span><span leaf=""><br/></span><span leaf="">            optimizer.zero_grad()</span><span leaf=""><br/></span><span leaf="">            outputs = model(images)</span><span leaf=""><br/></span><span leaf="">            loss = criterion(outputs, labels)</span><span leaf=""><br/></span><span leaf="">            loss.backward()</span><span leaf=""><br/></span><span leaf="">            optimizer.step()</span><span leaf=""><br/></span><span leaf="">            running_loss += loss.item()</span><span leaf=""><br/></span><span leaf="">            _, predicted = torch.max(outputs, </span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">            total += labels.size(</span><span style="color:#2aacb8;"><span leaf="">0</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">            correct += (predicted == labels).sum().item()</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">        accuracy = </span><span style="color:#2aacb8;"><span leaf="">100 </span></span><span leaf="">* correct / total</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">f&#34;Epoch </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">epoch + </span><span style="color:#2aacb8;"><span leaf="">1</span></span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">, Loss: </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">running_loss / </span><span style="color:#8888c6;"><span leaf="">len</span></span><span leaf="">(trainloader)</span><span style="color:#cf8e6d;"><span leaf="">:</span></span><span style="color:#6aab73;"><span leaf="">.4f</span></span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">, Accuracy: </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">accuracy</span><span style="color:#cf8e6d;"><span leaf="">:</span></span><span style="color:#6aab73;"><span leaf="">.2f</span></span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">%&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">测试阶段</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">model.eval()</span><span leaf=""><br/></span><span leaf="">    correct = </span><span style="color:#2aacb8;"><span leaf="">0</span><span leaf=""><br/></span></span><span style="color:#2aacb8;"><span leaf="">    </span></span><span leaf="">total = </span><span style="color:#2aacb8;"><span leaf="">0</span><span leaf=""><br/></span></span><span style="color:#2aacb8;"><span leaf="">    </span></span><span style="color:#cf8e6d;"><span leaf="">with </span></span><span leaf="">torch.no_grad():</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#cf8e6d;"><span leaf="">for </span></span><span leaf="">images, labels </span><span style="color:#cf8e6d;"><span leaf="">in </span></span><span leaf="">testloader:</span><span leaf=""><br/></span><span leaf="">            images, labels = images.to(device), labels.to(device)</span><span leaf=""><br/></span><span leaf="">            outputs = model(images)</span><span leaf=""><br/></span><span leaf="">            _, predicted = torch.max(outputs, </span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">            total += labels.size(</span><span style="color:#2aacb8;"><span leaf="">0</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">            correct += (predicted == labels).sum().item()</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    test_accuracy = </span><span style="color:#2aacb8;"><span leaf="">100 </span></span><span leaf="">* correct / total</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#cf8e6d;"><span leaf="">return </span></span><span leaf="">test_accuracy</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------------------------</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">定义</span></span><span style="color:#7a7e85;"><span leaf=""> Optuna </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">的目标函数来优化超参数</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------------------------</span><span leaf=""><br/></span></span><span style="color:#cf8e6d;"><span leaf="">def </span></span><span style="color:#56a8f5;"><span leaf="">objective</span></span><span leaf="">(trial):</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">选择卷积层的数量和每个卷积层的输出通道数</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">conv_layers = [trial.suggest_int(</span><span style="color:#6aab73;"><span leaf="">&#39;conv1_out_channels&#39;</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">32</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">128</span></span><span leaf="">),</span><span leaf=""><br/></span><span leaf="">                   trial.suggest_int(</span><span style="color:#6aab73;"><span leaf="">&#39;conv2_out_channels&#39;</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">64</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">256</span></span><span leaf="">)]</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">选择全连接层的神经元数量</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">fc_layers = [trial.suggest_int(</span><span style="color:#6aab73;"><span leaf="">&#39;fc1_out_features&#39;</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">128</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">512</span></span><span leaf="">)]</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">创建模型</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">model = DeepCNN(conv_layers, fc_layers)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">训练并返回在测试集上的准确率</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">accuracy = train_model(model, trainloader, testloader)</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#cf8e6d;"><span leaf="">return </span></span><span leaf="">accuracy</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------------------------</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">使用</span></span><span style="color:#7a7e85;"><span leaf=""> Optuna </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">进行超参数优化</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------------------------</span><span leaf=""><br/></span></span><span leaf="">study = optuna.create_study(</span><span style="color:#aa4926;"><span leaf="">direction</span></span><span leaf="">=</span><span style="color:#6aab73;"><span leaf="">&#39;maximize&#39;</span></span><span leaf="">)  </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">目标是最大化准确率</span><span leaf=""><br/></span></span><span leaf="">study.optimize(objective, </span><span style="color:#aa4926;"><span leaf="">n_trials</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">10</span></span><span leaf="">)  </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">进行</span></span><span style="color:#7a7e85;"><span leaf=""> 10 </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">次实验，尝试不同的超参数</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf=""><br/></span></span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">f&#34;Best hyperparameters: </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">study.best_params</span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">利用最佳参数构造模型，并进行最终训练</span><span leaf=""><br/></span></span><span leaf="">best_conv_layers = [study.best_params[</span><span style="color:#6aab73;"><span leaf="">&#39;conv1_out_channels&#39;</span></span><span leaf="">], study.best_params[</span><span style="color:#6aab73;"><span leaf="">&#39;conv2_out_channels&#39;</span></span><span leaf="">]]</span><span leaf=""><br/></span><span leaf="">best_fc_layers = [study.best_params[</span><span style="color:#6aab73;"><span leaf="">&#39;fc1_out_features&#39;</span></span><span leaf="">]]</span><span leaf=""><br/></span><span leaf="">best_model = DeepCNN(best_conv_layers, best_fc_layers)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">&#34;Training final model with best hyperparameters...&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">final_test_accuracy = train_model(best_model, trainloader, testloader, </span><span style="color:#aa4926;"><span leaf="">epochs</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">5</span></span><span leaf="">)</span><span leaf=""><br/></span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">f&#34;Final test accuracy with best hyperparameters: </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">final_test_accuracy</span><span style="color:#cf8e6d;"><span leaf="">:</span></span><span style="color:#6aab73;"><span leaf="">.2f</span></span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">%&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">保存最终模型到本地</span><span leaf=""><br/></span></span><span leaf="">torch.save(best_model.state_dict(), </span><span style="color:#6aab73;"><span leaf="">&#34;best_deep_cnn_model.pth&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">&#34;Best model saved as best_deep_cnn_model.pth&#34;</span></span><span leaf="">)</span></pre></td></tr></tbody></table><p style="text-align: left;"><span leaf="">代码2利用最佳的超参数，对模型进行全面评估。</span></p><table><tbody><tr><td data-colwidth="576" width="576"><pre style="font-family: &#34;JetBrains Mono&#34;, monospace;font-size: 9.8pt;text-align: left;"><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">torch</span><span leaf=""><br/></span><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">torch.nn </span><span style="color:#cf8e6d;"><span leaf="">as </span></span><span leaf="">nn</span><span leaf=""><br/></span><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">torch.optim </span><span style="color:#cf8e6d;"><span leaf="">as </span></span><span leaf="">optim</span><span leaf=""><br/></span><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">torchvision</span><span leaf=""><br/></span><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">torchvision.transforms </span><span style="color:#cf8e6d;"><span leaf="">as </span></span><span leaf="">transforms</span><span leaf=""><br/></span><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">optuna  </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">如果后续需要使用该工具进行超参数优化</span><span leaf=""><br/></span></span><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">numpy </span><span style="color:#cf8e6d;"><span leaf="">as </span></span><span leaf="">np</span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">matplotlib.pyplot </span><span style="color:#cf8e6d;"><span leaf="">as </span></span><span leaf="">plt</span><span leaf=""><br/></span><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">seaborn </span><span style="color:#cf8e6d;"><span leaf="">as </span></span><span leaf="">sns</span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#cf8e6d;"><span leaf="">from </span></span><span leaf="">sklearn.metrics </span><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">(precision_recall_fscore_support,</span><span leaf=""><br/></span><span leaf="">                             roc_auc_score,</span><span leaf=""><br/></span><span leaf="">                             confusion_matrix,</span><span leaf=""><br/></span><span leaf="">                             classification_report,</span><span leaf=""><br/></span><span leaf="">                             cohen_kappa_score,</span><span leaf=""><br/></span><span leaf="">                             balanced_accuracy_score,</span><span leaf=""><br/></span><span leaf="">                             roc_curve, auc)</span><span leaf=""><br/></span><span style="color:#cf8e6d;"><span leaf="">from </span></span><span leaf="">sklearn.preprocessing </span><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">label_binarize</span><span leaf=""><br/></span><span style="color:#cf8e6d;"><span leaf="">import </span></span><span leaf="">os</span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">数据增强与预处理</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">对训练数据新增数据增强：随机旋转</span></span><span style="color:#7a7e85;"><span leaf="">10</span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">度和随机平移（最大</span></span><span style="color:#7a7e85;"><span leaf="">10%</span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">的图像移动）</span><span leaf=""><br/></span></span><span leaf="">train_transform = transforms.Compose([</span><span leaf=""><br/></span><span leaf="">    transforms.RandomRotation(</span><span style="color:#2aacb8;"><span leaf="">10</span></span><span leaf="">),                </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">随机旋转</span></span><span style="color:#7a7e85;"><span leaf="">10</span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">度</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">transforms.RandomAffine(</span><span style="color:#aa4926;"><span leaf="">degrees</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">0</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">translate</span></span><span leaf="">=(</span><span style="color:#2aacb8;"><span leaf="">0.1</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">0.1</span></span><span leaf="">)),  </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">随机平移</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">transforms.ToTensor(),</span><span leaf=""><br/></span><span leaf="">    transforms.Normalize((</span><span style="color:#2aacb8;"><span leaf="">0.5</span></span><span leaf="">,), (</span><span style="color:#2aacb8;"><span leaf="">0.5</span></span><span leaf="">,))</span><span leaf=""><br/></span><span leaf="">])</span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">测试数据只做标准化，不做数据增强</span><span leaf=""><br/></span></span><span leaf="">test_transform = transforms.Compose([</span><span leaf=""><br/></span><span leaf="">    transforms.ToTensor(),</span><span leaf=""><br/></span><span leaf="">    transforms.Normalize((</span><span style="color:#2aacb8;"><span leaf="">0.5</span></span><span leaf="">,), (</span><span style="color:#2aacb8;"><span leaf="">0.5</span></span><span leaf="">,))</span><span leaf=""><br/></span><span leaf="">])</span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">数据加载与预处理</span><span leaf=""><br/></span></span><span leaf="">trainset = torchvision.datasets.MNIST(</span><span style="color:#aa4926;"><span leaf="">root</span></span><span leaf="">=</span><span style="color:#6aab73;"><span leaf="">&#39;./data&#39;</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">train</span></span><span leaf="">=</span><span style="color:#cf8e6d;"><span leaf="">True</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">download</span></span><span leaf="">=</span><span style="color:#cf8e6d;"><span leaf="">True</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">transform</span></span><span leaf="">=train_transform)</span><span leaf=""><br/></span><span leaf="">testset = torchvision.datasets.MNIST(</span><span style="color:#aa4926;"><span leaf="">root</span></span><span leaf="">=</span><span style="color:#6aab73;"><span leaf="">&#39;./data&#39;</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">train</span></span><span leaf="">=</span><span style="color:#cf8e6d;"><span leaf="">False</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">download</span></span><span leaf="">=</span><span style="color:#cf8e6d;"><span leaf="">True</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">transform</span></span><span leaf="">=test_transform)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">trainloader = torch.utils.data.DataLoader(trainset, </span><span style="color:#aa4926;"><span leaf="">batch_size</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">64</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">shuffle</span></span><span leaf="">=</span><span style="color:#cf8e6d;"><span leaf="">True</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">testloader = torch.utils.data.DataLoader(testset, </span><span style="color:#aa4926;"><span leaf="">batch_size</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">64</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">shuffle</span></span><span leaf="">=</span><span style="color:#cf8e6d;"><span leaf="">False</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">定义</span></span><span style="color:#7a7e85;"><span leaf=""> CNN </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">模型</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------</span><span leaf=""><br/></span></span><span style="color:#cf8e6d;"><span leaf="">class </span></span><span leaf="">CustomCNN(nn.Module):</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#cf8e6d;"><span leaf="">def </span></span><span style="color:#b200b2;"><span leaf="">__init__</span></span><span leaf="">(</span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">, conv1_out_channels, conv2_out_channels, fc1_out_features):</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#8888c6;"><span leaf="">super</span></span><span leaf="">(CustomCNN, </span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">).</span><span style="color:#b200b2;"><span leaf="">__init__</span></span><span leaf="">()</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.conv1 = nn.Conv2d(</span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">, conv1_out_channels, </span><span style="color:#aa4926;"><span leaf="">kernel_size</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">3</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">padding</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.conv2 = nn.Conv2d(conv1_out_channels, conv2_out_channels, </span><span style="color:#aa4926;"><span leaf="">kernel_size</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">3</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">padding</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.fc1 = nn.Linear(conv2_out_channels * </span><span style="color:#2aacb8;"><span leaf="">7 </span></span><span leaf="">* </span><span style="color:#2aacb8;"><span leaf="">7</span></span><span leaf="">, fc1_out_features)</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.fc2 = nn.Linear(fc1_out_features, </span><span style="color:#2aacb8;"><span leaf="">10</span></span><span leaf="">)  </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">输出</span></span><span style="color:#7a7e85;"><span leaf="">10</span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">个类别</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span style="color:#cf8e6d;"><span leaf="">def </span></span><span style="color:#56a8f5;"><span leaf="">forward</span></span><span leaf="">(</span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">, x):</span><span leaf=""><br/></span><span leaf="">        x = torch.relu(</span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.conv1(x))</span><span leaf=""><br/></span><span leaf="">        x = torch.max_pool2d(x, </span><span style="color:#2aacb8;"><span leaf="">2</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">        x = torch.relu(</span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.conv2(x))</span><span leaf=""><br/></span><span leaf="">        x = torch.max_pool2d(x, </span><span style="color:#2aacb8;"><span leaf="">2</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">        x = x.view(x.size(</span><span style="color:#2aacb8;"><span leaf="">0</span></span><span leaf="">), -</span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">        x = torch.relu(</span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.fc1(x))</span><span leaf=""><br/></span><span leaf="">        x = </span><span style="color:#94558d;"><span leaf="">self</span></span><span leaf="">.fc2(x)</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#cf8e6d;"><span leaf="">return </span></span><span leaf="">x</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">最佳超参数配置</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------</span><span leaf=""><br/></span></span><span leaf="">best_params = {</span><span style="color:#6aab73;"><span leaf="">&#39;conv1_out_channels&#39;</span></span><span leaf="">: </span><span style="color:#2aacb8;"><span leaf="">88</span></span><span leaf="">, </span><span style="color:#6aab73;"><span leaf="">&#39;conv2_out_channels&#39;</span></span><span leaf="">: </span><span style="color:#2aacb8;"><span leaf="">237</span></span><span leaf="">, </span><span style="color:#6aab73;"><span leaf="">&#39;fc1_out_features&#39;</span></span><span leaf="">: </span><span style="color:#2aacb8;"><span leaf="">389</span></span><span leaf="">}</span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">创建模型</span><span leaf=""><br/></span></span><span leaf="">model = CustomCNN(</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#aa4926;"><span leaf="">conv1_out_channels</span></span><span leaf="">=best_params[</span><span style="color:#6aab73;"><span leaf="">&#39;conv1_out_channels&#39;</span></span><span leaf="">],</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#aa4926;"><span leaf="">conv2_out_channels</span></span><span leaf="">=best_params[</span><span style="color:#6aab73;"><span leaf="">&#39;conv2_out_channels&#39;</span></span><span leaf="">],</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#aa4926;"><span leaf="">fc1_out_features</span></span><span leaf="">=best_params[</span><span style="color:#6aab73;"><span leaf="">&#39;fc1_out_features&#39;</span></span><span leaf="">]</span><span leaf=""><br/></span><span leaf="">)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">训练与评估函数</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------</span><span leaf=""><br/></span></span><span style="color:#cf8e6d;"><span leaf="">def </span></span><span style="color:#56a8f5;"><span leaf="">train_model</span></span><span leaf="">(model, trainloader, testloader, epochs=</span><span style="color:#2aacb8;"><span leaf="">5</span></span><span leaf="">):</span><span leaf=""><br/></span><span leaf="">    criterion = nn.CrossEntropyLoss()</span><span leaf=""><br/></span><span leaf="">    optimizer = optim.Adam(model.parameters(), </span><span style="color:#aa4926;"><span leaf="">lr</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">0.001</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    device = torch.device(</span><span style="color:#6aab73;"><span leaf="">&#34;cuda&#34; </span></span><span style="color:#cf8e6d;"><span leaf="">if </span></span><span leaf="">torch.cuda.is_available() </span><span style="color:#cf8e6d;"><span leaf="">else </span></span><span style="color:#6aab73;"><span leaf="">&#34;cpu&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    model.to(device)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">训练阶段</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span style="color:#cf8e6d;"><span leaf="">for </span></span><span leaf="">epoch </span><span style="color:#cf8e6d;"><span leaf="">in </span></span><span style="color:#8888c6;"><span leaf="">range</span></span><span leaf="">(epochs):</span><span leaf=""><br/></span><span leaf="">        model.train()</span><span leaf=""><br/></span><span leaf="">        running_loss = </span><span style="color:#2aacb8;"><span leaf="">0.0</span><span leaf=""><br/></span></span><span style="color:#2aacb8;"><span leaf="">        </span></span><span leaf="">correct = </span><span style="color:#2aacb8;"><span leaf="">0</span><span leaf=""><br/></span></span><span style="color:#2aacb8;"><span leaf="">        </span></span><span leaf="">total = </span><span style="color:#2aacb8;"><span leaf="">0</span><span leaf=""><br/></span></span><span style="color:#2aacb8;"><span leaf="">        </span></span><span style="color:#cf8e6d;"><span leaf="">for </span></span><span leaf="">images, labels </span><span style="color:#cf8e6d;"><span leaf="">in </span></span><span leaf="">trainloader:</span><span leaf=""><br/></span><span leaf="">            images, labels = images.to(device), labels.to(device)</span><span leaf=""><br/></span><span leaf="">            optimizer.zero_grad()</span><span leaf=""><br/></span><span leaf="">            outputs = model(images)</span><span leaf=""><br/></span><span leaf="">            loss = criterion(outputs, labels)</span><span leaf=""><br/></span><span leaf="">            loss.backward()</span><span leaf=""><br/></span><span leaf="">            optimizer.step()</span><span leaf=""><br/></span><span leaf="">            running_loss += loss.item()</span><span leaf=""><br/></span><span leaf="">            _, predicted = torch.max(outputs, </span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">            total += labels.size(</span><span style="color:#2aacb8;"><span leaf="">0</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">            correct += (predicted == labels).sum().item()</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">        accuracy = </span><span style="color:#2aacb8;"><span leaf="">100 </span></span><span leaf="">* correct / total</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">f&#34;Epoch </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">epoch + </span><span style="color:#2aacb8;"><span leaf="">1</span></span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">, Loss: </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">running_loss / </span><span style="color:#8888c6;"><span leaf="">len</span></span><span leaf="">(trainloader)</span><span style="color:#cf8e6d;"><span leaf="">:</span></span><span style="color:#6aab73;"><span leaf="">.4f</span></span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">, Accuracy: </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">accuracy</span><span style="color:#cf8e6d;"><span leaf="">:</span></span><span style="color:#6aab73;"><span leaf="">.2f</span></span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">%&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">评估阶段</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">model.eval()</span><span leaf=""><br/></span><span leaf="">    correct = </span><span style="color:#2aacb8;"><span leaf="">0</span><span leaf=""><br/></span></span><span style="color:#2aacb8;"><span leaf="">    </span></span><span leaf="">total = </span><span style="color:#2aacb8;"><span leaf="">0</span><span leaf=""><br/></span></span><span style="color:#2aacb8;"><span leaf="">    </span></span><span leaf="">all_preds = []  </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">存储预测标签</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">all_labels = []  </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">存储真实标签</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">all_probs = []  </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">存储模型输出的概率</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span style="color:#cf8e6d;"><span leaf="">with </span></span><span leaf="">torch.no_grad():</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#cf8e6d;"><span leaf="">for </span></span><span leaf="">images, labels </span><span style="color:#cf8e6d;"><span leaf="">in </span></span><span leaf="">testloader:</span><span leaf=""><br/></span><span leaf="">            images, labels = images.to(device), labels.to(device)</span><span leaf=""><br/></span><span leaf="">            outputs = model(images)</span><span leaf=""><br/></span><span leaf="">            probs = torch.softmax(outputs, </span><span style="color:#aa4926;"><span leaf="">dim</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">)  </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">将</span></span><span style="color:#7a7e85;"><span leaf=""> logits </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">转换为概率</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">            </span></span><span leaf="">_, predicted = torch.max(outputs, </span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">            total += labels.size(</span><span style="color:#2aacb8;"><span leaf="">0</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">            correct += (predicted == labels).sum().item()</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">            all_preds.extend(predicted.cpu().numpy())</span><span leaf=""><br/></span><span leaf="">            all_labels.extend(labels.cpu().numpy())</span><span leaf=""><br/></span><span leaf="">            all_probs.extend(probs.cpu().numpy())</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    test_accuracy = </span><span style="color:#2aacb8;"><span leaf="">100 </span></span><span leaf="">* correct / total</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">f&#34;</span></span><span style="color:#cf8e6d;"><span leaf="">\n</span></span><span style="color:#6aab73;"><span leaf="">Test Accuracy: </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">test_accuracy</span><span style="color:#cf8e6d;"><span leaf="">:</span></span><span style="color:#6aab73;"><span leaf="">.2f</span></span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">%&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">使用</span></span><span style="color:#7a7e85;"><span leaf=""> sklearn </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">计算宏平均的</span></span><span style="color:#7a7e85;"><span leaf=""> Precision</span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">、</span></span><span style="color:#7a7e85;"><span leaf="">Recall </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">和</span></span><span style="color:#7a7e85;"><span leaf=""> F1 </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">分数</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">precision, recall, f1, _ = precision_recall_fscore_support(all_labels, all_preds, </span><span style="color:#aa4926;"><span leaf="">average</span></span><span leaf="">=</span><span style="color:#6aab73;"><span leaf="">&#39;macro&#39;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">f&#34;Macro Precision: </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">precision</span><span style="color:#cf8e6d;"><span leaf="">:</span></span><span style="color:#6aab73;"><span leaf="">.4f</span></span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">f&#34;Macro Recall:    </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">recall</span><span style="color:#cf8e6d;"><span leaf="">:</span></span><span style="color:#6aab73;"><span leaf="">.4f</span></span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">f&#34;Macro F1 Score:  </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">f1</span><span style="color:#cf8e6d;"><span leaf="">:</span></span><span style="color:#6aab73;"><span leaf="">.4f</span></span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">混淆矩阵</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">cm = confusion_matrix(all_labels, all_preds)</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">&#34;</span></span><span style="color:#cf8e6d;"><span leaf="">\n</span></span><span style="color:#6aab73;"><span leaf="">Confusion Matrix:&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(cm)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">分类报告（包括每个类别的详细指标）</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">class_report = classification_report(all_labels, all_preds, </span><span style="color:#aa4926;"><span leaf="">target_names</span></span><span leaf="">=[</span><span style="color:#8888c6;"><span leaf="">str</span></span><span leaf="">(i) </span><span style="color:#cf8e6d;"><span leaf="">for </span></span><span leaf="">i </span><span style="color:#cf8e6d;"><span leaf="">in </span></span><span style="color:#8888c6;"><span leaf="">range</span></span><span leaf="">(</span><span style="color:#2aacb8;"><span leaf="">10</span></span><span leaf="">)])</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">&#34;</span></span><span style="color:#cf8e6d;"><span leaf="">\n</span></span><span style="color:#6aab73;"><span leaf="">Classification Report:&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(class_report)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">计算多类别</span></span><span style="color:#7a7e85;"><span leaf=""> ROC AUC </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">分数（使用</span></span><span style="color:#7a7e85;"><span leaf=""> One-vs-Rest </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">策略）</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">y_true_binarized = label_binarize(all_labels, </span><span style="color:#aa4926;"><span leaf="">classes</span></span><span leaf="">=</span><span style="color:#8888c6;"><span leaf="">list</span></span><span leaf="">(</span><span style="color:#8888c6;"><span leaf="">range</span></span><span leaf="">(</span><span style="color:#2aacb8;"><span leaf="">10</span></span><span leaf="">)))</span><span leaf=""><br/></span><span leaf="">    all_probs_array = np.array(all_probs)</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#cf8e6d;"><span leaf="">try</span></span><span leaf="">:</span><span leaf=""><br/></span><span leaf="">        roc_auc_overall = roc_auc_score(y_true_binarized, all_probs_array, </span><span style="color:#aa4926;"><span leaf="">multi_class</span></span><span leaf="">=</span><span style="color:#6aab73;"><span leaf="">&#39;ovr&#39;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">f&#34;Overall ROC AUC Score (OvR): </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">roc_auc_overall</span><span style="color:#cf8e6d;"><span leaf="">:</span></span><span style="color:#6aab73;"><span leaf="">.4f</span></span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#cf8e6d;"><span leaf="">except </span></span><span style="color:#8888c6;"><span leaf="">Exception </span></span><span style="color:#cf8e6d;"><span leaf="">as </span></span><span leaf="">e:</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">&#34;ROC AUC Score </span></span><span style="color:#6aab73;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">计算失败</span></span><span style="color:#6aab73;"><span leaf="">:&#34;</span></span><span leaf="">, e)</span><span leaf=""><br/></span><span leaf="">        roc_auc_overall = </span><span style="color:#cf8e6d;"><span leaf="">None</span><span leaf=""><br/></span></span><span style="color:#cf8e6d;"><span leaf=""><br/></span></span><span style="color:#cf8e6d;"><span leaf="">    </span></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">计算</span></span><span style="color:#7a7e85;"><span leaf=""> Cohen&#39;s Kappa </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">系数</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">kappa = cohen_kappa_score(all_labels, all_preds)</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">f&#34;Cohen&#39;s Kappa: </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">kappa</span><span style="color:#cf8e6d;"><span leaf="">:</span></span><span style="color:#6aab73;"><span leaf="">.4f</span></span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">计算平衡准确率</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">balanced_acc = balanced_accuracy_score(all_labels, all_preds)</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">f&#34;Balanced Accuracy: </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">balanced_acc</span><span style="color:#cf8e6d;"><span leaf="">:</span></span><span style="color:#6aab73;"><span leaf="">.4f</span></span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># ---------------------------</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf="">    # </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">绘制评估图像</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span style="color:#7a7e85;"><span leaf=""># ---------------------------</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf="">    # 1. </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">绘制混淆矩阵热力图</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">plt.figure(</span><span style="color:#aa4926;"><span leaf="">figsize</span></span><span leaf="">=(</span><span style="color:#2aacb8;"><span leaf="">8</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">6</span></span><span leaf="">))</span><span leaf=""><br/></span><span leaf="">    sns.heatmap(cm, </span><span style="color:#aa4926;"><span leaf="">annot</span></span><span leaf="">=</span><span style="color:#cf8e6d;"><span leaf="">True</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">fmt</span></span><span leaf="">=</span><span style="color:#6aab73;"><span leaf="">&#39;d&#39;</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">cmap</span></span><span leaf="">=</span><span style="color:#6aab73;"><span leaf="">&#39;Blues&#39;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    plt.title(</span><span style="color:#6aab73;"><span leaf="">&#39;Confusion Matrix&#39;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    plt.xlabel(</span><span style="color:#6aab73;"><span leaf="">&#39;Predicted Label&#39;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    plt.ylabel(</span><span style="color:#6aab73;"><span leaf="">&#39;True Label&#39;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    plt.show()</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># 2. </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">绘制多类别</span></span><span style="color:#7a7e85;"><span leaf=""> ROC </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">曲线</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">n_classes = </span><span style="color:#2aacb8;"><span leaf="">10</span><span leaf=""><br/></span></span><span style="color:#2aacb8;"><span leaf="">    </span></span><span leaf="">fpr = </span><span style="color:#8888c6;"><span leaf="">dict</span></span><span leaf="">()</span><span leaf=""><br/></span><span leaf="">    tpr = </span><span style="color:#8888c6;"><span leaf="">dict</span></span><span leaf="">()</span><span leaf=""><br/></span><span leaf="">    roc_auc = </span><span style="color:#8888c6;"><span leaf="">dict</span></span><span leaf="">()</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#cf8e6d;"><span leaf="">for </span></span><span leaf="">i </span><span style="color:#cf8e6d;"><span leaf="">in </span></span><span style="color:#8888c6;"><span leaf="">range</span></span><span leaf="">(n_classes):</span><span leaf=""><br/></span><span leaf="">        fpr[i], tpr[i], _ = roc_curve(y_true_binarized[:, i], all_probs_array[:, i])</span><span leaf=""><br/></span><span leaf="">        roc_auc[i] = auc(fpr[i], tpr[i])</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    plt.figure(</span><span style="color:#aa4926;"><span leaf="">figsize</span></span><span leaf="">=(</span><span style="color:#2aacb8;"><span leaf="">10</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">8</span></span><span leaf="">))</span><span leaf=""><br/></span><span leaf="">    colors = [</span><span style="color:#6aab73;"><span leaf="">&#39;aqua&#39;</span></span><span leaf="">, </span><span style="color:#6aab73;"><span leaf="">&#39;darkorange&#39;</span></span><span leaf="">, </span><span style="color:#6aab73;"><span leaf="">&#39;cornflowerblue&#39;</span></span><span leaf="">, </span><span style="color:#6aab73;"><span leaf="">&#39;green&#39;</span></span><span leaf="">, </span><span style="color:#6aab73;"><span leaf="">&#39;red&#39;</span></span><span leaf="">,</span><span leaf=""><br/></span><span leaf="">              </span><span style="color:#6aab73;"><span leaf="">&#39;purple&#39;</span></span><span leaf="">, </span><span style="color:#6aab73;"><span leaf="">&#39;brown&#39;</span></span><span leaf="">, </span><span style="color:#6aab73;"><span leaf="">&#39;pink&#39;</span></span><span leaf="">, </span><span style="color:#6aab73;"><span leaf="">&#39;gray&#39;</span></span><span leaf="">, </span><span style="color:#6aab73;"><span leaf="">&#39;olive&#39;</span></span><span leaf="">]</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#cf8e6d;"><span leaf="">for </span></span><span leaf="">i </span><span style="color:#cf8e6d;"><span leaf="">in </span></span><span style="color:#8888c6;"><span leaf="">range</span></span><span leaf="">(n_classes):</span><span leaf=""><br/></span><span leaf="">        plt.plot(fpr[i], tpr[i], </span><span style="color:#aa4926;"><span leaf="">color</span></span><span leaf="">=colors[i], </span><span style="color:#aa4926;"><span leaf="">lw</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">2</span></span><span leaf="">,</span><span leaf=""><br/></span><span leaf="">                 </span><span style="color:#aa4926;"><span leaf="">label</span></span><span leaf="">=</span><span style="color:#6aab73;"><span leaf="">&#39;Class {0} (AUC = {1:0.2f})&#39;</span></span><span leaf="">.format(i, roc_auc[i]))</span><span leaf=""><br/></span><span leaf="">    plt.plot([</span><span style="color:#2aacb8;"><span leaf="">0</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">], [</span><span style="color:#2aacb8;"><span leaf="">0</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">], </span><span style="color:#6aab73;"><span leaf="">&#39;k--&#39;</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">lw</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">2</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    plt.xlim([</span><span style="color:#2aacb8;"><span leaf="">0.0</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">1.0</span></span><span leaf="">])</span><span leaf=""><br/></span><span leaf="">    plt.ylim([</span><span style="color:#2aacb8;"><span leaf="">0.0</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">1.05</span></span><span leaf="">])</span><span leaf=""><br/></span><span leaf="">    plt.xlabel(</span><span style="color:#6aab73;"><span leaf="">&#39;False Positive Rate&#39;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    plt.ylabel(</span><span style="color:#6aab73;"><span leaf="">&#39;True Positive Rate&#39;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    plt.title(</span><span style="color:#6aab73;"><span leaf="">&#39;Multi-class ROC Curve&#39;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    plt.legend(</span><span style="color:#aa4926;"><span leaf="">loc</span></span><span leaf="">=</span><span style="color:#6aab73;"><span leaf="">&#34;lower right&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    plt.show()</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># 3. </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">绘制部分测试样本的预测结果</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">从</span></span><span style="color:#7a7e85;"><span leaf=""> testloader </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">中抽取一个</span></span><span style="color:#7a7e85;"><span leaf=""> batch</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf="">    </span></span><span leaf="">dataiter = </span><span style="color:#8888c6;"><span leaf="">iter</span></span><span leaf="">(testloader)</span><span leaf=""><br/></span><span leaf="">    sample_images, sample_labels = </span><span style="color:#8888c6;"><span leaf="">next</span></span><span leaf="">(dataiter)</span><span leaf=""><br/></span><span leaf="">    sample_images, sample_labels = sample_images.to(device), sample_labels.to(device)</span><span leaf=""><br/></span><span leaf="">    outputs = model(sample_images)</span><span leaf=""><br/></span><span leaf="">    _, sample_preds = torch.max(outputs, </span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    sample_images = sample_images.cpu().numpy()</span><span leaf=""><br/></span><span leaf="">    sample_labels = sample_labels.cpu().numpy()</span><span leaf=""><br/></span><span leaf="">    sample_preds = sample_preds.cpu().numpy()</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    plt.figure(</span><span style="color:#aa4926;"><span leaf="">figsize</span></span><span leaf="">=(</span><span style="color:#2aacb8;"><span leaf="">12</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">8</span></span><span leaf="">))</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#cf8e6d;"><span leaf="">for </span></span><span leaf="">idx </span><span style="color:#cf8e6d;"><span leaf="">in </span></span><span style="color:#8888c6;"><span leaf="">range</span></span><span leaf="">(</span><span style="color:#2aacb8;"><span leaf="">16</span></span><span leaf="">):  </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">显示前</span></span><span style="color:#7a7e85;"><span leaf="">16</span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">张图片</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">        </span></span><span leaf="">plt.subplot(</span><span style="color:#2aacb8;"><span leaf="">4</span></span><span leaf="">, </span><span style="color:#2aacb8;"><span leaf="">4</span></span><span leaf="">, idx + </span><span style="color:#2aacb8;"><span leaf="">1</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">        plt.imshow(sample_images[idx].squeeze(), </span><span style="color:#aa4926;"><span leaf="">cmap</span></span><span leaf="">=</span><span style="color:#6aab73;"><span leaf="">&#39;gray&#39;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">正确预测标为绿色，错误标为红色</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">        </span></span><span leaf="">color = </span><span style="color:#6aab73;"><span leaf="">&#34;green&#34; </span></span><span style="color:#cf8e6d;"><span leaf="">if </span></span><span leaf="">sample_preds[idx] == sample_labels[idx] </span><span style="color:#cf8e6d;"><span leaf="">else </span></span><span style="color:#6aab73;"><span leaf="">&#34;red&#34;</span><span leaf=""><br/></span></span><span style="color:#6aab73;"><span leaf="">        </span></span><span leaf="">plt.title(</span><span style="color:#6aab73;"><span leaf="">f&#34;P: </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">sample_preds[idx]</span><span style="color:#cf8e6d;"><span leaf="">}\n</span></span><span style="color:#6aab73;"><span leaf="">T: </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">sample_labels[idx]</span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">&#34;</span></span><span leaf="">, </span><span style="color:#aa4926;"><span leaf="">color</span></span><span leaf="">=color, </span><span style="color:#aa4926;"><span leaf="">fontsize</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">10</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">        plt.axis(</span><span style="color:#6aab73;"><span leaf="">&#34;off&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">    plt.tight_layout()</span><span leaf=""><br/></span><span leaf="">    plt.show()</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># ---------------------------</span><span leaf=""><br/></span></span><span style="color:#7a7e85;"><span leaf="">    # </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">整理所有评估指标到字典中返回</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">metrics = {</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#6aab73;"><span leaf="">&#39;test_accuracy&#39;</span></span><span leaf="">: test_accuracy,</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#6aab73;"><span leaf="">&#39;macro_precision&#39;</span></span><span leaf="">: precision,</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#6aab73;"><span leaf="">&#39;macro_recall&#39;</span></span><span leaf="">: recall,</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#6aab73;"><span leaf="">&#39;macro_f1&#39;</span></span><span leaf="">: f1,</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#6aab73;"><span leaf="">&#39;confusion_matrix&#39;</span></span><span leaf="">: cm,</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#6aab73;"><span leaf="">&#39;classification_report&#39;</span></span><span leaf="">: class_report,</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#6aab73;"><span leaf="">&#39;roc_auc_overall&#39;</span></span><span leaf="">: roc_auc_overall,</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#6aab73;"><span leaf="">&#39;cohen_kappa&#39;</span></span><span leaf="">: kappa,</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#6aab73;"><span leaf="">&#39;balanced_accuracy&#39;</span></span><span leaf="">: balanced_acc</span><span leaf=""><br/></span><span leaf="">    }</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#cf8e6d;"><span leaf="">return </span></span><span leaf="">metrics</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf=""><br/></span><span style="color:#cf8e6d;"><span leaf="">if </span></span><span leaf="">__name__ == </span><span style="color:#6aab73;"><span leaf="">&#39;__main__&#39;</span></span><span leaf="">:</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">先检查是否存在已保存的模型，若存在则直接加载，无需重新训练</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span leaf="">model_path = </span><span style="color:#6aab73;"><span leaf="">&#34;custom_cnn_mnist_1.pth&#34;</span><span leaf=""><br/></span></span><span style="color:#6aab73;"><span leaf="">    </span></span><span leaf="">device = torch.device(</span><span style="color:#6aab73;"><span leaf="">&#34;cuda&#34; </span></span><span style="color:#cf8e6d;"><span leaf="">if </span></span><span leaf="">torch.cuda.is_available() </span><span style="color:#cf8e6d;"><span leaf="">else </span></span><span style="color:#6aab73;"><span leaf="">&#34;cpu&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">若模型文件存在，则加载模型；否则进行训练</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">    </span></span><span style="color:#cf8e6d;"><span leaf="">if </span></span><span leaf="">os.path.exists(model_path):</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">f&#34;Found saved model at </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">model_path</span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">, loading model...&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">        model.load_state_dict(torch.load(model_path, </span><span style="color:#aa4926;"><span leaf="">map_location</span></span><span leaf="">=device))</span><span leaf=""><br/></span><span leaf="">        model.to(device)</span><span leaf=""><br/></span><span leaf="">        model.eval()</span><span leaf=""><br/></span><span leaf="">    </span><span style="color:#cf8e6d;"><span leaf="">else</span></span><span leaf="">:</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">&#34;No saved model found. Start training...&#34;</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">        metrics = train_model(model, trainloader, testloader, </span><span style="color:#aa4926;"><span leaf="">epochs</span></span><span leaf="">=</span><span style="color:#2aacb8;"><span leaf="">5</span></span><span leaf="">)</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#7a7e85;"><span leaf=""># </span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">保存模型参数，方便下次直接加载使用</span><span leaf=""><br/></span></span><span style="color:#7a7e85;font-family:&#39;Courier New&#39;,monospace;"><span leaf="">        </span></span><span leaf="">torch.save(model.state_dict(), model_path)</span><span leaf=""><br/></span><span leaf="">        </span><span style="color:#8888c6;"><span leaf="">print</span></span><span leaf="">(</span><span style="color:#6aab73;"><span leaf="">f&#34;Model saved to </span></span><span style="color:#cf8e6d;"><span leaf="">{</span></span><span leaf="">model_path</span><span style="color:#cf8e6d;"><span leaf="">}</span></span><span style="color:#6aab73;"><span leaf="">&#34;</span></span><span leaf="">)</span></pre><section><span leaf=""><br/></span></section></td></tr></tbody></table><p style="text-align: left;"><span leaf="">代码2输出F1与召回率有99.22%，如下图抽取数据进行预测，预测准确率还是很高的。</span></p><section style="text-align: left;" nodeleaf=""><img data-imgfileid="100001917" class="rich_pages wxw-img" data-ratio="0.6666666666666666" data-s="300,640" data-type="png" data-w="1080" type="block" src="https://wechat2rss.xlab.app/img-proxy/?k=f529fe4e&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0goUMY2myz52nqibiaRWUGrKT8CfThbmzErfaROKiak1BLYvIwCp3ckbQ8oS7MaJjsqvgDc4V65NbtNQ%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></section><section style="text-align: left;" nodeleaf=""><img data-imgfileid="100001918" class="rich_pages wxw-img" data-ratio="0.8" data-s="300,640" data-type="png" data-w="1000" type="block" src="https://wechat2rss.xlab.app/img-proxy/?k=0221e7d6&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0goUMY2myz52nqibiaRWUGrKTwLGYNSQHtQEh4WsgGmyrfx3PHOsHoOmY62IibPhLd1NrZdH0ZUdiaEnQ%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></section><section style="text-align: left;" nodeleaf=""><img data-imgfileid="100001919" class="rich_pages wxw-img" data-ratio="0.75" data-s="300,640" data-type="png" data-w="800" type="block" src="https://wechat2rss.xlab.app/img-proxy/?k=b75876ce&amp;u=https%3A%2F%2Fmmbiz.qpic.cn%2Fsz_mmbiz_png%2Fdib9GLOoSY0goUMY2myz52nqibiaRWUGrKTFavNqb7feGib76FGicp1QrYkE7EnZjb78icPA5mLaKT9iauicI1AWTpD21w%2F640%3Fwx_fmt%3Dpng%26from%3Dappmsg"/></section><p style="text-align: left;"><span leaf="">Test Accuracy: 99.22%</span></p><p style="text-align: left;"><span leaf="">Macro Precision: 0.9923</span></p><p style="text-align: left;"><span leaf="">Macro Recall:    0.9921</span></p><p style="text-align: left;"><span leaf="">Macro F1 Score:  0.9922</span></p><p style="text-align: left;"><span leaf=""><br/></span></p><p style="text-align: left;"><span leaf="">Confusion Matrix:</span></p><p style="text-align: left;"><span leaf="">[[ 977    0    0    0    0    0    1    1    1    0]</span></p><p style="text-align: left;"><span leaf="">[   0 1130    0    1    0    0    0    4    0    0]</span></p><p style="text-align: left;"><span leaf="">[   2    4 1015    0    0    0    0    9    2    0]</span></p><p style="text-align: left;"><span leaf="">[   0    0    0 1009    0    0    0    1    0    0]</span></p><p style="text-align: left;"><span leaf="">[   0    0    0    0  970    0    1    1    1    9]</span></p><p style="text-align: left;"><span leaf="">[   1    0    0    8    0  880    1    1    0    1]</span></p><p style="text-align: left;"><span leaf="">[   2    4    0    1    1    0  947    0    3    0]</span></p><p style="text-align: left;"><span leaf="">[   0    0    0    0    0    0    0 1026    1    1]</span></p><p style="text-align: left;"><span leaf="">[   2    0    2    0    0    0    0    0  969    1]</span></p><p style="text-align: left;"><span leaf="">[   0    0    0    1    1    2    0    4    2  999]]</span></p><p style="text-align: left;"><span leaf=""><br/></span></p><p style="text-align: left;"><span leaf="">Classification Report:</span></p><p style="text-align: left;"><span leaf="">              precision    recall  f1-score   support</span></p><p style="text-align: left;"><span leaf="">           0       0.99      1.00      0.99       980</span></p><p style="text-align: left;"><span leaf="">           1       0.99      1.00      0.99      1135</span></p><p style="text-align: left;"><span leaf="">           2       1.00      0.98      0.99      1032</span></p><p style="text-align: left;"><span leaf="">           3       0.99      1.00      0.99      1010</span></p><p style="text-align: left;"><span leaf="">           4       1.00      0.99      0.99       982</span></p><p style="text-align: left;"><span leaf="">           5       1.00      0.99      0.99       892</span></p><p style="text-align: left;"><span leaf="">           6       1.00      0.99      0.99       958</span></p><p style="text-align: left;"><span leaf="">           7       0.98      1.00      0.99      1028</span></p><p style="text-align: left;"><span leaf="">           8       0.99      0.99      0.99       974</span></p><p style="text-align: left;"><span leaf="">           9       0.99      0.99      0.99      1009</span></p><p style="text-align: left;"><span leaf="">    accuracy                           0.99     10000</span></p><p style="text-align: left;"><span leaf="">   macro avg       0.99      0.99      0.99     10000</span></p><p style="text-align: left;"><span leaf="">weighted avg       0.99      0.99      0.99     10000</span></p><p style="text-align: left;"><span leaf="">Overall ROC AUC Score (OvR): 1.0000</span></p><p style="text-align: left;"><span leaf="">Cohen&#39;s Kappa: 0.9913</span></p><p style="text-align: left;"><span leaf="">Balanced Accuracy: 0.9921</span></p><p style="display: none;"><mp-style-type data-value="3"></mp-style-type></p>



<p><a href="2247485571">阅读原文</a></p>
<p><a href="https://wechat2rss.xlab.app/link-proxy/?k=110da3b1&amp;r=1&amp;u=https%3A%2F%2Fmp.weixin.qq.com%2Fs%3F__biz%3DMzUyMTUwMzI3Ng%3D%3D%26mid%3D2247485571%26idx%3D1%26sn%3Dd51aa8f4c841386d80202428a0d598e9%26subscene%3D0">跳转微信打开</a></p>
]]></content:encoded>
      <pubDate>Sat, 22 Feb 2025 17:26:00 +0800</pubDate>
    </item>
  </channel>
</rss>