type
status
date
slug
summary
tags
category
icon
password
The Way Towards Best Codes
Attention:下面的问题顺序按照倒序来,越早的在越后面
52
51
50 PPT字体保存问题
使用问题:PPT中,某些字体无法随演示文稿一起保存。

解决方案:


Done!
49 Python到exe,狂踩坑后的救赎!
核心是两个技术问题
一个是streamlit库无法被主流python打包库识别,需要手动添加到spec里
另一个是conda虚拟环境与pyinstaller的兼容问题,conda的python环境与普通python环境的dll处理方式有差异
解决方案是使用原生python环境直接venv
下面是我看的几十个相关话题里,最有效和最有用的部分。
目前使用pyinstaller已经非常熟练了!
下面是一些参考的回答,不过大多都没用
https://stackoverflow.com/questions/60767017/importerror-dll-load-failed-while-importing-aggregations-the-specified-module
https://stackoverflow.com/questions/60763529/unable-to-import-pandas-pandas-libs-window-aggregations
https://stackoverflow.com/questions/60763529/unable-to-import-pandas-pandas-libs-window-aggregations
https://blog.csdn.net/yijie_01/article/details/139513580
https://www.google.com/search?q=pyinstaller%E5%A6%82%E4%BD%95%E6%89%93%E5%8C%85%E5%90%AB%E6%9C%89pandas+aggregations+%E7%9A%84dll&sca_esv=70277a813674651e&sxsrf=AE3TifNH2HCA-v4NQsrnau9inWWDRj0XEQ%3A1754555283531&ei=k2OUaJCeIPPf1e8PrtPF4QQ&ved=0ahUKEwjQs6fjo_iOAxXzb_UHHa5pMUwQ4dUDCBA&uact=5&oq=pyinstaller%E5%A6%82%E4%BD%95%E6%89%93%E5%8C%85%E5%90%AB%E6%9C%89pandas+aggregations+%E7%9A%84dll&gs_lp=Egxnd3Mtd2l6LXNlcnAiN3B5aW5zdGFsbGVy5aaC5L2V5omT5YyF5ZCr5pyJcGFuZGFzIGFnZ3JlZ2F0aW9ucyDnmoRkbGwyBRAAGO8FMggQABiABBiiBDIFEAAY7wUyBRAAGO8FMgUQABjvBUirPVDUCVjWPHADeACQAQCYAZkCoAGmEqoBBTAuOC40uAEDyAEA-AEB-AECmAIOoAKuEcICCBAAGLADGO8FwgILEAAYgAQYsAMYogTCAgQQIxgnwgIFECEYoAGYAwCIBgGQBgWSBwUzLjYuNaAHrDGyBwUwLjYuNbgHpBHCBwUwLjYuOMgHKw&sclient=gws-wiz-serp
https://www.bing.com/search?q=pyinstaller%e6%89%93%e5%8c%85%e4%b8%ba%e4%b8%80%e4%b8%aa%e6%96%87%e4%bb%b6%e5%a4%b9&qs=UT&pq=pyinstaller%e6%89%93%e5%8c%85%e4%b8%ba&sk=UT6&sc=12-14&cvid=8626F0B1163543D584E32ADD267A579C&FORM=QBRE&sp=7&lq=0&ntref=1
https://chatgpt.com/c/6894643a-4a44-8326-a760-a1dbdcc914a2
https://blog.csdn.net/yijie_01/article/details/139513580
https://www.google.com/search?q=pyinstaller%E5%A6%82%E4%BD%95%E6%89%93%E5%8C%85%E5%90%AB%E6%9C%89pandas%E7%9A%84%E5%BA%93aggregations+&sca_esv=70277a813674651e&sxsrf=AE3TifP9dBqtuO3rlimSAL18XX0k4iH6LA%3A1754553292789&ei=zFuUaKD0L7nM1e8P6s6rUA&ved=0ahUKEwigioaunPiOAxU5ZvUHHWrnCgoQ4dUDCBA&uact=5&oq=pyinstaller%E5%A6%82%E4%BD%95%E6%89%93%E5%8C%85%E5%90%AB%E6%9C%89pandas%E7%9A%84%E5%BA%93aggregations+&gs_lp=Egxnd3Mtd2l6LXNlcnAiNnB5aW5zdGFsbGVy5aaC5L2V5omT5YyF5ZCr5pyJcGFuZGFz55qE5bqTYWdncmVnYXRpb25zIDIFEAAY7wUyCBAAGIAEGKIEMgUQABjvBTIFEAAY7wUyCBAAGIAEGKIESPMKUPYBWKsHcAF4AJABAJgB5AGgAakDqgEFMC4xLjG4AQPIAQD4AQL4AQGYAgOgArMDwgIIEAAYsAMY7wXCAgsQABiABBiwAxiiBJgDAIgGAZAGBZIHBTEuMS4xoAfIBLIHBTAuMS4xuAeuA8IHBTAuMi4xyAcH&sclient=gws-wiz-serp
https://blog.csdn.net/m0_59066580/article/details/126661767
https://zhuanlan.zhihu.com/p/77028265
https://blog.51cto.com/u_14276/8832853
https://ithelp.ithome.com.tw/questions/10205861
https://www.bilibili.com/opus/595552139635714554
https://blog.csdn.net/qq_48979387/article/details/132359366
https://www.bing.com/search?q=pyinstaller%e6%89%93%e5%8c%85%e4%b8%ba%e4%b8%80%e4%b8%aa%e6%96%87%e4%bb%b6%e5%a4%b9&qs=UT&pq=pyinstaller%e6%89%93%e5%8c%85%e4%b8%ba&sk=UT6&sc=12-14&cvid=8626F0B1163543D584E32ADD267A579C&FORM=QBRE&sp=7&lq=0
https://blog.csdn.net/lzlxlzy/article/details/124545629
https://blog.csdn.net/m0_59066580/article/details/126661767
https://www.google.com/search?q=pyinstaller%E5%A6%82%E4%BD%95%E6%89%93%E5%8C%85%E5%90%AB%E6%9C%89pandas%E7%9A%84%E5%BA%93&sca_esv=70277a813674651e&sxsrf=AE3TifOlZsG6mnmfGde0IH854gkALoKXDw%3A1754552752824&ei=sFmUaNntMZzY1e8P78jLoA8&ved=0ahUKEwjZhcmsmviOAxUcbPUHHW_kEvQQ4dUDCBA&uact=5&oq=pyinstaller%E5%A6%82%E4%BD%95%E6%89%93%E5%8C%85%E5%90%AB%E6%9C%89pandas%E7%9A%84%E5%BA%93&gs_lp=Egxnd3Mtd2l6LXNlcnAiKXB5aW5zdGFsbGVy5aaC5L2V5omT5YyF5ZCr5pyJcGFuZGFz55qE5bqTMgUQABjvBTIIEAAYgAQYogQyBRAAGO8FMgUQABjvBTIFEAAY7wVIuUBQjAVYyz9wAXgAkAECmAH9AaABkziqAQYwLjM1Lji4AQPIAQD4AQGYAh2gAqEkwgIIEAAYsAMY7wXCAgsQABiwAxiiBBiJBcICCxAAGIAEGLADGKIEwgIJECEYoAEYChgqwgIHECEYoAEYCsICBBAjGCfCAggQABiiBBiJBcICBRAAGIAEwgIIEAAYgAQYywHCAgcQIxixAhgnwgIHEAAYgAQYCpgDAIgGAZAGBZIHBjEuMjIuNqAH4YgBsgcGMC4yMi42uAebJMIHBjAuMjMuNsgHSQ&sclient=gws-wiz-serp
https://fishc.com.cn/thread-174621-1-1.html
https://www.bing.com/search?q=%E8%A3%85Visual%20C%2B%2B%20Redistributable%20for%20Visual%20Studio%EF%BC%8C%E5%B9%B6%E7%A1%AE%E4%BF%9D%E7%89%88%E6%9C%AC%E4%B8%8E%E4%BD%A0%E7%9A%84Python%E8%A7%A3%E9%87%8A%E5%99%A8%E5%92%8CPyInstaller%E7%89%88%E6%9C%AC%E7%9B%B8%E5%8C%B9%E9%85%8D%E3%80%82&qs=n&form=QBRE&sp=-1&lq=0&pq=&sc=0-0&sk=&cvid=5467D73622684105A93D5C8D71845F66&ajf=60&mkt=zh-CN
https://cloud.baidu.com/article/2795305
https://cloud.tencent.com/developer/article/2550690
https://developer.baidu.com/article/detail.html?id=3311586
https://www.bing.com/search?q=pyinstaller%E5%AF%B9%E5%BA%94pandas%E7%89%88%E6%9C%AC&cvid=21d53970ac174c76b8d26e1caa6cf8ff&gs_lcrp=EgRlZGdlKgYIABBFGDkyBggAEEUYOTIHCAEQ6wcYQDIGCAIQABhAMgYIAxAAGEAyBggEEAAYQDIGCAUQABhAMgYIBhAAGEAyBggHEAAYQDIGCAgQABhA0gEJMTEyNjdqMGoxqAIIsAIB&FORM=ANAB01&adppc=EdgeStart&PC=U531&mkt=zh-CN
https://www.google.com/search?q=pyinstaller%E6%89%93%E5%8C%85%E5%90%8EDLL+load+failed&sca_esv=70277a813674651e&sxsrf=AE3TifOORthT8WCBuQXQQwQA2qy9DaCfBg%3A1754552432434&ei=cFiUaPykGrWovr0PnLHduAQ&ved=0ahUKEwj8nOaTmfiOAxU1lK8BHZxYF0cQ4dUDCBA&uact=5&oq=pyinstaller%E6%89%93%E5%8C%85%E5%90%8EDLL+load+failed&gs_lp=Egxnd3Mtd2l6LXNlcnAiI3B5aW5zdGFsbGVy5omT5YyF5ZCORExMIGxvYWQgZmFpbGVkMggQABiwAxjvBTILEAAYgAQYsAMYogQyCBAAGLADGO8FMggQABiwAxjvBTILEAAYgAQYsAMYogRI5QVQzAJYzAJwAXgAkAEAmAEAoAEAqgEAuAEDyAEA-AEC-AEBmAIBoAIGmAMAiAYBkAYFkgcBMaAHALIHALgHAMIHAzItMcgHAw&sclient=gws-wiz-serp
https://zhuanlan.zhihu.com/p/368416870
https://blog.csdn.net/qq_38418314/article/details/113992201
https://blog.csdn.net/Neil_001/article/details/121132604
https://www.google.com/search?q=pyinstaller%E6%89%93%E5%8C%85%E5%90%8E%E6%89%BE%E4%B8%8D%E5%88%B0dll&sca_esv=70277a813674651e&sxsrf=AE3TifOUAVAAgVd8P_wjgfZNZbkHGvhWDg%3A1754551020636&ei=7FKUaP_HJpLAvr0Pl-DJUA&ved=0ahUKEwj_7czyk_iOAxUSoK8BHRdwEgoQ4dUDCBA&uact=5&oq=pyinstaller%E6%89%93%E5%8C%85%E5%90%8E%E6%89%BE%E4%B8%8D%E5%88%B0dll&gs_lp=Egxnd3Mtd2l6LXNlcnAiIHB5aW5zdGFsbGVy5omT5YyF5ZCO5om-5LiN5YiwZGxsMgUQABjvBTIFEAAY7wUyCBAAGIAEGKIEMgUQABjvBTIIEAAYogQYiQVInVJQ3xZYzFFwAngBkAEAmAH6AaABoSuqAQYwLjMwLjW4AQPIAQD4AQGYAiGgAvwlwgIKEAAYsAMY1gQYR8ICDRAAGIAEGLEDGEMYigXCAgoQABiABBhDGIoFwgILEAAYgAQYsQMYgwHCAhAQABiABBixAxhDGIMBGIoFwgIFEAAYgATCAggQLhiABBixA8ICCBAAGIAEGMsBwgIHEAAYgAQYDJgDAIgGAZAGApIHBjIuMjcuNKAHkG6yBwYwLjI3LjS4B_ElwgcHMC4xOC4xNcgHaQ&sclient=gws-wiz-serp
https://chatgpt.com/c/68944def-a01c-8330-b1a9-db86880b7b3d
https://blog.csdn.net/qq_43215538/article/details/126161578#:~:text=%E5%AE%8C%E7%BE%8E%E8%A7%A3%E5%86%B3import%20cv2%20%E5%87%BA%E7%8E%B0ImportError:DLL%20load%20fail:%E6%89%BE%E4%B8%8D%E5%88%B0%E6%8C%87%E5%AE%9A%E6%A8%A1%E5%9D%97%20%E7%84%B6%E8%80%8C%EF%BC%8C%E5%BD%93%E4%BD%A0%E5%B0%9D%E8%AF%95%E5%AF%BC%E5%85%A5%60cv2%60%E6%97%B6%EF%BC%8C%E5%8F%AF%E8%83%BD%E4%BC%9A%E9%81%87%E5%88%B0%60ImportError:%20DLL%20load.
https://www.google.com/search?q=ImportError%3A%20DLL%20load%20failed%20while%20importing%20aggregations%3A%20%E6%89%BE%E4%B8%8D%E5%88%B0%E6%8C%87%E5%AE%9A%E7%9A%84%E6%A8%A1%E5%9D%97%E3%80%82
https://cloud.baidu.com/article/3311530
https://stackoverflow.com/questions/60767017/importerror-dll-load-failed-while-importing-aggregations-the-specified-module
https://blog.csdn.net/jianmoumou233/article/details/106690928
https://www.google.com/search?q=pandas%E8%BF%9B%E8%A1%8Cpython%E6%89%93%E5%8C%85exe%E6%97%B6ImportError%3A+DLL+load+failed+while+importing+aggregations%3A+%E6%89%BE%E4%B8%8D%E5%88%B0%E6%8C%87%E5%AE%9A%E7%9A%84%E6%A8%A1%E5%9D%97%E3%80%82&sca_esv=446501d459bf113a&sxsrf=AE3TifMDoiSE7MGmUtLJhSfymskxPtUctA%3A1754550228657&ei=1E-UaLTYJ4nD1e8P3JPj0QQ&ved=0ahUKEwi0kvr4kPiOAxWJYfUHHdzJOEoQ4dUDCBA&uact=5&oq=pandas%E8%BF%9B%E8%A1%8Cpython%E6%89%93%E5%8C%85exe%E6%97%B6ImportError%3A+DLL+load+failed+while+importing+aggregations%3A+%E6%89%BE%E4%B8%8D%E5%88%B0%E6%8C%87%E5%AE%9A%E7%9A%84%E6%A8%A1%E5%9D%97%E3%80%82&gs_lp=Egxnd3Mtd2l6LXNlcnAidHBhbmRhc-i_m-ihjHB5dGhvbuaJk-WMhWV4ZeaXtkltcG9ydEVycm9yOiBETEwgbG9hZCBmYWlsZWQgd2hpbGUgaW1wb3J0aW5nIGFnZ3JlZ2F0aW9uczog5om-5LiN5Yiw5oyH5a6a55qE5qih5Z2X44CCSABQAFgAcAB4AZABAJgBAKABAKoBALgBA8gBAPgBAZgCAKACAJgDAJIHAKAHALIHALgHAMIHAMgHAA&sclient=gws-wiz-serp
https://www.google.com/search?q=streamlit%E8%BF%9B%E8%A1%8Cpython%E6%89%93%E5%8C%85exe%E6%97%B6ImportError%3A+DLL+load+failed+while+importing+aggregations%3A+%E6%89%BE%E4%B8%8D%E5%88%B0%E6%8C%87%E5%AE%9A%E7%9A%84%E6%A8%A1%E5%9D%97%E3%80%82&sca_esv=446501d459bf113a&sxsrf=AE3TifNUO35TXMYqwSNhPo4V6VhH1IWXPg%3A1754546798680&ei=bkKUaPSUKcKLvr0P5MnWgA4&ved=0ahUKEwj0g7WVhPiOAxXCha8BHeSkFeAQ4dUDCBA&uact=5&oq=streamlit%E8%BF%9B%E8%A1%8Cpython%E6%89%93%E5%8C%85exe%E6%97%B6ImportError%3A+DLL+load+failed+while+importing+aggregations%3A+%E6%89%BE%E4%B8%8D%E5%88%B0%E6%8C%87%E5%AE%9A%E7%9A%84%E6%A8%A1%E5%9D%97%E3%80%82&gs_lp=Egxnd3Mtd2l6LXNlcnAid3N0cmVhbWxpdOi_m-ihjHB5dGhvbuaJk-WMhWV4ZeaXtkltcG9ydEVycm9yOiBETEwgbG9hZCBmYWlsZWQgd2hpbGUgaW1wb3J0aW5nIGFnZ3JlZ2F0aW9uczog5om-5LiN5Yiw5oyH5a6a55qE5qih5Z2X44CCMgoQABiwAxjWBBhHMgoQABiwAxjWBBhHSNYRUE5YTnABeAGQAQCYAQCgAQCqAQC4AQPIAQD4AQL4AQGYAgGgAgqYAwCIBgGQBgKSBwExoAcAsgcAuAcAwgcDMi0xyAcD&sclient=gws-wiz-serp
https://chatgpt.com/c/68944def-a01c-8330-b1a9-db86880b7b3d
https://chatgpt.com/?prompt=ImportError%3A+DLL+load+failed+while+importing+aggregations%3A+%E6%89%BE%E4%B8%8D%E5%88%B0%E6%8C%87%E5%AE%9A%E7%9A%84%E6%A8%A1%E5%9D%97%E3%80%82%0A%0AFile+%22streamlit%5Cruntime%5Cscriptrunner%5Cexec_code.py%22%2C+line+128%2C+in+exec_func_with_error_handling%0A++++result+%3D+func%28%29%0AFile+%22streamlit%5Cruntime%5Cscriptrunner%5Cscript_runner.py%22%2C+line+669%2C+in+code_to_exec%0A++++exec%28code%2C+module.__dict__%29++%23+noqa%3A+S102%0AFile+%22D%3A%5CCode%5C20250807_UTDTI%5Cdist%5Cdashboard.py%22%2C+line+2%2C+in+%3Cmodule%3E%0A++++import+pandas+as+pd%0AFile+%22PyInstaller%5Cloader%5Cpyimod02_importers.py%22%2C+line+457%2C+in+exec_module%0AFile+%22pandas%5C__init__.py%22%2C+line+80%2C+in+%3Cmodule%3E%0AFile+%22PyInstaller%5Cloader%5Cpyimod02_importers.py%22%2C+line+457%2C+in+exec_module%0AFile+%22pandas%5Ccore%5Capi.py%22%2C+line+47%2C+in+%3Cmodule%3E%0AFile+%22PyInstaller%5Cloader%5Cpyimod02_importers.py%22%2C+line+457%2C+in+exec_module%0AFile+%22pandas%5Ccore%5Cgroupby%5C__init__.py%22%2C+line+1%2C+in+%3Cmodule%3E%0AFile+%22PyInstaller%5Cloader%5Cpyimod02_importers.py%22%2C+line+457%2C+in+exec_module%0AFile+%22pandas%5Ccore%5Cgroupby%5Cgeneric.py%22%2C+line+68%2C+in+%3Cmodule%3E%0AFile+%22PyInstaller%5Cloader%5Cpyimod02_importers.py%22%2C+line+457%2C+in+exec_module%0AFile+%22pandas%5Ccore%5Cframe.py%22%2C+line+149%2C+in+%3Cmodule%3E%0AFile+%22PyInstaller%5Cloader%5Cpyimod02_importers.py%22%2C+line+457%2C+in+exec_module%0AFile+%22pandas%5Ccore%5Cgeneric.py%22%2C+line+193%2C+in+%3Cmodule%3E%0AFile+%22PyInstaller%5Cloader%5Cpyimod02_importers.py%22%2C+line+457%2C+in+exec_module%0AFile+%22pandas%5Ccore%5Cwindow%5C__init__.py%22%2C+line+1%2C+in+%3Cmodule%3E%0AFile+%22PyInstaller%5Cloader%5Cpyimod02_importers.py%22%2C+line+457%2C+in+exec_module%0AFile+%22pandas%5Ccore%5Cwindow%5Cewm.py%22%2C+line+11%2C+in+%3Cmodule%3E
https://usillyb.com/archives/643466d9-1dc0-477f-baad-92f51a057257
https://blog.csdn.net/m0_38045198/article/details/129579568
https://blog.csdn.net/nexttoparadise/article/details/135368387
https://www.google.com/search?q=streamlit%E8%BF%9B%E8%A1%8Cpython%E6%89%93%E5%8C%85exe%E6%97%B6%E6%89%BE%E4%B8%8D%E5%88%B0%20pyinstaller
https://blog.csdn.net/qq_48979387/article/details/132359366
下面展示一些常见bug






48 怎么生成电脑上文件夹的目录结构
有时我们会看见有人发布这样的内容:

这个是电脑上一个文件夹的目录结构,用于显示文件夹里各个文件的名称。怎么生成这样的目录呢?
一、按住shift键,右击你要生成目录的文件夹,选择“在此处打开命令窗口”
二、在命令窗口里输入命令“tree”,按回车。就会显示出目录结构。

三、如果需要将目录结构导出到文本文档,输入命令“tree >1.txt”。就会将目录结构保存到新建的“1.txt”。
四、如果需要显示子文件里的文件目录,可以使用命令“tree /f>1.txt”。
五、用bat实现自动生成目录结构。新建一个test.txt文件,输入“tree /f>1.txt”,保存后将test.txt,后缀改成bat,即test.bat。将test.bat复制到需要生成目录结构的文件夹,双击运行test.bat,就可以自动生成目录结构了。
47 Python中实验数据存储格式
预处理后最适合保存的格式一般如下:
- Pandas的DataFrame pickle格式(.pkl):如果后续继续用Python处理,pickle格式方便快速读写,能完整保存DataFrame数据结构和数据类型,避免每次都解析CSV,速度快且便于后续处理和分析。
- Parquet格式(.parquet):支持高效的列存储格式,压缩率好,读取速度快,适合中大型数据,且支持Pandas直接读写。适合存储结构化数据,方便后续特征工程和相关性分析。
- HDF5格式(.h5):适合大数据集保存,有层次化结构,也支持数据压缩,Pandas支持读写,适合多维科学数据。
一般流程建议:
- 用Pandas读取CSV文件后做预处理(清洗、缺失值处理、类型转换等)。
- 特征提取和相关性分析等操作完成后,将结果保存为pickle或parquet格式以便快速载入。
- 如果需要与其他语言或工具共享数据,建议保存CSV或Parquet(Parquet兼容性更好且效率更高)。
46 深入理解LightGBM
1. LightGBM简介
GBDT (Gradient Boosting Decision Tree) 是机器学习中一个长盛不衰的模型,其主要思想是利用弱分类器(决策树)迭代训练以得到最优模型,该模型具有训练效果好、不易过拟合等优点。GBDT不仅在工业界应用广泛,通常被用于多分类、点击率预测、搜索排序等任务;在各种数据挖掘竞赛中也是致命武器,据统计Kaggle上的比赛有一半以上的冠军方案都是基于GBDT。而LightGBM(Light Gradient Boosting Machine)是一个实现GBDT算法的框架,支持高效率的并行训练,并且具有更快的训练速度、更低的内存消耗、更好的准确率、支持分布式可以快速处理海量数据等优点。
1.1 LightGBM提出的动机
常用的机器学习算法,例如神经网络等算法,都可以以mini-batch的方式训练,训练数据的大小不会受到内存限制。而GBDT在每一次迭代的时候,都需要遍历整个训练数据多次。如果把整个训练数据装进内存则会限制训练数据的大小;如果不装进内存,反复地读写训练数据又会消耗非常大的时间。尤其面对工业级海量的数据,普通的GBDT算法是不能满足其需求的。
LightGBM提出的主要原因就是为了解决GBDT在海量数据遇到的问题,让GBDT可以更好更快地用于工业实践。
1.2 XGBoost的缺点及LightGBM的优化
(1)XGBoost的缺点
在LightGBM提出之前,最有名的GBDT工具就是XGBoost了,它是基于预排序方法的决策树算法。这种构建决策树的算法基本思想是:首先,对所有特征都按照特征的数值进行预排序。其次,在遍历分割点的时候用O(#data)的代价找到一个特征上的最好分割点。最后,在找到一个特征的最好分割点后,将数据分裂成左右子节点。
这样的预排序算法的优点是能精确地找到分割点。但是缺点也很明显:首先,空间消耗大。这样的算法需要保存数据的特征值,还保存了特征排序的结果(例如,为了后续快速的计算分割点,保存了排序后的索引),这就需要消耗训练数据两倍的内存。其次,时间上也有较大的开销,在遍历每一个分割点的时候,都需要进行分裂增益的计算,消耗的代价大。最后,对cache优化不友好。在预排序后,特征对梯度的访问是一种随机访问,并且不同的特征访问的顺序不一样,无法对cache进行优化。同时,在每一层长树的时候,需要随机访问一个行索引到叶子索引的数组,并且不同特征访问的顺序也不一样,也会造成较大的cache miss。
(2)LightGBM的优化
为了避免上述XGBoost的缺陷,并且能够在不损害准确率的条件下加快GBDT模型的训练速度,lightGBM在传统的GBDT算法上进行了如下优化:
- 基于Histogram的决策树算法。
- 单边梯度采样 Gradient-based One-Side Sampling(GOSS):使用GOSS可以减少大量只具有小梯度的数据实例,这样在计算信息增益的时候只利用剩下的具有高梯度的数据就可以了,相比XGBoost遍历所有特征值节省了不少时间和空间上的开销。
- 互斥特征捆绑 Exclusive Feature Bundling(EFB):使用EFB可以将许多互斥的特征绑定为一个特征,这样达到了降维的目的。
- 带深度限制的Leaf-wise的叶子生长策略:大多数GBDT工具使用低效的按层生长 (level-wise) 的决策树生长策略,因为它不加区分的对待同一层的叶子,带来了很多没必要的开销。实际上很多叶子的分裂增益较低,没必要进行搜索和分裂。LightGBM使用了带有深度限制的按叶子生长 (leaf-wise) 算法。
- 直接支持类别特征(Categorical Feature)
- 支持高效并行
- Cache命中率优化
下面我们就详细介绍以上提到的lightGBM优化算法。
2. LightGBM的基本原理
2.1 基于Histogram的决策树算法
(1)直方图算法
Histogram algorithm应该翻译为直方图算法,直方图算法的基本思想是:先把连续的浮点特征值离散化成 个整数,同时构造一个宽度为 的直方图。在遍历数据的时候,根据离散化后的值作为索引在直方图中累积统计量,当遍历一次数据后,直方图累积了需要的统计量,然后根据直方图的离散值,遍历寻找最优的分割点。

图:直方图算法
直方图算法简单理解为:首先确定对于每一个特征需要多少个箱子(bin)并为每一个箱子分配一个整数;然后将浮点数的范围均分成若干区间,区间个数与箱子个数相等,将属于该箱子的样本数据更新为箱子的值;最后用直方图(#bins)表示。看起来很高大上,其实就是直方图统计,将大规模的数据放在了直方图中。
我们知道特征离散化具有很多优点,如存储方便、运算更快、鲁棒性强、模型更加稳定等。对于直方图算法来说最直接的有以下两个优点:
- 内存占用更小:直方图算法不仅不需要额外存储预排序的结果,而且可以只保存特征离散化后的值,而这个值一般用 位整型存储就足够了,内存消耗可以降低为原来的 。也就是说XGBoost需要用位的浮点数去存储特征值,并用位的整形去存储索引,而 LightGBM只需要用 位去存储直方图,内存相当于减少为 ;

图:内存占用优化为预排序算法的1/8
- 计算代价更小:预排序算法XGBoost每遍历一个特征值就需要计算一次分裂的增益,而直方图算法LightGBM只需要计算 次( 可以认为是常数),直接将时间复杂度从降低到,而我们知道。
当然,Histogram算法并不是完美的。由于特征被离散化后,找到的并不是很精确的分割点,所以会对结果产生影响。但在不同的数据集上的结果表明,离散化的分割点对最终的精度影响并不是很大,甚至有时候会更好一点。原因是决策树本来就是弱模型,分割点是不是精确并不是太重要;较粗的分割点也有正则化的效果,可以有效地防止过拟合;即使单棵树的训练误差比精确分割的算法稍大,但在梯度提升(Gradient Boosting)的框架下没有太大的影响。
(2)直方图做差加速
LightGBM另一个优化是Histogram(直方图)做差加速。一个叶子的直方图可以由它的父亲节点的直方图与它兄弟的直方图做差得到,在速度上可以提升一倍。通常构造直方图时,需要遍历该叶子上的所有数据,但直方图做差仅需遍历直方图的k个桶。在实际构建树的过程中,LightGBM还可以先计算直方图小的叶子节点,然后利用直方图做差来获得直方图大的叶子节点,这样就可以用非常微小的代价得到它兄弟叶子的直方图。

图:直方图做差
注意:XGBoost 在进行预排序时只考虑非零值进行加速,而 LightGBM 也采用类似策略:只用非零特征构建直方图。
2.2 带深度限制的 Leaf-wise 算法
在Histogram算法之上,LightGBM进行进一步的优化。首先它抛弃了大多数GBDT工具使用的按层生长 (level-wise) 的决策树生长策略,而使用了带有深度限制的按叶子生长 (leaf-wise) 算法。
XGBoost 采用 Level-wise 的增长策略,该策略遍历一次数据可以同时分裂同一层的叶子,容易进行多线程优化,也好控制模型复杂度,不容易过拟合。但实际上Level-wise是一种低效的算法,因为它不加区分的对待同一层的叶子,实际上很多叶子的分裂增益较低,没必要进行搜索和分裂,因此带来了很多没必要的计算开销。

图:按层生长的决策树
LightGBM采用Leaf-wise的增长策略,该策略每次从当前所有叶子中,找到分裂增益最大的一个叶子,然后分裂,如此循环。因此同Level-wise相比,Leaf-wise的优点是:在分裂次数相同的情况下,Leaf-wise可以降低更多的误差,得到更好的精度;Leaf-wise的缺点是:可能会长出比较深的决策树,产生过拟合。因此LightGBM会在Leaf-wise之上增加了一个最大深度的限制,在保证高效率的同时防止过拟合。

图:按叶子生长的决策树
2.3 单边梯度采样算法
Gradient-based One-Side Sampling 应该被翻译为单边梯度采样(GOSS)。GOSS算法从减少样本的角度出发,排除大部分小梯度的样本,仅用剩下的样本计算信息增益,它是一种在减少数据量和保证精度上平衡的算法。
AdaBoost中,样本权重是数据重要性的指标。然而在GBDT中没有原始样本权重,不能应用权重采样。幸运的是,我们观察到GBDT中每个数据都有不同的梯度值,对采样十分有用。即梯度小的样本,训练误差也比较小,说明数据已经被模型学习得很好了,直接想法就是丢掉这部分梯度小的数据。然而这样做会改变数据的分布,将会影响训练模型的精确度,为了避免此问题,提出了GOSS算法。
GOSS是一个样本的采样算法,目的是丢弃一些对计算信息增益没有帮助的样本留下有帮助的。根据计算信息增益的定义,梯度大的样本对信息增益有更大的影响。因此,GOSS在进行数据采样的时候只保留了梯度较大的数据,但是如果直接将所有梯度较小的数据都丢弃掉势必会影响数据的总体分布。所以,GOSS首先将要进行分裂的特征的所有取值按照绝对值大小降序排序(XGBoost一样也进行了排序,但是LightGBM不用保存排序后的结果),选取绝对值最大的 个数据。然后在剩下的较小梯度数据中随机选择 个数据。接着将这 个数据乘以一个常数 ,这样算法就会更关注训练不足的样本,而不会过多改变原数据集的分布。最后使用这 个数据来计算信息增益。下图是GOSS的具体算法。

图:单边梯度采样算法
2.4 互斥特征捆绑算法
高维度的数据往往是稀疏的,这种稀疏性启发我们设计一种无损的方法来减少特征的维度。通常被捆绑的特征都是互斥的(即特征不会同时为非零值,像one-hot),这样两个特征捆绑起来才不会丢失信息。如果两个特征并不是完全互斥(部分情况下两个特征都是非零值),可以用一个指标对特征不互斥程度进行衡量,称之为冲突比率,当这个值较小时,我们可以选择把不完全互斥的两个特征捆绑,而不影响最后的精度。互斥特征捆绑算法(Exclusive Feature Bundling, EFB)指出如果将一些特征进行融合绑定,则可以降低特征数量。这样在构建直方图时的时间复杂度从 变为 ,这里 指特征融合绑定后特征包的个数,且 远小于 。
针对这种想法,我们会遇到两个问题:
- 怎么判定哪些特征应该绑在一起(build bundled)?
- 怎么把特征绑为一个(merge feature)?
(1)解决哪些特征应该绑在一起
将相互独立的特征进行绑定是一个 NP-Hard 问题,LightGBM的EFB算法将这个问题转化为图着色的问题来求解,将所有的特征视为图的各个顶点,将不是相互独立的特征用一条边连接起来,边的权重就是两个相连接的特征的总冲突值,这样需要绑定的特征就是在图着色问题中要涂上同一种颜色的那些点(特征)。此外,我们注意到通常有很多特征,尽管不是100%相互排斥,但也很少同时取非零值。 如果我们的算法可以允许一小部分的冲突,我们可以得到更少的特征包,进一步提高计算效率。经过简单的计算,随机污染小部分特征值将影响精度最多 , 是每个绑定中的最大冲突比率,当其相对较小时,能够完成精度和效率之间的平衡。具体步骤可以总结如下:
- 构造一个加权无向图,顶点是特征,边有权重,其权重与两个特征间冲突相关;
- 根据节点的度进行降序排序,度越大,与其它特征的冲突越大;
- 遍历每个特征,将它分配给现有特征包,或者新建一个特征包,使得总体冲突最小。
算法允许两两特征并不完全互斥来增加特征捆绑的数量,通过设置最大冲突比率 来平衡算法的精度和效率。EFB 算法的伪代码如下所示:

图:贪心绑定算法
算法3的时间复杂度是 ,训练之前只处理一次,其时间复杂度在特征不是特别多的情况下是可以接受的,但难以应对百万维度的特征。为了继续提高效率,LightGBM提出了一种更加高效的无图的排序策略:将特征按照非零值个数排序,这和使用图节点的度排序相似,因为更多的非零值通常会导致冲突,新算法在算法3基础上改变了排序策略。
(2)解决怎么把特征绑为一捆
特征合并算法,其关键在于原始特征能从合并的特征中分离出来。绑定几个特征在同一个bundle里需要保证绑定前的原始特征的值可以在bundle中识别,考虑到histogram-based算法将连续的值保存为离散的bins,我们可以使得不同特征的值分到bundle中的不同bin(箱子)中,这可以通过在特征值中加一个偏置常量来解决。比如,我们在bundle中绑定了两个特征A和B,A特征的原始取值为区间[0,10),B特征的原始取值为区间[0,20),我们可以在B特征的取值上加一个偏置常量10,将其取值范围变为[10,30),绑定后的特征取值范围为 [0, 30),这样就可以放心的融合特征A和B了。具体的特征合并算法如下所示:

图:特征合并算法
3. LightGBM的工程优化
我们将论文《Lightgbm: A highly efficient gradient boosting decision tree》中没有提到的优化方案,而在其相关论文《A communication-efficient parallel algorithm for decision tree》中提到的优化方案,放到本节作为LightGBM的工程优化来向大家介绍。
3.1 直接支持类别特征
实际上大多数机器学习工具都无法直接支持类别特征,一般需要把类别特征,通过 one-hot 编码,转化到多维的0/1特征,降低了空间和时间的效率。但我们知道对于决策树来说并不推荐使用 one-hot 编码,尤其当类别特征中类别个数很多的情况下,会存在以下问题:
- 会产生样本切分不平衡问题,导致切分增益非常小(即浪费了这个特征)。使用 one-hot编码,意味着在每一个决策节点上只能使用one vs rest(例如是不是狗,是不是猫等)的切分方式。例如,动物类别切分后,会产生是否狗,是否猫等一系列特征,这一系列特征上只有少量样本为 1,大量样本为 0,这时候切分样本会产生不平衡,这意味着切分增益也会很小。较小的那个切分样本集,它占总样本的比例太小,无论增益多大,乘以该比例之后几乎可以忽略;较大的那个拆分样本集,它几乎就是原始的样本集,增益几乎为零。比较直观的理解就是不平衡的切分和不切分没有区别。
- 会影响决策树的学习。因为就算可以对这个类别特征进行切分,独热编码也会把数据切分到很多零散的小空间上,如下图左边所示。而决策树学习时利用的是统计信息,在这些数据量小的空间上,统计信息不准确,学习效果会变差。但如果使用下图右边的切分方法,数据会被切分到两个比较大的空间,进一步的学习也会更好。下图右边叶子节点的含义是X=A或者X=C放到左孩子,其余放到右孩子。

图:左图为基于 one-hot 编码进行分裂,右图为 LightGBM 基于 many-vs-many 进行分裂
而类别特征的使用在实践中是很常见的。且为了解决one-hot编码处理类别特征的不足,LightGBM优化了对类别特征的支持,可以直接输入类别特征,不需要额外的0/1展开。LightGBM采用 many-vs-many 的切分方式将类别特征分为两个子集,实现类别特征的最优切分。假设某维特征有 k 个类别,则有 种可能,时间复杂度为 ,LightGBM 基于 Fisher的《On Grouping For Maximum Homogeneity》论文实现了 的时间复杂度。
算法流程如下图所示,在枚举分割点之前,先把直方图按照每个类别对应的label均值进行排序;然后按照排序的结果依次枚举最优分割点。从下图可以看到, 为类别的均值。当然,这个方法很容易过拟合,所以LightGBM里面还增加了很多对于这个方法的约束和正则化。

图:LightGBM求解类别特征的最优切分算法
在Expo数据集上的实验结果表明,相比0/1展开的方法,使用LightGBM支持的类别特征可以使训练速度加速8倍,并且精度一致。更重要的是,LightGBM是第一个直接支持类别特征的GBDT工具。
3.2 支持高效并行
(1)特征并行
特征并行的主要思想是不同机器在不同的特征集合上分别寻找最优的分割点,然后在机器间同步最优的分割点。XGBoost使用的就是这种特征并行方法。这种特征并行方法有个很大的缺点:就是对数据进行垂直划分,每台机器所含数据不同,然后使用不同机器找到不同特征的最优分裂点,划分结果需要通过通信告知每台机器,增加了额外的复杂度。
LightGBM 则不进行数据垂直划分,而是在每台机器上保存全部训练数据,在得到最佳划分方案后可在本地执行划分而减少了不必要的通信。具体过程如下图所示。

图:特征并行
(2)数据并行
传统的数据并行策略主要为水平划分数据,让不同的机器先在本地构造直方图,然后进行全局的合并,最后在合并的直方图上面寻找最优分割点。这种数据划分有一个很大的缺点:通讯开销过大。如果使用点对点通信,一台机器的通讯开销大约为 ;如果使用集成的通信,则通讯开销为 。
LightGBM在数据并行中使用分散规约 (Reduce scatter) 把直方图合并的任务分摊到不同的机器,降低通信和计算,并利用直方图做差,进一步减少了一半的通信量。具体过程如下图所示。

图:数据并行
(3)投票并行
基于投票的数据并行则进一步优化数据并行中的通信代价,使通信代价变成常数级别。在数据量很大的时候,使用投票并行的方式只合并部分特征的直方图从而达到降低通信量的目的,可以得到非常好的加速效果。具体过程如下图所示。
大致步骤为两步:
- 本地找出 Top K 特征,并基于投票筛选出可能是最优分割点的特征;
- 合并时只合并每个机器选出来的特征。

图:投票并行
3.3 Cache命中率优化
XGBoost对cache优化不友好,如下图所示。在预排序后,特征对梯度的访问是一种随机访问,并且不同的特征访问的顺序不一样,无法对cache进行优化。同时,在每一层长树的时候,需要随机访问一个行索引到叶子索引的数组,并且不同特征访问的顺序也不一样,也会造成较大的cache miss。为了解决缓存命中率低的问题,XGBoost 提出了缓存访问算法进行改进。

图:随机访问会造成cache miss
而 LightGBM 所使用直方图算法对 Cache 天生友好:
- 首先,所有的特征都采用相同的方式获得梯度(区别于XGBoost的不同特征通过不同的索引获得梯度),只需要对梯度进行排序并可实现连续访问,大大提高了缓存命中率;
- 其次,因为不需要存储行索引到叶子索引的数组,降低了存储消耗,而且也不存在 Cache Miss的问题。

图:LightGBM增加缓存命中率
4. LightGBM的优缺点
4.1 优点
这部分主要总结下 LightGBM 相对于 XGBoost 的优点,从内存和速度两方面进行介绍。
(1)速度更快
- LightGBM 采用了直方图算法将遍历样本转变为遍历直方图,极大的降低了时间复杂度;
- LightGBM 在训练过程中采用单边梯度算法过滤掉梯度小的样本,减少了大量的计算;
- LightGBM 采用了基于 Leaf-wise 算法的增长策略构建树,减少了很多不必要的计算量;
- LightGBM 采用优化后的特征并行、数据并行方法加速计算,当数据量非常大的时候还可以采用投票并行的策略;
- LightGBM 对缓存也进行了优化,增加了缓存命中率;
(2)内存更小
- XGBoost使用预排序后需要记录特征值及其对应样本的统计值的索引,而 LightGBM 使用了直方图算法将特征值转变为 bin 值,且不需要记录特征到样本的索引,将空间复杂度从 降低为 ,极大的减少了内存消耗;
- LightGBM 采用了直方图算法将存储特征值转变为存储 bin 值,降低了内存消耗;
- LightGBM 在训练过程中采用互斥特征捆绑算法减少了特征数量,降低了内存消耗。
4.2 缺点
- 可能会长出比较深的决策树,产生过拟合。因此LightGBM在Leaf-wise之上增加了一个最大深度限制,在保证高效率的同时防止过拟合;
- Boosting族是迭代算法,每一次迭代都根据上一次迭代的预测结果对样本进行权重调整,所以随着迭代不断进行,误差会越来越小,模型的偏差(bias)会不断降低。由于LightGBM是基于偏差的算法,所以会对噪点较为敏感;
- 在寻找最优解时,依据的是最优切分变量,没有将最优解是全部特征的综合这一理念考虑进去;
5. LightGBM实例
本篇文章所有数据集和代码均在我的GitHub中,地址:https://github.com/Microstrong0305/WeChat-zhihu-csdnblog-code/tree/master/Ensemble%20Learning/LightGBM
5.1 安装LightGBM依赖包
pip install lightgbm
5.2 LightGBM分类和回归
LightGBM有两大类接口:LightGBM原生接口 和 scikit-learn接口 ,并且LightGBM能够实现分类和回归两种任务。
(1)基于LightGBM原生接口的分类
import
lightgbm
as
lgb
from
sklearn
import
datasets
from
sklearn.model_selection
import
train_test_split
import
numpy
as
np
from
sklearn.metrics
import
roc_auc_score, accuracy_score
# 加载数据
iris
=
datasets
.
load_iris()
# 划分训练集和测试集
X_train, X_test, y_train, y_test
=
train_test_split(iris
.
data, iris
.
target, test_size
=
0.3)
# 转换为Dataset数据格式
train_data
=
lgb
.
Dataset(X_train, label
=
y_train)
validation_data
=
lgb
.
Dataset(X_test, label
=
y_test)
# 参数
params
=
{
'learning_rate': 0.1,
'lambda_l1': 0.1,
'lambda_l2': 0.2,
'max_depth': 4,
'objective': 'multiclass',
# 目标函数
'num_class': 3,
}
# 模型训练
gbm
=
lgb
.
train(params, train_data, valid_sets
=
[validation_data])
# 模型预测
y_pred
=
gbm
.
predict(X_test)
y_pred
=
[list(x)
.
index(max(x))
for
x
in
y_pred]
print(y_pred)
# 模型评估
print(accuracy_score(y_test, y_pred))
(2)基于Scikit-learn接口的分类
from lightgbm import LGBMClassifier
from sklearn.metrics import accuracy_score
from sklearn.model_selection import GridSearchCV
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.externals import joblib
# 加载数据
iris = load_iris()
data = iris.data
target = iris.target
# 划分训练数据和测试数据
X_train, X_test, y_train, y_test = train_test_split(data, target, test_size=0.2)
# 模型训练
gbm = LGBMClassifier(num_leaves=31, learning_rate=0.05, n_estimators=20)
gbm.fit(X_train, y_train, eval_set=[(X_test, y_test)], early_stopping_rounds=5)
# 模型存储
joblib.dump(gbm, 'loan_model.pkl')
# 模型加载
gbm = joblib.load('loan_model.pkl')
# 模型预测
y_pred = gbm.predict(X_test, num_iteration=gbm.best_iteration_)
# 模型评估
print('The accuracy of prediction is:', accuracy_score(y_test, y_pred))
# 特征重要度
print('Feature importances:', list(gbm.feature_importances_))
# 网格搜索,参数优化
estimator = LGBMClassifier(num_leaves=31)
param_grid = {
'learning_rate': [0.01, 0.1, 1],
'n_estimators': [20, 40]
}
gbm = GridSearchCV(estimator, param_grid)
gbm.fit(X_train, y_train)
print('Best parameters found by grid search are:', gbm.best_params_)
(3)基于LightGBM原生接口的回归
对于LightGBM解决回归问题,我们用Kaggle比赛中回归问题:House Prices: Advanced Regression Techniques,地址:https://www.kaggle.com/c/house-prices-advanced-regression-techniques 来进行实例讲解。
该房价预测的训练数据集中一共有81列,第一列是Id,最后一列是label,中间79列是特征。这79列特征中,有43列是分类型变量,33列是整数变量,3列是浮点型变量。训练数据集中存在缺失值。
import pandas as pd
from sklearn.model_selection import train_test_split
import lightgbm as lgb
from sklearn.metrics import mean_absolute_error
from sklearn.preprocessing import Imputer
# 1.读文件
data = pd.read_csv('./dataset/train.csv')
# 2.切分数据输入:特征 输出:预测目标变量
y = data.SalePrice
X = data.drop(['SalePrice'], axis=1).select_dtypes(exclude=['object'])
# 3.切分训练集、测试集,切分比例7.5 : 2.5
train_X, test_X, train_y, test_y = train_test_split(X.values, y.values, test_size=0.25)
# 4.空值处理,默认方法:使用特征列的平均值进行填充
my_imputer = Imputer()
train_X = my_imputer.fit_transform(train_X)
test_X = my_imputer.transform(test_X)
# 5.转换为Dataset数据格式
lgb_train = lgb.Dataset(train_X, train_y)
lgb_eval = lgb.Dataset(test_X, test_y, reference=lgb_train)
# 6.参数
params = {
'task': 'train',
'boosting_type': 'gbdt', # 设置提升类型
'objective': 'regression', # 目标函数
'metric': {'l2', 'auc'}, # 评估函数
'num_leaves': 31, # 叶子节点数
'learning_rate': 0.05, # 学习速率
'feature_fraction': 0.9, # 建树的特征选择比例
'bagging_fraction': 0.8, # 建树的样本采样比例
'bagging_freq': 5, # k 意味着每 k 次迭代执行bagging
'verbose': 1 # <0 显示致命的, =0 显示错误 (警告), >0 显示信息
}
# 7.调用LightGBM模型,使用训练集数据进行训练(拟合)
# Add verbosity=2 to print messages while running boosting
my_model = lgb.train(params, lgb_train, num_boost_round=20, valid_sets=lgb_eval, early_stopping_rounds=5)
# 8.使用模型对测试集数据进行预测
predictions = my_model.predict(test_X, num_iteration=my_model.best_iteration)
# 9.对模型的预测结果进行评判(平均绝对误差)
print("Mean Absolute Error : " + str(mean_absolute_error(predictions, test_y)))
(4)基于Scikit-learn接口的回归
import pandas as pd
from sklearn.model_selection import train_test_split
import lightgbm as lgb
from sklearn.metrics import mean_absolute_error
from sklearn.preprocessing import Imputer
# 1.读文件
data = pd.read_csv('./dataset/train.csv')
# 2.切分数据输入:特征 输出:预测目标变量
y = data.SalePrice
X = data.drop(['SalePrice'], axis=1).select_dtypes(exclude=['object'])
# 3.切分训练集、测试集,切分比例7.5 : 2.5
train_X, test_X, train_y, test_y = train_test_split(X.values, y.values, test_size=0.25)
# 4.空值处理,默认方法:使用特征列的平均值进行填充
my_imputer = Imputer()
train_X = my_imputer.fit_transform(train_X)
test_X = my_imputer.transform(test_X)
# 5.调用LightGBM模型,使用训练集数据进行训练(拟合)
# Add verbosity=2 to print messages while running boosting
my_model = lgb.LGBMRegressor(objective='regression', num_leaves=31, learning_rate=0.05, n_estimators=20,
verbosity=2)
my_model.fit(train_X, train_y, verbose=False)
# 6.使用模型对测试集数据进行预测
predictions = my_model.predict(test_X)
# 7.对模型的预测结果进行评判(平均绝对误差)
print("Mean Absolute Error : " + str(mean_absolute_error(predictions, test_y)))
5.3 LightGBM调参
在上一部分中,LightGBM模型的参数有一部分进行了简单的设置,但大都使用了模型的默认参数,但默认参数并不是最好的。要想让LightGBM表现的更好,需要对LightGBM模型进行参数微调。下图展示的是回归模型需要调节的参数,分类模型需要调节的参数与此类似。

6. 关于LightGBM若干问题的思考
6.1 LightGBM与XGBoost的联系和区别有哪些?
(1)LightGBM使用了基于histogram的决策树算法,这一点不同于XGBoost中的贪心算法和近似算法,histogram算法在内存和计算代价上都有不小优势。1)内存上优势:很明显,直方图算法的内存消耗为 (因为对特征分桶后只需保存特征离散化之后的值),而XGBoost的贪心算法内存消耗为: ,因为XGBoost既要保存原始feature的值,也要保存这个值的顺序索引,这些值需要32位的浮点数来保存。2)计算上的优势:预排序算法在选择好分裂特征计算分裂收益时需要遍历所有样本的特征值,时间为,而直方图算法只需要遍历桶就行了,时间为。
(2)XGBoost采用的是level-wise的分裂策略,而LightGBM采用了leaf-wise的策略,区别是XGBoost对每一层所有节点做无差别分裂,可能有些节点的增益非常小,对结果影响不大,但是XGBoost也进行了分裂,带来了不必要的开销。leaft-wise的做法是在当前所有叶子节点中选择分裂收益最大的节点进行分裂,如此递归进行,很明显leaf-wise这种做法容易过拟合,因为容易陷入比较高的深度中,因此需要对最大深度做限制,从而避免过拟合。
(3)XGBoost在每一层都动态构建直方图,因为XGBoost的直方图算法不是针对某个特定的特征,而是所有特征共享一个直方图(每个样本的权重是二阶导),所以每一层都要重新构建直方图,而LightGBM中对每个特征都有一个直方图,所以构建一次直方图就够了。
(4)LightGBM使用直方图做差加速,一个子节点的直方图可以通过父节点的直方图减去兄弟节点的直方图得到,从而加速计算。
(5)LightGBM支持类别特征,不需要进行独热编码处理。
(6)LightGBM优化了特征并行和数据并行算法,除此之外还添加了投票并行方案。
(7)LightGBM采用基于梯度的单边采样来减少训练样本并保持数据分布不变,减少模型因数据分布发生变化而造成的模型精度下降。
(8)特征捆绑转化为图着色问题,减少特征数量。
7. Reference
由于参考的文献较多,我把每篇参考文献按照自己的学习思路,进行了详细的归类和标注。
LightGBM论文解读:
【1】Ke G, Meng Q, Finley T, et al. Lightgbm: A highly efficient gradient boosting decision tree[C]//Advances in Neural Information Processing Systems. 2017: 3146-3154.
【2】Taifeng Wang分享LightGBM的视频,地址:https://v.qq.com/x/page/k0362z6lqix.html
【3】开源|LightGBM:三天内收获GitHub 1000+ 星,地址:https://mp.weixin.qq.com/s/M25d_43gHkk3FyG_Jhlvog
【4】Lightgbm源论文解析:LightGBM: A Highly Efficient Gradient Boosting Decision Tree,地址:https://blog.csdn.net/anshuai_aw1/article/details/83048709
【5】快的不要不要的lightGBM - 王乐的文章 - 知乎 https://zhuanlan.zhihu.com/p/31986189
【6】『 论文阅读』LightGBM原理-LightGBM: A Highly Efficient Gradient Boosting Decision Tree,地址:https://blog.csdn.net/shine19930820/article/details/79123216
LightGBM算法讲解:
【7】【机器学习】决策树(下)——XGBoost、LightGBM(非常详细) - 阿泽的文章 - 知乎 https://zhuanlan.zhihu.com/p/87885678
【8】入门 | 从结构到性能,一文概述XGBoost、Light GBM和CatBoost的同与不同,地址:https://mp.weixin.qq.com/s/TD3RbdDidCrcL45oWpxNmw
【9】CatBoost vs. Light GBM vs. XGBoost,地址:https://towardsdatascience.com/catboost-vs-light-gbm-vs-xgboost-5f93620723db
【10】机器学习算法之LightGBM,地址:https://www.biaodianfu.com/lightgbm.html
LightGBM工程优化:
【11】Meng Q, Ke G, Wang T, et al. A communication-efficient parallel algorithm for decision tree[C]//Advances in Neural Information Processing Systems. 2016: 1279-1287.
【12】Zhang H, Si S, Hsieh C J. GPU-acceleration for Large-scale Tree Boosting[J]. arXiv preprint arXiv:1706.08359, 2017.
【13】LightGBM的官方GitHub代码库,地址:https://github.com/microsoft/LightGBM
【14】关于sklearn中的决策树是否应该用one-hot编码? - 柯国霖的回答 - 知乎 https://www.zhihu.com/question/266195966/answer/306104444
LightGBM实例:
【15】LightGBM使用,地址:https://bacterous.github.io/2018/09/13/LightGBM%E4%BD%BF%E7%94%A8/
LightGBM若干问题的思考:
【17】GBDT、XGBoost、LightGBM的区别和联系,地址:https://www.jianshu.com/p/765efe2b951a
【18】xgboost和lightgbm的区别和适用场景,地址:https://www.nowcoder.com/ta/review-
45 关于Github Page(我的学术网页搭建)
44 如何评估显卡算力
部分数值由于厂家不同,略有出入 | ㅤ | ㅤ | ㅤ |
Nvidia Tesla T4 | Nvidia RTX 3090Ti | 该参数的作用 | |
架构 | Turing架构 | Ampere架构 | |
VERSUS网评分 | 52分 | 94分 | 综合评分 |
Tensor核心数 | 320个Tensor Core | 656个Tensor Core | 张量核支持混合精度计算,动态调整计算以加快吞吐量,同时保持精度。 |
CUDA数量 | 2560 | 10725 | CUDA运算速度只和核心频率有关,而CUDA核心数量则决定了显卡的计算力的强弱。(比如,一项渲染任务,可以拆分为更多份交给不同的CUDA核心进行处理) |
单精度浮点性能(FP32) | 8.1FLOPS | 代表显卡的浮点计算能力,越高算力越强。 | |
半精度浮点数(FP16) | 65TFLOPS | ||
INT4浮点性能 | 260TFLOPS | ||
浮点性能 | 7.76 TFLOPS | 40 TFLOPS | 浮点运算性能是衡量GPU处理器基本马力的方法 |
AI计算运行速度 | 320TFLOPS | ||
显存带宽(存储器带宽) | 320 GB/s | 1008 GB/s | 指显示芯片与显存之间的数据传输速率,它以字节/秒为单位。显存带宽是决定显卡性能和速度最重要的因素之一。 |
显存类型 | GDDR6 | GDDR6X | |
显存大小(VRAM) | 16G | 24G | 是显卡的专用内存。决定batch_size的上限 |
内存总线宽度(显存位宽) | 256bit | 384bit | 更宽的总线宽度代表在每个电脑运行周期能处理更多的数据。(代表GPU芯片每个时钟周期内能从GPU显卡中读取的数据大小,值越大,代表GPU芯片与显存之间的数据交换的速度越快。) |
GPU时脉速度 | 1005MHz | 1670MHz | |
核心频率 | 1582Mhz | 1560MHz | 只显示核心的工作频率,其工作频率在一定程度上可以反映出显示核心的性能。 |
超频频率(GPU TURBO) | 1590MHz | 1890MHz | 当cpu运行低于其限制速度时,其会促进更高的时钟速度,从而获得更高的性能。 |
纹理速率 | |||
像素率 | |||
功率 | 75w | 450w |
1. GPU的计算能力的衡量指标:显存大小、CUDA数量、计算主频;
2. 描述GPU计算能力的指标:计算峰值;存储器带宽;
3. GPU的计算峰值在进行边缘计算的时候是非常重要的。
单精度计算能力的峰值 = 单核单周期计算次数 * 处理核个数 * 主频;
FLOPS是每秒所执行的浮点运算次数,也就是GPU计算的基本单位;TFLOPS: 每秒一万亿次的浮点运算;
GPU计算浮点数的理论峰值 = GPU芯片数量 * GPU Boost主频 * 核心数量 * 单个时钟周期内能处理的浮点计算次数;
4. 带宽:带宽由频率和位宽两个因素所决定;计算公式为:带宽=频率*位宽/8
个人总结:
1. 个人觉得,这么看下来,显卡就是看:能存多少;存的有多快;算的有多快;对应就是:显存大小;带宽;浮点速度;
2. 在不考虑显存上限前提下,带宽,浮点速度同时影响GPU的性能;
3. 从上图所示,T4的处理速度是3090Ti的1/5,但交换速度同时也更慢,在1/3左右。因此T4的整体深度学习速度,大概会在 3090Ti的0.16倍~0.06倍之间;
43 VScode git管理最佳使用教程
42 我要终极解决方案!不再纠结环境!
首先,环境管理肯定用miniconda,省力多了!
其次,确认我的cuda等版本
41 更通透地安装pytorch和tensorflow
Tensorflow2.10版本后不再支持在Windows设备上使用GPU加速,所以windows下Tensorflow支持的CUDA最高版本为11.2;由于之前我安装Tensorflow时安装了11.2版本的CUDA,为了节省空间不安装两个版本的CUDA,这里直接使用11.2版本的CUDA。如果后续因为版本问题需要安装更高版本的Pytorch再安装其他版本的CUDA即可,方法是一样的。
我仔细看了一下,我的cuda在环境变量中的配置就是11.3,以后就安装对应版本的tensorflow吧,也就是2.5
但是,在很多情况下,我的当前环境完全不适配,因此,选择卸载现有cuda,升级到12.4版本,以应对不同挑战
注意:cuda12.4 对应的版本应为
推翻前面的!!!
虚拟环境似乎支持独立的cuda
详见‣结论来说
- 查看tensorflow-cuDNN-cuda之间的对应关系(Build from source on Windows TensorFlow (google.cn))

- conda install cudatoolkit=11.2
- conda install cudnn=8.1
- pip install tensorflow==2.6.0安装时间可能久一点,一般是下载时间
- 检查是否安装成功

- 查看是否能够加载GPU

持续报错,上网查询,还要调整keras的版本

pip install keras==2.6
Could not load dynamic library 'cudart64_110.dll’
总结:目前debug不能完全依靠ai,还是得上网
40 在vscode终端打开conda环境
‣
这个照着做,确实有用
核心是新建一个终端配置,并给一下具体的路径参数
39 conda指令复习
删除环境 conda env remove --name 环境名
38 C盘的 Roaming 文件夹可以删除吗?
太长不看版本:不能直接删除文件夹,通过软件删除垃圾文件即可,也可以针对其中没用过的软件进行文件定点清除
可以删除的内容
在 Roaming 文件夹中,有一些文件是可以安全删除的,尤其是那些不再需要或者过时的文件。
1.临时文件:一些应用程序在使用过程中会生成临时文件,如果这些文件不再使用,可以安全删除。2.旧版应用程序数据:如果卸载了一个应用程序但仍然存在其数据文件夹,可以安全删除这些文件夹。
3.备份文件:某些软件会自动创建备份文件,这些文件通常以.bak或.old 扩展名结尾,如果确认不再需要,可以删除。
4.缓存数据:应用程序的缓存数据通常用于加速加载过程,但在一段时间后可能会积累大量无用数据,可以定期清理。
5.配置文件:有时候,应用程序会出现异常或崩溃,导致生成异常的配置文件,这些文件可以手动删除或重命名。
不建议删除的内容
Roaming 文件夹中的一些文件对系统的正常运行至关重要,因此不建议随意删除:
1.系统文件:任何标记为“系统”或“只读”的文件都不应被删除。
2.关键应用程序配置:大多数正规应用程序都会在 Roaming 文件夹中保存必要的配置文件,删除它们可能会导致程序无法正常启动。
3.个人数据:如文档、图片、音频文件等个人数据通常不会放在 Roaming 文件夹中,但如果误将其放在此处,删除前务必先备份。
37 克隆/复制环境Conda
conda create -n B --clone A
B是新环境的名字,A是老环境的名字
36 配置transunet的一些启发
关于pytorch版本适配的问题
注意区分区分 nvidia-smi、nvcc --version、CUDA Runtime 和 pip 安装的 PyTorch
nvcc 是 NVIDIA 的 CUDA 编译器,用于将 CUDA 程序编译成可执行文件。nvcc --version 命令显示的是你系统中安装的 CUDA Toolkit 版本,通常用于开发和编译 CUDA 程序。
CUDA Toolkit 版本:显示当前安装的 CUDA 编译工具的版本,包括 nvcc 编译器、库文件等。这个版本通常用来开发和构建基于 CUDA 的程序。
注意:CUDA Toolkit 版本 和 CUDA runtime 版本 可能不同,尤其是在 GPU 驱动版本较新的情况下。
当你通过 pip 安装 PyTorch(或其他支持 GPU 加速的深度学习框架)时,你实际上是安装了与特定 CUDA runtime 版本 兼容的 PyTorch 库。这些库包含了与 GPU 交互所需的 CUDA runtime,而无需手动安装完整的 CUDA Toolkit。
CUDA runtime:PyTorch 会依赖于你 GPU 驱动支持的 CUDA runtime 版本(由 nvidia-smi 显示)。
CUDA Toolkit:PyTorch 安装包不依赖于 CUDA Toolkit,因此你不需要手动安装完整的 CUDA 编译工具。如果你的系统只安装了 CUDA runtime(通过驱动程序提供),而没有安装 CUDA Toolkit,你仍然可以使用 PyTorch 来加速深度学习模型。
nvcc --version 与 nvidia-smi 显示的 CUDA version 不匹配:这通常是因为你系统安装了多个 CUDA 版本(如 CUDA Toolkit 和 GPU 驱动版本不一致)。nvcc 显示的是 CUDA Toolkit 的版本,而 nvidia-smi 显示的是与 GPU 驱动兼容的 CUDA runtime 版本。
CUDA Toolkit 版本低于 PyTorch 需要的 CUDA runtime 版本:如果你的 CUDA Toolkit 版本 低于 PyTorch 所需要的 CUDA runtime 版本,可能会出现不兼容问题。比如,PyTorch 可能依赖于 CUDA 11.x 或 12.x 的新特性,而你安装的 CUDA 10.2 不支持这些特性。
最重要的一点,可以向下兼容pytorch版本所需的cuda版本,所以我直接装大多数版本其实都行,只要注意一下pytorch版本和工具库就行,比如:

11.3的CUDA版本,1.11.0+cu113的torch版本,但其实我的电脑应该是12.8的cuda
 
35 VR第三方游戏配置
- language schinese -Steam -VR -novid +volume_fog_disable 1
加在快捷方式的属性exe后边
34 神经网络的优化问题
参数量过大从而避免陷入局部最优
33 更优的命名法
下划线规则更佳

32 torch curriculum
x = x.reshape(8,-1) # 这里的-1表示这个维度让torch自动推算,只要第一个维度是8就行
将后续几个维度都变成了一维,一般是直接连接
一个很重要的启示,通过绘制loss的走向可以很明确的理解是不是过拟合,学习率是否合适,如何调整超参数等。
当然更好的方式是用如Adam、Adagrad等,它们可以根据梯度信息自动调节每个参数的学习率,减轻手动设定学习率的压力。
31 卷积神经网络
30 Torchsummary 这个库来看模型结构
from torchsummary import summary
model = Net()
summary(model, input_size=(1, 4, 1050)) # 输入形状 (channels, height, width)
29 神经网络 curriculum
28 Dataloader的一个坑
在 DataLoader 里,PyTorch 默认会 自动堆叠 (batching),如果 labels 长度不一致,可能会自动补全为 最大时间步长 (225)。
在 trainer.fit(model, train_dataloader, val_dataloader) 里:
DataLoader 会 自动将 batch 内样本堆叠,如果 labels 的时间步长 T 不是固定值,PyTorch 可能会自动 pad,导致变成 (batch_size, max_T),而不是 (batch_size,)。
CrossEntropyLoss 只接受 1D 整数索引的标签,但你的 labels.shape = (7, 225),所以报错 multi-target not supported。
27 模式识别·校内
少写code多炼丹
- 优化问题:全局最优的trick——
- 其实使用神经网络的时候参数量都很大,最后其实往往都会训练到过拟合,当模型的参数越多,实际上能拟合的复杂度就更大,也就越容易过拟合,这块好理解
- 针对上述问题,我们往往通过earlystopping来实现拟合
- 训练集与测试集分布不一致,应该通过domainadaption,来进行适应
- 在训练时loss降不下去怎么办——优化问题optimization
- 梯度消失:局部极小or极大,或是 鞍点
- 数学上就是找二阶导,但是实际问题里用hessian矩阵来进行判断,loss函数在此点的泰勒展开来进行数学推导
- Saddlepoint——附近特征根有大于零有小于零
- 另一种思路——退火法,从局部极小跳到全局极小
- 梯度爆炸?
- 常见库Adam
- 医生的问题:多少数据是足够的?实际上:很难确定
26 各种验证集的设置方案
Holdout Validation
在holdout验证中,我们只是执行一个简单的训练/测试分割,在这个分割中,我们将我们的模型适合我们的训练数据,并将其应用于我们的测试数据以生成预测值。 我们“保留”测试数据只用于严格的预测目的。 拒绝验证不是一种交叉验证技术。 但我们必须讨论模型评估的标准方法,以便将其属性与实际的交叉验证技术进行比较。
当涉及到代码时,拒绝验证很容易使用。 该实现很简单,不需要在计算能力和时间复杂度方面投入大量精力。 此外,我们可以更好地解释和理解holdout验证的结果,因为holdout验证不需要我们弄清楚迭代是如何执行的。
然而,在许多情况下,holdout验证并不能保持数据集的统计完整性。 例如,将数据分割成训练和测试部分的holdout验证由于没有将测试数据合并到模型中而导致了偏差。 测试数据可能包含一些重要的观察结果。 这将对模型的准确性造成损害。 此外,除了引入验证和/或训练误差之外,这将导致数据的欠拟合(underfiting)和过拟合(overfitting)。
K-fold Validation
在K-fold交叉验证中,我们回答了许多holdout验证固有的问题,如欠拟合(underfiting)和过拟合(overfitting)、验证和训练误差。 这是通过在某些迭代中使用验证集中的所有观察结果来实现的。 我们计算每k次迭代中计算的所有精度分数的平均精度分数。 通过这样做,我们最小化了可能出现在初步模型验证技术——holdout验证中的偏差和方差。
然而,就计算能力而言,k-fold交叉验证是非常昂贵的。 计算机必须进行几次迭代才能得到正确的分数。 理论上,模型的精度分数随着每增加k次迭代而增加。 这将减少偏差,同时增加variation。 当我们尝试将k-fold验证应用到包含大约58万个观测的非常大的数据集时,我们将在本文后面看到一个例子。
LOOCV
LOOCV 与 K-fold 非常相似,其中 是k 等于整个数据集的长度(或样本/行数)时的特殊情况。 因此,训练集的长度为 k-1,而测试集将是单个数据样本。 LOOCV 在我们的数据集特别小,不适合进行 K-fold 的情况下特别有用。 LOOCV 通常在计算上也非常昂贵,尽管它通常是倾向于在固有较小的数据集上使用。
然而,LOOCV 往往会产生高方差,因为该方法会通过单个测试值检测数据中所有可能的噪声和异常值。 对于非常大的数据集,LOOCV 的计算成本会非常高; 在这种情况下,最好使用常规的 k-fold。
25 Transformer教程
没看完,想先做自己的项目o(╥﹏╥)o
24 个人ai机器人远程云服务器部署
用astrbot + 云服务器
核心操作
Qq开发平台QQ机器人管理端
Astrbot官方文档
阿里云的教程
获取大模型的api
在服务器里部署astrbot然后设置我们的机器人相关参数
配置自己的远程服务器
在腾讯云通过68元/年进行租赁
不要选择没听说过的系统内核
此处我用的是ubantu
注意这里是轻量化服务器,无法进行图形化界面显示。
需要通过云服务器进行托管,用docker部署的时候发现会卡在astrbot下载,于是手动部署,直接上传一下本地的源码,准备配置环境的时候,发现轻量服务器中搭载的ide里边python环境又不响应,搞半天轻量服务器连图形化界面都没有。
sudo docker run -itd -p 6180-6200:6180-6200 -p 11451:11451 -v $PWD/data:/AstrBot/data --name astrbot soulter/astrbot:latest
sudo docker logs -f astrbot
换了一个代码来部署,部署好了又是因为没有图形化界面而打不开astrbot的管理界面,只能先装一个图形化界面,但愿能够有用。——结局,装到90%多不行了,暂时不想折腾了。
这里注意一个很重要的细节:我们安装部署后,里面会给一个local地址,我们能够通过这个地址对机器人进行配置,这里其实轻量服务器是无法打开的,但是神器的是,只需要把“local替换为“服务器的ip”,再加上原本的端口,就可以在自己的本地电脑打开我们的网页从而完成配置。
在云服务器上部署 AstrBot,需要将 localhost 替换为你的服务器 IP 地址。
配置好后挂起就行了,即便关闭了云端服务器的网页也会一直开机。
最麻烦的地方是隐私协议还有审核文档。
23 什么是mne,为什么要用mne
22 很好的网页保存方式
当然是 .mhtm格式!
直接ctrl+s 然后选择这个格式,就能用一个文件保存好网页啦,比pdf舒服多了!
21 更好的注释效果
在 Python 中,函数内部的注释(即 docstring)可以通过在函数定义后面添加一个字符串来实现。在函数名上悬停时,可以看到 docstring,这通常是函数的简要说明。
def sample_entropy(x):
""" 计算样本熵 """
return an.sample_entropy(x)
20 获得上上级目录
from pathlib import Path
# 获取当前文件的路径对象
current_file = Path(__file__).resolve()
# 获取上上级目录
parent_dir = current_file.parent.parent
# 示例:拼接上上级目录中的子文件
target_path = parent_dir / "data" / "file.txt"
print(target_path)
19 print的所有用法
18 Pytorch深入学习
17 几个常见ML模型的数学原理
似乎没那么重要,所以一直没复习……
16 为jupyter配置conda环境
按照这个教程做了,但不知道有没有起作用,
直接在vscode里选择对应内核就可以跑了。
15 GridSearchCV 自动超参数寻优
14 装饰器
@语法就是一个装饰语法
是帽子一样的功能

函数名作为参数传入到装饰器函数里,二者进行关联。
目的是通过多个装饰器,对一个函数进行多次调用,而实现一些有区别的功能。
里面常见的一个操作是传入参数 *args,来表示自己其实不知道里面有什么参数的传入和传出,也不太关心。
其实是有两种方法,第一种是严格定义一个装饰函数,来对业务函数进行修饰。
另一种方法,使用@
先@一个装饰器函数,再定义一个新的函数,这样的新函数就会被@的这个装饰函数给装饰,就可以在调用业务函数时,先到装饰函数里走一遭。

@intro
def eat(……):
那具体如何变化呢?
实际使用时是,一个装饰器用在多个业务函数上。
@intro
funcA(*args)
@intro
funcB(*args)
13 经验总结 一些快速上手完整Repository的trick
先找数据输出行:看看数据输出的结构
save_df(df, is_complete_dataset, output_dir, "raw", train_metadata)
glimpse_df(df)
df = df_replace_values(df)
save_df(df, is_complete_dataset, output_dir, "clean", train_metadata)
最终输出的是一个dataframe的pkl
反向寻找定义的函数save_df,此函数内部的核心传入了输出路径与命名。数据是通过df和train_metadata
def set_defaults(**kwargs: Any) -> None
**kwargs: 这是Python函数的一种特殊参数形式,表示接受一个任意数量的关键字参数。关键字参数的形式是以 key=value 的方式传递给方法。这里的 kwargs 是参数名,实际上它是一个字典,包含所有传入的关键字参数。
例如,当调用 set_defaults(param1=value1, param2=value2) 时,kwargs 将是一个字典:{'param1': value1, 'param2': value2}。kwargs 前的两个星号 ** 表示将参数打包为字典。如果函数没有这个语法,它只能接受固定数量的参数,无法处理不确定数量的输入。
Any: 在 kwargs 后面声明了类型注解 Any,这表明 kwargs 可以是任何类型的值。Any 是Python中一个特殊的类型,表示没有具体类型的限制,可以接受任何类型。
- > None: 这是返回值的类型注解,表示该方法不返回任何值。None 是Python中表示“无返回值”或“空值”的类型,通常用于表示方法执行完毕后没有任何需要返回的内容。
is_complete_dataset = not any(map(lambda arg_name, parser=parser, args=args: is_arg_default(arg_name, parser, args), ["driver_num", "signal_duration", "epoch_events_num", "channels_ignore"]))
这部分代码涉及的语法
12 python里类class里的_init_的作用
正常情况下,直接在class里定义的变量是公共的,一旦修改,后面实例化的对象也会继承修改后的部分。初始化函数就是为了使得每个实例具有自己个性的变量。

详细讲解↓

11.如何使用git为自己的编程助力
参考教程视频:给傻子的Git教程_bilibili
Github其实就像是steam的云存档服务
存档 仓库 项目 其实三位一体 都是一个东西 Repository
Publish to github 这一步就叫做push
具体来说,先要创建存档
其余配置都很简单,现在卡在了代理配置上,需要设置一个代理配置网址
最后管用的代码
git config --global http.https://github.com.proxy socks5://127.0.0.1:10808
这里的10808是在v2ray上可以看到的
详细的参考这篇文章:设置代理解决github被墙 - 知乎
如何理解代理?待办
git log 日志,可以查看本地的各种操作
总结:通过种种操作,已经可以实现“云存档”功能,但是远远不够,现在我要寻找一个范例来跟踪学习。
参考视频:
这个教程里也很好地讲解了如何安装适配自己显卡版本的pytorch
出现了如 nvidia -smi 这样的好代码
看了一些,发现与我的方向不够契合,因此选择用下面的视频教程
10. conda环境常见指令 如何导出requirements 如何删去环境
conda list -e > requirements.txt
conda env list
conda info –envs
conda create -n 新环境名 python=3.8
deactivate
conda remove -n xxxxx(名字) --all
9. 帮我在qtdesigner里设置一个qframe的样式表,使得其有卡片一样的质感
8. property() 函数及 @property 装饰器的使用
见14
7. PyQt5已安装提示No module named ‘PyQt5.QtChart‘
Qtchart是单独的包,需要用pip单独安装。
具体命令为:
pip install pyqtchart
6.文件路径获取
用尽可能短的代码实现对我的目录dir下第一个文件绝对路径的获取
import os
dir = r'../data/mask'
files = [f for f in os.listdir(dir) if os.path.isfile(os.path.join(dir, f))]
if files:
mask_nrrd_path1 = os.path.abspath(os.path.join(dir, files[0]))
print(mask_nrrd_path1)
else:
print("No files found in the directory.")
5.5 自动化python打包程序(lose)
从一个项目入手,尝试一下,这样未来可以直接使用这样的方法来构建我的应用程序,大大省力。
先大致规划一下,主要分为几个步骤:
1. 备份我的代码,以免操作时出现失误,损失惨重
- 2. 下载并完成pyinstaller的部署
- 3. 根据教程完成打包
- 4. 出现问题先bing,再通义,再copilot
- 5. 完成打包,在其他电脑上测试
- 6. 解决测试的问题,解决思路同上
- 7. 总结
计划时间: 120min
开始!
进入官网
在这里通过pip install auto-py-to-exe 安装
通过 auto-py-to-exe 启动
成功打开这个软件,切换语言
不太理解里面几个参数怎么用,找到一个更好的介绍网站

设置导入各个文件和文件夹,点击最下方按钮
PyInstaller.isolated._parent.SubprocessDiedError: Child process died calling _is_package() with args=('skimage.io._plugins',) and kwargs={}. Its exit code was 3228369022.
Project output will not be moved to output folder
Complete.
完成后没有顺利导出
Ai告诉我是因为skimage不兼容
此外我也注意到中间TensorFlow导入时出错了
考虑使用cx_Freeze包来进行打包
根据ai的教程完成setup的配置,出现问题
RecursionError: maximum recursion depth exceeded 通常意味着在导入模块时发生了无限递归。这可能是由于 cx_Freeze 在处理某些模块或钩子时遇到了问题,导致它不断地尝试导入相同的模块。
推测是因为其中相互调用太多了,导致出现了死循环,看来还是要从单个文件练手开始,同时注意其中的引用格式
现在纠结一下是不是要继续折腾……
5.一个打包py文件的实例(lose)
为了使用`PyInstaller`将你的项目打包,你需要确保`PyInstaller`能够识别并包含你的所有必需文件和库。下面是一个基于你提供的文件结构的打包命令示例:
假设你的目录结构如下:
```
D:\Code\Python\TZB2024\ui
├── __pycache__
├── data
├── dll
├── main.py
└── VER1.ui
```
你想要将打包后的文件放到 `D:\Code\Python\TZB2024` 目录下。
### 第一步:编写.spec文件
首先,你可能需要创建一个`.spec`文件,这将告诉`PyInstaller`如何构建你的应用。打开文本编辑器,创建一个新的文件,并将其命名为 `main.spec`(或者任何你喜欢的名字)。将以下内容粘贴到该文件中:
这个`.spec`文件包含了以下信息:
- `Analysis` 部分指定了主要的Python脚本 (`main.py`) 和其所在目录。
- `binaries` 参数用来指定`dll`文件夹的位置和它应该被包含的方式。
- `datas` 参数用来指定`data`文件夹和UI文件的位置以及它们应该被包含的方式。
- `EXE` 部分定义了最终的可执行文件的属性,包括它的名字 (`name='TZB2024'`) 和是否使用控制台 (`console=False`)。
### 第二步:运行PyInstaller
在你的命令行工具中,导航至包含`main.spec`文件的目录,然后运行以下命令:
```bash
pyinstaller D:\Code\Python\TZB2024\ui\main.spec
```
这将会使用你刚刚创建的`.spec`文件来构建你的应用。默认情况下,`PyInstaller`会在`D:\Code\Python\TZB2024\ui\dist`目录下生成可执行文件。要改变输出目录,你可以在.spec文件中修改`distpath`参数,或者使用命令行参数`--distpath`。
### 第三步:移动输出文件
打包完成后,你可以手动将`dist`目录下的文件移动到`D:\Code\Python\TZB2024`目录下,或者通过脚本自动化这个过程。
Auto,但还没试过
4 python中文件路径的写法
注意区分 / 与 \
其中 / 是正斜杠,在Linux与macOS里用,而反斜杠 \ 则更多用于windows系统
3 网站开发记录 8.3
使用Notion的尝试:
获得一个模板,share从而得到网址:https://knotty-equinox-49a.notion.site/fa88ffa6f02e4dd09bd9cb7bbef97960?v=17fa249218b049148b2fc624457dab42&pvs=4
页面ID fa88ffa6f02e4dd09bd9cb7bbef97960
通过eu.org获取自己的免费域名,使用了一个生成的英国用户信息
在Vercel进行配置
完成配置后,总的来说,使用三个网站进行综合管理:
Notion进行内容的管理,Git上的代码对底层逻辑进行修改(类似JavaScript的作用),Vercel对域名和网站的流量、历史版本等进行管理
(还有腾讯云用于托管域名,背后的玄机暂未理解)
最后的方案是用cloudfare加nameiso两个解决的,第一年一共花了7块钱
有时间再写吧
2 ui开发中的记录 8.3
我的文件读取实现是通过在qtdesigner里放置一个叫做fileup_1的pushbutton,然后点击后可以打开一个窗口,上传文件至与代码同一目录下的data\1文件夹内,并在一个叫做list的QlistWidget中显示文件名
同理我的fileup_2的pushbutton,然后点击后可以打开一个窗口,上传文件至与代码同一目录下的data\2文件夹内,并在一个叫做list_1的QlistWidget中显示文件名
对几个widget进行排版
学到一个核心技术,不必先建一个frame,可以直接对两个部件进行排版,大大简化过程,也避免了很多bug
设置stackwidget的布局
卡在了布局的一个神秘bug上,我的page1可以顺利设置布局,但是page2等其他page却不行,好奇怪!
###一个实用的经验,在中心界面右键widget忽然就可以设置layout了
开一个坑:openGL似乎可以实时显示点云!有时间看看怎么用
在我的main代码里调用我同一父目录下的dll\pic_generate.py文件,在我的界面中我只要点击我的fileup_1这个pushbutton就可以调用这个文件
现在我要联系我的pic1这个QGraphicsView和horizontalSlider_2这个Qslider,使得我拖动slider时,pic1里显示的图片能够依次切换,我的pic1里的图片全都来自于dir_pic1这个目录
我的文件格式如下,所有文件都在D:\Code\Python\TZB2024\ui这个目录下,里面有__pycache__,data,dll,这三个文件夹和main.py、VER1.ui这两个文件,其中data里面用于放置各种程序运行中产生的数据,dll里有各种需要调用的库
请帮我写一个完整的打包代码,把打包后的文件放在D:\Code\Python\TZB2024目录下
下面是我的一个函数库,我要在main函数里调用里面的read_dcm和save_as_folder这2个函数来对我上传的dcm文件进行处理,并将图像保存到我的show/rawdata里面
把分割代码的数据转成了cpu
那个分割模型,我先是转到cpu计算避免用户显卡驱动和cuda版本不对应,然后简单优化,但是现在单独能跑,在程序里调用跑不动,我在de这个bug
我在使用qtdesiner和下面的main代码来制作我的ui,要在ui里点击view3d这个Qpushbutton调用我的dll. 3d_view这个代码
作为背景,一个非常漂亮的Qwidget的背景的样式表,要求主色调为浅蓝色
我用下面的代码调用我的ui文件,却出现了AttributeError: type object 'Qt' has no attribute 'QFrame::Shape::NoFrame'的报错
使用qtdesiner和下面的main代码来制作我的ui,添加功能:
点击divide_pic1后,不仅调用分割函数,还可以将函数生成的nrrd文件利用利用我的read_nrrd来读取,再使用save_as_folder来对其进行图像的生成和保存(保存至.\data\show\slicepic里)
右边的代码,直接运行没问题,但是在其他文件里调用其中的函数,会显示FileNotFoundError: [Errno 2] No such file or directory: 'MGUNet1.pt'
——应该是工作路径变化了,无法识别
Python里,我在代码A中通过import dll.B来调用B里面的函数,但是B里面又通过import utils.C来调用C代码里的函数,运行A时工作目录是A代码的目录,可以读取到B,但是无法在B中继续读取C
###解决:哪个文件运行就是在那个文件的目录下找文件,运行 A的时候,把C中的import以A为参考系来导入
此外,init可能也很有用?
模仿里面的change_picture1写一个change_picture3,把horizontalSlider_5和slicepic1_b这个graphicsview联系到一起,需要在哪些地方添加哪些代码
在__init__方法中添加对horizontalSlider_4和slicepic1_a的引用。
添加一个新的方法change_picture4来处理滑块改变时的行为。
将horizontalSlider_4的valueChanged信号连接到change_picture4方法。
做到滑动一个slicer就能同步控制两个graphicsview改变图像
如何让正在运行的代码,在我的UI中显示进度条
我在使用qtdesiner和下面的main代码来制作我的ui,我要添加功能:实现点击part3button就能调用我的process_dicom_files(dicom_directory, output_directory)函数
我的output_directory = "./data/show/yingbianpic"中的3张图片,能分别在yb1,yb2,yb3这3个graphicsview中呈现
似乎遇到了多线程运行的问题,或是某个函数反复运行
###应该在每个函数后边加一个中断信号的代码
self.XXbutton.clicked.disconnect()
将这里边print的内容输入additem到我的list_widget_2里
测试一下
将这个代码整体的调用进行封装,传入必要的参数
我的代码classit(config)计算需要一段时间,我该如何用进度条来展示我现在的进度,必须要修改我的classit的写法吗?
self.progressbarC.setValue(88)解决问题
主窗口的大小设置
应该对其中的centralwidget进行操作,才能完成窗口大小的调整,理解一下便是主窗口是在适应唯一一个widget的大小
无边框设置
关于一个layout里的布局使用方法
###点击layout,里面会有layoutstrech这个值,如果是两个控件在里面就是a,b,有三个就是a,b,c,通过这个来调整比例,值得注意的是要先将空间设置为prefer的策略
如何在我的qtdesigner里给我的ui加一个图标
添加资源
现在我是动态读取的ui文件,我在qtdesigner里设置了对应的icon,—pyqt5 动态读取ui文件的时候识别不了我的qrc资源
###只需要先转qrc为py文件,再import进去即可,设置相关的在ui文件里包含了,from img import *
对于我的下面的函数,这个函数在点击divide_pic1这个button后会开始被调用进行分割计算,现在我要在pyqt5中利用QprogressBar来实现进度的实时呈现,修改函数和主代码
写一个韩式def save_as_folder(image, base_dir, cmap='gray', choose_axis=['Axial', 'Coronal', 'Sagittal'], save_every_nth=100):实现读取base_dir
点击我的PART1这个button后,设置我的button1,button2的样式表中的 background-color变成qlineargradient(x1: 0, y1: 0, x2: 1, y2: 1, stop: 0 #5C67F0, stop: 1 #9FA8DA); border变成 1px solid #4A54E1;
请问我connect的on_PART1_clicked应该怎么改
神秘bug,修改了connect还是可以运行对应的函数
写一个函数,在我的ui中点击detail这个button后,可以打开我的“field_dir=r'../data/result/field' 读取里面的第一个csv,def on_detail_clicked(self):
现在点击detail_2打开.\data\show\partC\strain里的第一个文件
一些血的教训
1.队友一定要教会他们如何做接口
2.对于各个功能的实现需要知道预期的时间,但是没有过经验又确实不知道要做多久,本质还是矛盾的
3.对于对方给的每一个函数,不要太自信自己去修改,应该让对面改到合适才行
1.库安装,使用清华源 8.3
前言
在这里开个坑。
这是一件想做了很久的事,也有过一些已经被忘记的深思熟虑:起因是在写一个有一定规模的项目时遇到的困境,那就是GPT很难理解我们的整个项目,难以构建起多个代码与文件之间的串联。在多次的使用中能很明显地发现它的适用场景还是偏向一些独立的小功能上,可以简单提升Code效率。简而言之,是一个很好的小工具,但不适合长期使用。
再者便是看到身边的同学,一种源自peer pressure的动力。在GPT的帮助下,越来越多的人开始使用机器学习、深度学习等来丰富自己的课题,这也确实带来了一些焦虑——自己的技术壁垒是否构筑起来了?
因此这里就显得很有必要,我需要这样一个地方来安置我的各种所学,像背英语单词一样,在使用中渐渐记住各种用法,各种常见的bug,从而在下一次能快速反应过来,如是,方将技能内化为自己的一部分,而不是浮于表面。
用txt可以尽可能降低这个记录对于内存的负荷,降低的记录门槛
一个好的格式应当可以事半功倍,方便检索