[{"content":" 声明 这篇文章是由cc + glm 辅助生成的 前置要求 服务器已安装Docker和Docker Compose 具备基本的Linux命令操作能力 拥有一个邮箱账户用于邮件服务配置 镜像下载 Overleaf主镜像 推荐使用增强版Overleaf镜像，包含了完整的TeX Live环境：\n1 2 # 国内用户可使用镜像加速 docker pull docker.1ms.run/tuetenk0pp/sharelatex-full 增强功能包括：\n完整的TeX Live安装及所有可用包 支持minted代码高亮 支持SVG图片（集成Inkscape） 支持Lilypond音乐排版 默认启用shell-escape 数据库镜像下载 MongoDB配置 1 2 3 4 5 6 # 下载MongoDB 6.0 docker pull docker.1ms.run/library/mongo:6.0 # 重命名镜像 docker tag docker.1ms.run/library/mongo:6.0 mongo:6.0 docker rmi docker.1ms.run/library/mongo:6.0 Redis配置 1 2 3 4 5 6 # 下载Redis 6.2 docker pull docker.1ms.run/library/redis:6.2 # 重命名镜像 docker tag docker.1ms.run/library/redis:6.2 redis:6.2 docker rmi docker.1ms.run/library/redis:6.2 项目配置 下载部署工具 1 2 git clone https://github.com/overleaf/toolkit.git overleaf-toolkit cd overleaf-toolkit 生成配置文件 1 bin/init 替换镜像 编辑overleaf-toolkit/lib/docker-compose.base.yml, 注意，这个镜像为刚才下载的那个overleaf主镜像，如果你是使用docker.1ms.run下载的，image改为docker.1ms.run/tuetenk0pp/sharelatex-full\n1 image: \u0026#34;${IMAGE}\u0026#34; --\u0026gt; image: tuetenk0pp/sharelatex-full 基础配置文件编辑 编辑 config/overleaf.rc：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # 修改监听地址 OVERLEAF_LISTEN_IP=127.0.0.1 --\u0026gt; OVERLEAF_LISTEN_IP=0.0.0.0 # 设置容器映射的端口 OVERLEAF_PORT:80 OVERLEAF_PORT=8108 # 注释掉Nginx # TLS proxy configuration (optional) # See documentation in doc/tls-proxy.md NGINX_ENABLED=false # NGINX_CONFIG_PATH=config/nginx/nginx.conf # NGINX_HTTP_PORT=80 # Replace these IP addresses with the external IP address of your host # NGINX_HTTP_LISTEN_IP=127.0.1.1 # NGINX_TLS_LISTEN_IP=127.0.1.1 # TLS_PRIVATE_KEY_PATH=config/nginx/certs/overleaf_key.pem # TLS_CERTIFICATE_PATH=config/nginx/certs/overleaf_certificate.pem # TLS_PORT=443 环境变量配置 编辑 config/variables.env：\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 # 实例基本信息 OVERLEAF_APP_NAME=My Overleaf Instance OVERLEAF_SITE_URL=http://your-server-ip:port OVERLEAF_NAV_TITLE=My Overleaf # 管理员邮箱配置 OVERLEAF_ADMIN_EMAIL=admin@yourdomain.com OVERLEAF_EMAIL_FROM_ADDRESS=noreply@yourdomain.com # SMTP邮件服务配置（以163邮箱为例） OVERLEAF_EMAIL_SMTP_HOST=smtp.163.com OVERLEAF_EMAIL_SMTP_PORT=465 OVERLEAF_EMAIL_SMTP_SECURE=true OVERLEAF_EMAIL_SMTP_NAME=Overleaf OVERLEAF_EMAIL_SMTP_USER=your-email@163.com OVERLEAF_EMAIL_SMTP_PASS=your-smtp-password # 页脚自定义 OVERLEAF_LEFT_FOOTER=\u0026#39;[{\u0026#34;text\u0026#34;: \u0026#34;Contact Support\u0026#34;, \u0026#34;url\u0026#34;: \u0026#34;mailto:support@yourdomain.com\u0026#34;}]\u0026#39; OVERLEAF_RIGHT_FOOTER=\u0026#39;[{\u0026#34;text\u0026#34;: \u0026#34;© 2025 Your Company\u0026#34;}]\u0026#39; # TLS配置（重要：无证书时必须配置，否则邮件发不出） OVERLEAF_EMAIL_SMTP_TLS_REJECT_UNAUTH=false OVERLEAF_EMAIL_SMTP_IGNORE_TLS=true 部署步骤 初始化配置 1 2 3 4 # 启动所有服务 bin/up # 可以后台启动 bin/up -d 验证部署 访问 http://your-server-ip:port，应该能看到Overleaf登录页面。\n创建管理员账户 访问http://your-server-ip:port/launchpad，进行管理员账户注册\n或者, 进入容器内设置\n1 2 3 docker exec -it sharelatex /bin/bash cd /overleaf/services/web grunt user:create-admin --email=admin@example.com 升级成员为管理员 直接操作MongoDB数据库\ndocker exec -it mongo mongosh 切换数据库， use sharelatex 查找所有用户，db.users.find({}, {email:1, isAdmin:1}) 将目标用户设置为管理员，db.users.updateOne({email: \u0026ldquo;you@example.com\u0026rdquo;}, {$set: {isAdmin: true}}) 退出，exit 参考资源 Overleaf官方文档 增强版镜像项目 部署工具项目 ","date":"2025-10-11T16:19:36+08:00","image":"https://blog-wine-six-14.vercel.app/p/overleaf%E8%87%AA%E9%83%A8%E7%BD%B2/images/cover_hu_14a65048271cfe12.webp","permalink":"https://blog-wine-six-14.vercel.app/p/overleaf%E8%87%AA%E9%83%A8%E7%BD%B2/","title":"overleaf自部署"},{"content":" 声明 这篇文章是由cc + glm 辅助生成的 Claude Code简介 Claude Code是Anthropic推出的AI编程助手，它不仅仅是一个简单的代码生成工具，更是一个能够理解项目结构、分析代码逻辑、提供优化建议的智能编程伙伴。\n安装 需要有node环境\n1 npm install -g @anthropic-ai/claude-code 集成glm 修改 ~/.claude/settings.json，如果不存在就创建一个。 1 2 3 4 5 6 7 8 9 { \u0026#34;env\u0026#34;: { \u0026#34;ANTHROPIC_DEFAULT_HAIKU_MODEL\u0026#34;: \u0026#34;glm-4.5-air\u0026#34;, \u0026#34;ANTHROPIC_DEFAULT_SONNET_MODEL\u0026#34;: \u0026#34;glm-4.6\u0026#34;, \u0026#34;ANTHROPIC_DEFAULT_OPUS_MODEL\u0026#34;: \u0026#34;glm-4.6\u0026#34;, \u0026#34;ANTHROPIC_BASE_URL\u0026#34;: \u0026#34;https://open.bigmodel.cn/api/anthropic\u0026#34;, \u0026#34;ANTHROPIC_AUTH_TOKEN\u0026#34;: \u0026#34;your_zhipu_api_key\u0026#34; } } 获取APi key，API KEY, 新用户有一些体验的token资源包赠送喔！ GLM-4.6 GLM-4.6是智谱AI最新发布的语言模型，在Claude Code中作为后端支持时，展现出了令人印象深刻的编程能力。\nVSCode集成体验 安装和配置 在VSCode中使用Claude Code非常简单，只需要安装相应的扩展插件即可。\n配置步骤： 打开VSCode扩展市场 搜索\u0026quot;Claude Code for VS Code\u0026quot; 点击安装并重启VSCode Terminal中使用 除了GUI界面的VSCode插件，Claude Code在Terminal中也有着出色的表现。\n常用命令和技巧 1. 项目分析 1 2 3 4 5 6 7 8 # 分析项目结构 claude analyze . --recursive # 检查代码质量 claude quality-check --language javascript # 生成项目文档 claude docs --format markdown 2. 批量操作 1 2 3 4 5 6 7 8 # 批量重构文件 claude refactor --pattern \u0026#34;*.js\u0026#34; --rule \u0026#34;use-const-let\u0026#34; # 代码格式化 claude format --language typescript --prettier # 依赖更新建议 claude update-check --dependencies 相关链接：\nClaude Code官方文档 GLM模型介绍 ","date":"2025-10-11T11:32:39+08:00","image":"https://blog-wine-six-14.vercel.app/p/claude-code--glm-4.6-%E4%BD%BF%E7%94%A8%E4%BD%93%E9%AA%8C/images/cover_hu_3404c1c550a1e892.webp","permalink":"https://blog-wine-six-14.vercel.app/p/claude-code--glm-4.6-%E4%BD%BF%E7%94%A8%E4%BD%93%E9%AA%8C/","title":"Claude Code + GLM-4.6 使用体验"},{"content":"1、问题背景 GitLab Runner 跑在一个容器里\n用 shell 执行器\n容器里shell执行器运行 docker compose 来启动服务\n依赖 宿主机 Docker（docker:dind） 去创建业务容器\n在启动服务时，docker compose 涉及文件挂载。相关文件最初由宿主机挂载到 Runner 容器中，然后在 docker-compose.yml 中再次挂载到业务容器。\n在宿主机直接执行 docker compose 启动服务一切正常，但在 Runner 容器中执行时，就会报以下错误。\n2、报错 1 Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: error during container init: error mounting \u0026#34;/home/xxx/client/conf/nginx.conf\u0026#34; to rootfs at \u0026#34;/etc/nginx/nginx.conf\u0026#34;: create mountpoint for /etc/nginx/nginx.conf mount: cannot create subdirectories in \u0026#34;/var/lib/docker/overlay2/be07c226551b939ab5c47865c441c289bba7f26e7a449ef8610f5399e7ec2fda/merged/etc/nginx/nginx.conf\u0026#34;: not a directory: unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type 3、chatgpt给的方案 方案 1：路径一致化 确保 Runner 容器挂载的路径 和 宿主机路径 完全一致。\n比如宿主机上有：\n1 /srv/ci-data/nginx.conf 启动 Runner 容器时：\n1 docker run -v /srv/ci-data:/srv/ci-data gitlab-runner 那么 docker-compose.yml 里用：\n1 2 volumes: - /srv/ci-data/nginx.conf:/etc/nginx/nginx.conf:ro 这样 Docker daemon 解析路径时就能找到正确的文件。\n方案 2：把文件做成 Volume 不要直接 bind-mount 宿主机路径，而是：\n1 2 docker volume create nginx_conf docker run -v nginx_conf:/etc/nginx ... 这样路径类型和内容不会依赖宿主机真实文件结构，避免类型冲突。但缺点是调试不如 bind mount 方便。\n4、解决 通过使用方案1成功解决了如上问题。\n另外一个小办法 在docker-compose.yml中先不挂载 docker compose起了服务后，通过命令拷贝到对应的业务容器，然后重启业务 示例 原先的挂载\n1 2 3 4 volumes: - \u0026#34;$PWD/conf/nginx.conf:/etc/nginx/nginx.conf\u0026#34; - \u0026#34;$PWD/conf/xxx.pem:/etc/nginx/xxx.pem\u0026#34; - \u0026#34;$PWD/conf/xxx.key:/etc/nginx/xxx.key\u0026#34; 删除这部分挂载，直接docker compose启动，然后拷贝\n1 2 3 4 docker cp ./conf/nginx.conf \u0026lt;container_name\u0026gt;:/etc/nginx/nginx.conf docker cp ./conf/xxx.pem \u0026lt;container_name\u0026gt;:/etc/nginx/xxx.pem docker cp ./conf/xxx.key \u0026lt;container_name\u0026gt;:/etc/nginx/xxx.key docker exec \u0026lt;container_name\u0026gt; nginx -s reload ","date":"2025-08-09T15:38:37+08:00","image":"https://blog-wine-six-14.vercel.app/p/gitlab-runner-%E4%BB%A5-docker-%E5%AE%B9%E5%99%A8%E6%96%B9%E5%BC%8F%E9%83%A8%E7%BD%B2/cover_hu_c0303be794687876.webp","permalink":"https://blog-wine-six-14.vercel.app/p/gitlab-runner-%E4%BB%A5-docker-%E5%AE%B9%E5%99%A8%E6%96%B9%E5%BC%8F%E9%83%A8%E7%BD%B2/","title":"GitLab Runner 以 Docker 容器方式部署"},{"content":" HF简介 DeepSeek： Hugging Face 堪称 AI 界的「模型超市」——就像 GitHub 托管代码一样，它汇聚了全球开发者训练的机器学习模型（从聊天机器人到图像生成器），并提供开箱即用的工具链。只需几行代码，你就能调用 ChatGPT 同款技术栈，或像逛应用商店一样下载现成模型，把「造火箭」变成「拼乐高」。 Transformers安装 DeepSeek总结 Transformers 和 Hugging Face 的关系\n一句话总结：\nTransformers 是 Hugging Face 生态的核心库，相当于 GitHub 的 Git——它是 HF 技术栈的底层引擎，而 Hugging Face 平台（如 Model Hub）则像 GitHub 网站一样提供模型托管、社区协作等完整生态。\n关键关联点：\n库（Transformers）⇨ 平台（HF）\nTransformers 库：提供代码工具（如 pipeline()）来加载和运行模型 Hugging Face 平台：提供模型托管（Model Hub）、数据集（Datasets）、推理API（Inference API）等配套服务 模型共享生态\n通过 transformers 库的 from_pretrained() 方法，可直接加载 Hugging Face Hub 上的 30万+开源模型（如 model=\u0026quot;meta-llama/Llama-2-7b\u0026quot;） 协同工作流\n1 2 3 # 用transformers库调用HF平台上的模型 from transformers import AutoModel model = AutoModel.from_pretrained(\u0026#34;bert-base-uncased\u0026#34;) # 自动从HF Hub下载 类比：\n就像 Git（工具） + GitHub（平台）的组合，Transformers 是技术基础，Hugging Face 是扩展生态的「模型社区」。\n安装的前置条件 Python版本需要大于等于3.8（之前用3.6的安装失败了，报了这个错）\n创建新的虚拟环境时，报HTTP错误，404\n1 2 3 4 5 An HTTP error occurred when trying to retrieve this URL. HTTP errors are often intermittent, and a simple retry will get you on your way. CondaError: CondaHTTPError: HTTP 404 NOT FOUND for url \u0026lt;https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/win-64/xxxxxx\u0026gt; Elapsed: 00:00.635947 解决方案\n参考文章： https://blog.csdn.net/qq_44833403/article/details/144535945\n在C盘\\用户\u0026lt;用户名\u0026gt;文件夹下 找到.condarc文件（注意是文件，不是文件夹，因为本人电脑文件排序原因，文件夹整体排前面，看字母序去找一直没找到🤣），整体替换为 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 channels: - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/ - https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/ - http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/ - http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/ default_channels: - http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main - http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r - http://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2 custom_channels: conda-forge: http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud msys2: http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud bioconda: http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud menpo: http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud pytorch: http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud pytorch-lts: http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud simpleitk: http://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud show_channel_urls: true offline: false ssl_verify: false python版本需要和setuptools版本匹配，python 3.9版本可以搭配63.4.1版本的setuptools,执行下面命令即可 1 conda create -n env python=3.9 setuptools==63.4.1 电脑需要有rust的环境，rustc的版本需要有一定要求，之前版本1.71.0失败了，目前好像是最低要1.74以上,通过以下代码更新\n1 2 3 4 rustup --version # 查看是否安装了rustup，没有需要安装 rustup self update # 更新rustup rustup update stable # 更新rust版本 rustc --version # 查看更新后的rustc版本 安装transformers 通过下面命令即可安装\n1 pip install transformers Transformers使用 环境变量设置 Hugging Face的默认的cache地址为C:\\ 用户 \\ 用户名 \\ .cache \\ huggingface,假如需要放置到其他位置，可添加一个环境变量\n变量名： HF_HOME 变量值： D:\\.cache\\huggingface(这里我是放到D盘下，之后模型会自动缓存在这里) 使用pipeline 下面通过img2txt的模型演示一下使用\n1 2 3 4 5 6 7 8 9 10 11 12 13 from transformers import pipeline def img2text(image_path): # 加载图像描述模型 img_to_txt = pipeline(\u0026#34;image-to-text\u0026#34;, model=\u0026#34;Salesforce/blip-image-captioning-base\u0026#34;) # 使用模型生成图片描述 captions = img_to_txt(image_path) # 输出结果 print(captions) return captions[0][\u0026#39;generated_text\u0026#39;] 使用openrouter openrouter简介 OpenRouter 的核心功能是提供 单一 API 接口，让开发者无需分别对接不同厂商的 AI 模型（如 GPT-4、Claude、Llama 等），即可通过一次集成调用多种模型。 这里主要是练习一下使用openrouter，通过调用其api完成一些有趣的任务。目前可以免费调用DeepSeek: DeepSeek V3 0324 (free)。下面将演示调用免费的deepseek模型基于一段图片描述生成一首中文诗歌。\n依赖包 首先需要安装下面的依赖包\n1 pip install langchain langchain-community langchain-openai 调用模型 获取api key\n点击后面链接在openrouter中创建一个key， https://openrouter.ai/deepseek/deepseek-chat-v3-0324:free/api\n通过key调用模型\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 from langchain_openai import ChatOpenAI from langchain.prompts import ChatPromptTemplate def generate_poem(scenario): system_prompt = \u0026#34;\u0026#34;\u0026#34; 你是一个作诗非常好的诗人，接下来你要根据一段英文描述的场景生成一首中文现代诗。 1.希望你能用优美的语言描绘出这个场景 2.诗的内容要有意境 3.字数在100个字以内。\u0026#34;\u0026#34;\u0026#34; prompt_template = ChatPromptTemplate.from_messages([ (\u0026#34;system\u0026#34;, system_prompt), # 系统级提示 (\u0026#34;human\u0026#34;, \u0026#34;{scenario}\u0026#34;) # 用户输入 ]) # 初始化模型 chat_llm = ChatOpenAI( openai_api_base=\u0026#34;https://openrouter.ai/api/v1\u0026#34;, # 统一都是调这个api url openai_api_key=\u0026#34;你创建的key\u0026#34;, model=\u0026#34;deepseek/deepseek-chat-v3-0324:free\u0026#34;, # 指定模型名称 temperature=0.7 ) print(\u0026#34;正在生成诗歌...\u0026#34;) # 3. 创建 LLMChain,并运行 chain = prompt_template | chat_llm # 通过管道输入到llm模型中 result = chain.invoke({\u0026#34;scenario\u0026#34;: scenario}) print(result.content) return result 效果展示 用 HuggingFace 模型提取图片描述，再调用 LLM 生成诗歌，就能让图片‘开口吟诗’啦！🤪！\n1 2 txt = img2text(image_path=\u0026#34;img2poem\\image.jpg\u0026#34;) # 使用img2poem文件夹下的图片生成诗歌 generate_poem(txt) 运行结果展示\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 Device set to use cpu [{\u0026#39;generated_text\u0026#39;: \u0026#39;a cartoon character running in the grass\u0026#39;}] 正在生成诗歌... 《草上飞》 绿浪里跃动的光点， 是风追不上的弧线。 大地在脚下柔软， 天空在头顶旋转。 橡皮鞋底沾满春天， 笑声把阳光压弯。 地平线张开双臂， 接住这失控的欢颜。 ","date":"2025-04-06T19:37:30+08:00","image":"https://blog-wine-six-14.vercel.app/p/hf%E4%BD%BF%E7%94%A8%E4%BD%93%E9%AA%8C/cover_hu_cbfe7c3fada71274.webp","permalink":"https://blog-wine-six-14.vercel.app/p/hf%E4%BD%BF%E7%94%A8%E4%BD%93%E9%AA%8C/","title":"HF使用体验"},{"content":" 提示 本篇文章持续更新中，以后对于博客的改动都将记录在此文章中 性能篇 随着不断的修改博客，添加的东西也越来越多，博客的访问速度也逐渐减慢。尤其是增加字体后，因为中文的字体文件十分巨大，导致加载一个字体文件都要3-4秒。遂进行性能优化。\n1.字体文件的精简 由于中文字体文件很大，把所有字体加载过来是一个耗时的操作，并且很多字体我们其实并没有用到，所以可以考虑只加载我们网站所用的字符部分。font-spider就是做这么一件事的工具。\nhttps://github.com/aui/font-spider\n安装font-spider 首先你需要有node环境，并且有npm包管理\n然后全局安装 1 npm i font-spider -g 使用 具体使用可以参考github仓库官方文档给的示例\nHugo博客的便捷使用 因为官方示例是基础的使用，hugo博客怎么更便捷的使用是接下来要讨论的问题。\n下面是适用于hugo博客使用font-spider的一些自动化脚本。主要原理：\n通过hugo命令在public目录下生成所有网页的html文件 通过python脚本读取所有的html页面的所有字符，并写到根目录下index.html文件的content div中 再通过font-spider 命令找出网站中所使用到的字符，font-spider生成的字体文件会在font/目录下。这个文件是精简过后的文件 小工具的目录结构\n其中index.html的内容如下，jiangxizhuokai是本站使用的字体，在使用时请改成自己对应的，且将字体文件下载到本地放置在fonts目录下 1 2 3 4 5 6 7 8 9 10 11 12 13 \u0026lt;div class=\u0026#34;content\u0026#34;\u0026gt;\t\u0026lt;/div\u0026gt; \u0026lt;style\u0026gt; @font-face { font-family: \u0026#39;jiangxizhuokai\u0026#39;; src: url(\u0026#39;fonts/jiangxizhuokai.ttf\u0026#39;); font-weight: normal; font-style: normal; } .content{ font-family: \u0026#39;jiangxizhuokai\u0026#39;; } \u0026lt;/style\u0026gt; 字体文件的font-face在themes\\hugo-theme-stack-master\\assets\\scss\\partials\\base.scss中定义\nscript.py内容如下，需要安装beautifulsoup4这个库，这个文件就是把所有网页的html里面的字符写到上面的index.html的脚本。其中在运行完后char.txt中会存放当前网站所用到的所有字符，并在下次运行的时候进行比较，当字符集没变的时候，会打印出No new characters found, no update needed.这句话。（记得在main中更改网站生成的public路径） 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 import os from bs4 import BeautifulSoup def extract_text_from_html(file_path): \u0026#34;\u0026#34;\u0026#34;Extract all unique characters from an HTML file.\u0026#34;\u0026#34;\u0026#34; char_set = set() try: with open(file_path, \u0026#39;r\u0026#39;, encoding=\u0026#39;utf-8\u0026#39;) as file: content = file.read() for char in content: char_set.add(char) return \u0026#39;\u0026#39;.join(sorted(char_set)) except Exception as e: print(f\u0026#34;Error reading {file_path}: {e}\u0026#34;) return \u0026#34;\u0026#34; def collect_html_files(directory): \u0026#34;\u0026#34;\u0026#34;Recursively collect all HTML files in a directory.\u0026#34;\u0026#34;\u0026#34; html_files = [] for root, _, files in os.walk(directory): for file in files: if file.endswith(\u0026#39;.html\u0026#39;): html_files.append(os.path.join(root, file)) print(f\u0026#34;Found HTML files: {html_files}\u0026#34;) # Debugging output return html_files def main(input_directory, index_html_file, chars_file): \u0026#34;\u0026#34;\u0026#34;Main function to collect text from HTML files and write to a div in an HTML file.\u0026#34;\u0026#34;\u0026#34; html_files = collect_html_files(input_directory) new_chars_set = set() for html_file in html_files: text = extract_text_from_html(html_file) if text: new_chars_set.update(text) new_chars = \u0026#39;\u0026#39;.join(sorted(new_chars_set)) try: # Read the existing character set from the file if os.path.exists(chars_file): with open(chars_file, \u0026#39;r\u0026#39;, encoding=\u0026#39;utf-8\u0026#39;) as file: old_chars = file.read() else: old_chars = \u0026#39;\u0026#39; # Check if the character set has changed if new_chars != old_chars: # Update the character set file with open(chars_file, \u0026#39;w\u0026#39;, encoding=\u0026#39;utf-8\u0026#39;) as file: file.write(new_chars) # Update the target HTML file with open(index_html_file, \u0026#39;r\u0026#39;, encoding=\u0026#39;utf-8\u0026#39;) as file: soup = BeautifulSoup(file, \u0026#39;html.parser\u0026#39;) content_div = soup.find(\u0026#39;div\u0026#39;, class_=\u0026#39;content\u0026#39;) if content_div: content_div.clear() # Clear the existing content content_div.append(new_chars) with open(index_html_file, \u0026#39;w\u0026#39;, encoding=\u0026#39;utf-8\u0026#39;) as file: file.write(str(soup)) print(f\u0026#34;Updated {index_html_file} with new characters.\u0026#34;) else: print(\u0026#34;No new characters found, no update needed.\u0026#34;) except Exception as e: print(f\u0026#34;Error updating {index_html_file}: {e}\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: input_directory = \u0026#34;D:/Hugo/project/blog/public\u0026#34; # Replace with your directory index_html_file = \u0026#34;./index.html\u0026#34; chars_file = \u0026#34;./chars.txt\u0026#34; main(input_directory, index_html_file, chars_file) 总结一下，上面需要做的步骤就是创建index.html和script.py文件，然后创建fonts文件夹并在其中放置字体文件。最后修改前面两个文件中相关的内容，运行script脚本后运行font-spider命令。\n1 font-spider .\\index.html 精简后的字体文件便在fonts目录下，并且会有一个.font-spider文件夹，这个文件夹是原始字体文件的备份。\n2.CDN的使用 本站部分资源使用了免费的CDN方案：jsDelivr+Github。\n参考链接： https://zhuanlan.zhihu.com/p/76951130\nCDN的全称是Content Delivery Network，即内容分发网络。CDN是构建在网络之上的内容分发网络，依靠部署在各地的边缘服务器，通过中心平台的负载均衡、内容分发、调度等功能模块，使用户就近获取所需内容，降低网络拥塞，提高用户访问响应速度和命中率。CDN的关键技术主要有内容存储和分发技术。——百度百科\n知乎. \u0026ldquo;免费CDN：jsDelivr+Github 使用方法\u0026rdquo; 知乎专栏, 2019, https://zhuanlan.zhihu.com/p/76951130.\n3.优化结果 经过上面两方面的优化，下面是本次优化的结果，关闭浏览器缓存后，多次刷新一般加载时间都是在600-700毫秒之间。congratulations！\n功能篇 1.Moments的添加 具体请查看这篇博客Moments的添加\n效果图： ","date":"2024-05-31T18:40:17+08:00","image":"https://blog-wine-six-14.vercel.app/p/%E5%8D%9A%E5%AE%A2%E4%BC%98%E5%8C%96/cover_hu_16ab6d304d31d5e0.webp","permalink":"https://blog-wine-six-14.vercel.app/p/%E5%8D%9A%E5%AE%A2%E4%BC%98%E5%8C%96/","title":"博客优化"},{"content":"","date":"2024-05-24T23:29:03+08:00","image":"https://blog-wine-six-14.vercel.app/p/%E4%BD%BF%E7%94%A8antv-x6%E7%BB%98%E5%9B%BE%E5%8C%85%E7%9A%84%E4%B8%80%E4%BA%9B%E6%8A%80%E5%B7%A7/image/cover_hu_d5d56fa061ba6265.webp","permalink":"https://blog-wine-six-14.vercel.app/p/%E4%BD%BF%E7%94%A8antv-x6%E7%BB%98%E5%9B%BE%E5%8C%85%E7%9A%84%E4%B8%80%E4%BA%9B%E6%8A%80%E5%B7%A7/","title":"使用Antv X6绘图包的一些技巧"},{"content":"需求 在编辑节点名称的时候，我们希望节点框的大小随着内容的大小进行变化。简单来说就是节点根据内容自适应大小。如何获取内容文本的大小下面有两种方法实现。\n实现 水平文本测量大小的实现 这种方式仅对水平文本有效，能测量出文本的宽度，测量文本的高度无效。\n1 2 3 4 const canvas = document.createElement(\u0026#39;canvas\u0026#39;); const context = canvas.getContext(\u0026#39;2d\u0026#39;); context!.font = \u0026#39;14px Arial, helvetica, sans-serif\u0026#39;; // 设置字体和字号，根据你要测的文本设置 const textWidth = context!.measureText(node.getAttrs()[\u0026#39;text\u0026#39;][\u0026#39;text\u0026#39;]?.toString()!).width; 主要思路就是利用 HTML5 Canvas 的绘图功能来测量文本的宽度，然后根据文本的宽度动态调整节点的尺寸，以确保文本内容完全显示在节点内部。\n创建画布和上下文：\n首先，通过 document.createElement('canvas') 创建了一个 HTML5 Canvas 元素。 然后，通过 getContext('2d') 获取了 2D 绘图上下文，以便后续进行文本测量。 设置字体和字号：\n使用 context.font 设置了绘制文本时所使用的字体和字号。这个需要和你节点内容字体、字号相匹配，否则存在误差 测量文本宽度：\n调用了 context.measureText() 方法来测量给定文本在当前字体和字号下的宽度。measureText() 方法返回一个 TextMetrics 对象，其中包含了文本的宽度等信息。 另一种实现方式 这种方式类似于打一个草稿，先创建一个svg然后渲染然后获得文本的宽高，这个对于水平排列的文本和竖直排列的文本都有效。\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 // 创建一个包含字符串的 svg 元素 const svg = document.createElementNS(\u0026#34;http://www.w3.org/2000/svg\u0026#34;, \u0026#34;svg\u0026#34;); svg.setAttribute(\u0026#39;width\u0026#39;, \u0026#39;100\u0026#39;); svg.setAttribute(\u0026#39;height\u0026#39;, \u0026#39;100\u0026#39;); // 创建一个 \u0026lt;text\u0026gt; 元素 const text = document.createElementNS(\u0026#34;http://www.w3.org/2000/svg\u0026#34;, \u0026#34;text\u0026#34;); text.setAttribute(\u0026#39;font-family\u0026#39;, \u0026#39;Microsoft YaHei\u0026#39;); text.setAttribute(\u0026#39;font-size\u0026#39;, \u0026#39;14\u0026#39;); text.setAttribute(\u0026#39;white-space\u0026#39;, \u0026#39;nowrap\u0026#39;); text.setAttribute(\u0026#39;writing-mode\u0026#39;, \u0026#39;vertical-rl\u0026#39;); text.style.textOrientation = \u0026#39;upright\u0026#39; text.textContent = node.getAttrs()[\u0026#39;text\u0026#39;][\u0026#39;text\u0026#39;]?.toString()! // 将 \u0026lt;text\u0026gt; 元素添加到 \u0026lt;svg\u0026gt; 中 svg.appendChild(text); // 将 \u0026lt;svg\u0026gt; 元素添加到文档中 document.body.appendChild(svg); // 获取字符串的宽高 const textHeight = text.getBBox().height; const textWidth = text.getBBox().width; 主要思路和水平节点的测量相同，不过因为竖直节点的定义和水平节点的不同，竖直节点中的内容是竖直排列，而canvas不能测量文本的高度，所以这里创建和antv X6中svg节点相同的元素，把文本放在其中渲染，然后获取高度，最后完成节点高度的动态调整。\n其中，竖直节点的实现是在css上加上下面三个属性： 1 2 3 white-space: \u0026#39;nowrap\u0026#39;; writing-mode: \u0026#39;vertical-rl\u0026#39;; text-orientation = \u0026#39;upright\u0026#39;; 其他 刚开始我尝试的方法是先修改节点的名称，再通过DOM的getBoundingClientRect获取修改后的文本宽高，但是因为X6 实现了异步的渲染调度算法，所以会出现获取不到DOM元素的情况，如果通过settimeout设置一定的时延再获取，容易造成修改时的频闪，或者有时未动态调整的情况。\n","date":"2024-04-01T22:27:38+08:00","image":"https://blog-wine-six-14.vercel.app/p/%E4%BD%BF%E7%94%A8antv-x6%E7%BB%98%E5%9B%BE%E5%8C%85%E6%97%B6%E8%8A%82%E7%82%B9%E8%87%AA%E9%80%82%E5%BA%94%E5%A4%A7%E5%B0%8F%E7%9A%84%E5%AE%9E%E7%8E%B0/antv_hu_76c5ba5bf37b629c.png","permalink":"https://blog-wine-six-14.vercel.app/p/%E4%BD%BF%E7%94%A8antv-x6%E7%BB%98%E5%9B%BE%E5%8C%85%E6%97%B6%E8%8A%82%E7%82%B9%E8%87%AA%E9%80%82%E5%BA%94%E5%A4%A7%E5%B0%8F%E7%9A%84%E5%AE%9E%E7%8E%B0/","title":"使用Antv X6绘图包时节点自适应大小的实现"},{"content":"问题描述 今天下午在mac系统设置中将系统从版本Ventura 13.5.2升级到Ventura 13.6.4时出现 未能准备软件更新。请再试一次。 的弹窗提示。\n解决过程 首先看到了这篇博客 https://www.waistu.com/archives/LpQOaR1r ，其中他的方法是在命令行输入以下命令 1 sudo softwareupdate -ai --restart 在我输入后，仍然未能成功安装，下面是报错信息：\n1 2 3 4 5 6 7 8 9 10 11 12 Software Update Tool Finding available software Downloading macOS Ventura 13.6.4 Downloading: 100.00%Attempting to quit apps: ( \u0026#34;com.apple.Safari.SafariQuickLookPreview\u0026#34;, \u0026#34;com.apple.Safari\u0026#34; ) Waiting for user to quit any relevant apps Failed to download \u0026amp; prepare update: Error Domain=SUOSUErrorDomain Code=201 \u0026#34;未能准备软件更新。请再试一次。\u0026#34; UserInfo={NSLocalizedRecoverySuggestion=下载所选更新时发生错误。请检查你的互联网连接并再试一次。, NSLocalizedDescription=未能准备软件更新。请再试一次。, NSUnderlyingError=0x600002d780f0 {Error Domain=SUMacControllerError Code=7740 \u0026#34;[SUMacControllerErrorPrepareFailed=7740] Failed to perform Prepare operation: [MobileSoftwareUpdateErrorDomain(MSU):MSU_ERR_FILESYSTEM_DOESNT_VERIFY(3)_1_MobileSoftwareUpdateBOMErrorDomain:1|FullReplacementRequired|]\u0026#34; UserInfo={SUMacControllerErrorIndicationsSummary=|FullReplacementRequired|, SUMacControllerErrorIndicationsMask=2, NSUnderlyingError=0x600002d7ba80 {Error Domain=MobileSoftwareUpdateErrorDomain Code=3 \u0026#34;\u0026#39;./usr/sbin/BlueTool\u0026#39; does not verify\u0026#34; UserInfo={target_update=22G513, NSUnderlyingError=0x600002d7ac40 {Error Domain=MobileSoftwareUpdateBOMErrorDomain Code=1 \u0026#34;contents of \u0026#39;/usr/sbin/BlueTool\u0026#39; don\u0026#39;t match bom (10ddf270 vs ff9bb905)\u0026#34; UserInfo=0x600002358020 (not displayed)}, MSUFullReplacementRecommened=true, NSLocalizedDescription=\u0026#39;./usr/sbin/BlueTool\u0026#39; does not verify}}, NSLocalizedDescription=未能准备软件更新。请再试一次。, NSDebugDescription=[SUMacControllerErrorPrepareFailed=7740] Failed to perform Prepare operation: [MobileSoftwareUpdateErrorDomain(MSU):MSU_ERR_FILESYSTEM_DOESNT_VERIFY(3)_1_MobileSoftwareUpdateBOMErrorDomain:1|FullReplacementRequired|], SUMacControllerErrorIndicationsDescription=-\u0026gt; Full replacement is required [as opposed to incremental patch].}}} 在看到请检查你的互联网连接并再试一次的提示后。我将科学上网关闭后，再次运行上面命令，耐心等待一会后成功更新。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Software Update Tool Finding available software Downloading macOS Ventura 13.6.4 Downloading: 100.00% Downloaded: macOS Ventura 13.6.4 Attempting to quit apps: ( \u0026#34;com.apple.Safari.SafariQuickLookPreview\u0026#34;, \u0026#34;com.apple.Safari\u0026#34; ) Waiting for user to quit any relevant apps Successfully quit all apps Downloading Safari浏览器 Downloaded Safari浏览器 Installing Safari浏览器 [恢复于2024年1月31日 16:10:37] Last login: Wed Jan 31 16:00:39 on console Restored session: 2024年 1月31日 星期三 15时55分04秒 CST ","date":"2024-01-31T21:55:04+08:00","image":"https://blog-wine-six-14.vercel.app/p/%E9%BB%91%E8%8B%B9%E6%9E%9C%E6%9B%B4%E6%96%B0%E7%B3%BB%E7%BB%9F%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98/error_hu_43b4692e74143960.png","permalink":"https://blog-wine-six-14.vercel.app/p/%E9%BB%91%E8%8B%B9%E6%9E%9C%E6%9B%B4%E6%96%B0%E7%B3%BB%E7%BB%9F%E9%81%87%E5%88%B0%E7%9A%84%E9%97%AE%E9%A2%98/","title":"黑苹果更新系统遇到的问题"},{"content":"硬件篇 使用的电脑配置如下，还安装了一张免驱的拆机苹果无线网卡BCM94360CS2：\n为了更好地玩黑苹果，特地加了点预算选了有两个M.2接口的主板，还特地在闲鱼淘了一块256G的二手硬盘。让我没想到的是这块主板虽然是有两个接口，但是插无线网卡的那个Pcie接口和第二个M.2接口会冲突，只能二选一。。。。。属于是做了点功课但是没做全了😭。浪费了一百块的预算，没办法只能再到闲鱼上买了一块240G的sata固态，速度慢了些也没办法了，能玩就行。\nsata固态 淘的这块固态是65块钱，测试结果如下，算是还行吧，安全下车。\n配置过程 在开始决定玩黑苹果时，我是根据黑果魏叔的文章来调整装机配置的（一开始只想简单的上个5600G，为了玩黑苹果在PDD上淘了个亮机卡RX470）。 https://www.imacosx.cn/7375.html 如果你也想玩黑苹果，可以去看看适合的型号。虽然说玩黑苹果Intel的CPU要好一些，但是预算不足，掏钱的时候还是AMD yes！🤗\n学习过程 在b站上跟着国光的黑苹果教程系列学习了基本的EFI知识，一开始自己跟着视频教程和文档 https://apple.sqlsec.com/ 完成了一个EFI的制作，然后跟着这篇文章 https://post.m.smzdm.com/p/agqq02rw/ 开始设置BIOS，可是在主板上只找到了几个需要开关的选项，其中大部分都没找到，难绷，一直找一直找，最后放弃，进入安装系统的环节。果然不出所料！！当我刚开始安装系统的时候就卡住了，报EB错误，不断尝试了一晚上，还是卡EB，遂放弃。\n第二天一早，还是放弃制作EFI，转向github寻找类似配置的EFI，使用 r5 5600 + EFI的关键词找到了较为符合的EFI文件，https://github.com/maxswjeon/OpenCore-5600X-B550-RX560.git，开始了黑苹果的安装过程。\n安装的步骤是参考 https://post.m.smzdm.com/p/agqq02rw/ 这篇文章的，步骤比较详细和符合，不过有一个坑需要注意，就是安装磁盘格式化后的命名上，我使用 MAC OS 时会报错格式化不了，好像是空格的原因吧，使用MAC名称就顺利格式化了。\n安装过程 驱动安装 因为显卡和无线网卡都是免驱的，所以这里比较省心，不用去找驱动安装。安装完成后发现无法外放声音，参考网上的教程发现应该是EFI中config文件中的声卡编码没写对，具体步骤参考下面网站 https://www.dians.net/thread-144.htm ，具体查看自己声卡编码的网址 https://github.com/acidanthera/appleALC/wiki/Supported-codecs 。\n使用体验 目前麦克风不能用，还未解决，其他功能大致正常，就是信息还是登不进去。\nMacOS vs win11 下面是我将电脑分别在macos和win11系统下测得的分数，在mac上的性能大致相当于win11的92%到93%的样子，感觉相差不是很多。\nGPU 跑分 下面是Mac OS下的GPU跑分\n","date":"2024-01-16T23:05:52+08:00","image":"https://blog-wine-six-14.vercel.app/p/%E7%AC%AC%E4%B8%80%E6%AC%A1%E5%B0%9D%E8%AF%95%E9%BB%91%E8%8B%B9%E6%9E%9C/hackintosh_hu_2e616284396d70a7.jpg","permalink":"https://blog-wine-six-14.vercel.app/p/%E7%AC%AC%E4%B8%80%E6%AC%A1%E5%B0%9D%E8%AF%95%E9%BB%91%E8%8B%B9%E6%9E%9C/","title":"第一次尝试黑苹果"},{"content":" 鸣谢 本次改造是基于砖瓦匠杜重的Hugo主题Moments进行的，这里我把它的主要功能作为一个子模块嵌入到stack主题中，同时为适应stack主题，这里也做了小修改。 体验 大家可以访问 https://blog.kellehod.top/moments/链接体验。点击每个瞬间的内容文字可以进入每个瞬间的详情页，并进行评论。\n集成步骤 Moments主题github地址 https://github.com/FarseaSH/hugo-theme-moments.git，先将这个项目下载到本地，然后继续接下来的步骤。\n修改配置文件 添加moments的permalinks 为moments添加permalinks，将之前的permalinks由\n1 2 3 permalinks: post: /p/:slug/ page: /:slug/ 改为\n1 2 3 4 permalinks: post: /p/:slug/ page: /:slug/ moments: /moments/:year/:month/:day/:slug/ 修改params 在params中添加下面的参数\n1 2 3 4 5 6 params: name: Aiden momentsSection: - moments moments: paginate: 6 其中name是当你发布的Moment时名字为空时的默认名字，moments下的paginate是控制Moments一页有多少个moment的参数，这里的分页栏是stack主题提供的。\n添加模板文件 因为文件有点多，这里我将需要添加的文件整理了一下，放到这个仓库中 https://github.com/kellehod/moments-extension.git，请根据对应的路径添加到你主题的指定位置。\n添加HTML文件 先在layouts下添加仓库的layouts\\moments这一整个文件夹 在layouts\\partials下添加仓库的layouts\\partials\\moments这一整个文件夹 在layouts\\shortcodes下添加仓库的layouts\\shortcodes\\moments这一整个文件夹 添加SCSS文件 在assets\\scss\\partials\\layout下添加仓库的moments.scss文件，这个文件是控制Moments样式的 记得在项目中引入这个样式，具体是在assets\\scss\\style.scss中添加 1 @import \u0026#34;partials/layout/moments.scss\u0026#34;; 这里适配了stack主题的暗色模型，并且对移动端的效果进行了些许调整\n添加资源文件 在static目录下添加仓库中static下的所有内容。\n使用 发布Moment类似于发布博客文章，在content目录下新建一个moments的子目录，然后类似写文章的编写markdown文件。具体写法请参照下载的Moments主题中的README.md文件。\n一些使用示例 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 --- name: 瑟德 avatar: date: 2021-08-03T11:57:40+08:00 tags: - 链接 - Github title: test3 link: https://www.github.com link_logo: link_text: GitHub - Where the world builds software · GitHub note: 这是加入链接的Moment --- 你也可以像这样附带网络链接。 GitHub是通过Git进行版本控制的软件源代码托管服务平台，由GitHub公司（曾称Logical Awesome）的开发者Chris Wanstrath、P. J. Hyett和汤姆·普雷斯顿·沃纳使用Ruby on Rails编写而成。（引用自Wikipedia） 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 --- name: 赛肯德 avatar: https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg11.360buyimg.com%2Fn1%2Fjfs%2Ft22180%2F273%2F1048905858%2F16927%2Fc863f2d8%2F5b1ee306Nc3fa41e8.jpg\u0026amp;refer=http%3A%2F%2Fimg11.360buyimg.com\u0026amp;app=2002\u0026amp;size=f9999,10000\u0026amp;q=a80\u0026amp;n=0\u0026amp;g=0n\u0026amp;fmt=jpeg?sec=1630730078\u0026amp;t=818b15beaf41cabfa800ddea79f89445 date: 2021-08-04T11:57:49+08:00 title: hello tags: - 图片集 - 美食 pictures: - https://p8.itc.cn/images01/20210119/628400a0528c4dc696efdac8749b176d.jpeg - bilibili.webp - https://cdn.pixabay.com/photo/2016/10/13/11/44/chocolates-1737503_1280.jpg - https://cdn.pixabay.com/photo/2016/01/11/07/18/cupcakes-1133146_1280.jpg - https://img1.baidu.com/it/u=78864137,3397842120\u0026amp;fm=253\u0026amp;fmt=auto\u0026amp;app=138\u0026amp;f=JPEG?w=889\u0026amp;h=500 note: 这是附带图片集的moment --- 你也可以为每条moment附带更多的图片，做成图片集。 比如最近打卡的美食们： 一些修改说明 图片的引用，这里适配了本地图片的引用，你可以在md文件的Front Matter中写图片路径时直接使用本地图片。类似下面： Front Matter中的title参数，因为Hugp好像是链接的生成时/moments/:year/:month/:day/:slug/中slug占位符是用title生成的（不是很了解），所以为了避免同一天的moment链接覆盖了（重复了），请写一个unique的title参数！！ ","date":"2023-12-07T13:18:57+08:00","image":"https://blog-wine-six-14.vercel.app/p/moments%E7%9A%84%E6%B7%BB%E5%8A%A0/feature_hu_c897e60387b5dd1b.webp","permalink":"https://blog-wine-six-14.vercel.app/p/moments%E7%9A%84%E6%B7%BB%E5%8A%A0/","title":"Moments的添加"},{"content":"逻辑回归的损失函数 逻辑回归的损失函数通常是通过最大似然估计（Maximum Likelihood Estimation, MLE）推导得到的,最大似然估计介绍如下：\n最大似然估计（Maximum Likelihood Estimation, MLE）是统计学和机器学习中一种常用的参数估计方法，用于估计模型参数以最大化观测数据的似然函数。\n最大似然估计： 让我们通过一个生动的例子来解释最大似然估计（Maximum Likelihood Estimation，MLE）是什么。假设你是一名统计学家，对某个城市的新生儿体重感兴趣。你想估计这个城市新生儿的平均体重。\n你在医院收集了 100 个新生儿的体重数据。这些数据如下：\n2.7 kg 3.1 kg 2.9 kg 3.4 kg \u0026hellip; 现在，你知道新生儿的体重通常服从正态分布（高斯分布）。你的任务是使用这些观测数据来估计这个城市新生儿的平均体重。\n这就是应用最大似然估计的场景。你首先要选择一个概率分布模型，正态分布是一个合适的选择，因为它通常用于描述连续型随机变量，如体重。正态分布由两个参数描述：均值（平均值）和标准差。\n你的目标是找到最适合数据的均值和标准差，以使观测数据出现的概率最大。这就是似然性的概念。似然性表示给定模型参数的情况下，观测数据出现的概率。\n你可以使用最大似然估计来估计这两个参数，即找到均值和标准差，以使似然性最大化。在这个过程中，你会考虑所有观测数据，并寻找能够最好描述这些数据的模型参数。\n一旦最大似然估计完成，你将得到一个估计的均值和标准差，这些值代表了这个城市新生儿的平均体重和体重分布的变异程度。\n通过最大似然估计，你将以一种统计上合理的方式估计这个城市新生儿的平均体重，这是一种常用的参数估计方法，可用于许多不同的统计和机器学习问题。\nsigmoid 函数: 这是逻辑回归中的激活函数，用于将线性组合的特征和权重映射到 (0, 1) 之间的概率值。sigmoid 函数的定义如下：\n$$sigmoid = \\frac{1}{1 + e^{-x}}$$\n1 2 def sigmoid(z): return 1 / (1 + np.exp(-z)) 计算逻辑回归损失的函数 为什么逻辑回归可以使用最大似然估计：\n概率建模：逻辑回归是一种概率模型，它使用 logistic 函数（sigmoid 函数）将线性组合的特征和权重映射到一个介于 0 和 1 之间的概率值。对于二元分类问题，逻辑回归建模了样本属于正类别的概率 P(y=1)。\n对数似然函数：在逻辑回归中，对数似然函数用来描述观测数据的似然性。对数似然函数是根据样本的实际类别（y）以及模型的预测概率（hx）来构建的。具体来说，如果 y=1，对数似然函数是 log(hx)；如果 y=0，对数似然函数是 log(1 - hx)。\n最大化似然函数：逻辑回归通过选择模型参数 theta，使对数似然函数最大化，从而最大化似然性。这意味着模型的参数将被调整以使其与观测数据的概率分布最匹配，即最大程度地与数据一致。\n最小化损失函数：通常，为了求解最大似然估计，我们会取对数似然函数的负数，以将最大化问题转化为最小化问题。这就是逻辑回归中的损失函数，通常表示为：\n$$L = -\\frac{1}{N}\\sum_{i=1}^{N} \\left[y_i \\log(hx) + (1 - y_i) \\log(1 - hx)\\right]$$\n其中，$L$ 是损失函数，$N$ 是样本数量，$\\sum$ 表示对所有样本求和, $y_i$ 是第$i$个样本实际观测值。\n下面是当正类为1，负类为-1的逻辑回归函数计算方式\n1 2 3 4 def logistic_loss(X, y ,theta): hx = sigmoid(X.dot(theta)) cost = np.multiply((1+y), np.log(1+hx)) + np.multiply((1-y), np.log(1-hx)) return -cost.mean()/2 逻辑回归梯度函数的推导 逻辑回归的梯度可以通过最大似然估计（Maximum Likelihood Estimation, MLE）的方法来推导。下面是逻辑回归梯度的推导：\n假设我们有一个二元分类问题，标签 y 取值为 0 或 1，而模型的输出是一个概率值，通常用 Sigmoid 函数来表示，即 $$hx = \\frac{1}{1 + e^{-z}}$$，其中 $z$ 是线性组合（$z = X\\theta$）。\n逻辑回归的目标是估计模型参数 theta，以使模型的预测概率 $hx$ 与实际标签 y 尽可能一致。逻辑回归的损失函数通常使用对数损失函数（log loss）来衡量模型的性能。\n对数损失函数的定义如下：\n如果 $y=1$，对数损失函数为 $-log(hx)$ 如果 $y=0$，对数损失函数为 $-log(1 - hx)$ 现在，我们将计算损失函数相对于模型参数 $\\theta$ 的梯度。对于一个训练样本，梯度的计算如下：\n如果 $y=1$，对数损失函数为 $-log(hx)$。使用链式法则，我们可以计算关于 theta 的偏导数：\n$$\\frac{\\partial(-log(hx))}{\\partial \\theta} = -\\frac{1}{hx} * \\frac{\\partial {hx}}{\\partial \\theta}$$\n其中 $\\frac{\\partial {hx}}{\\partial \\theta}$ 表示 $hx$ 相对于 $\\theta$ 的偏导数。我们知道 $hx = \\frac{1}{1 + e^{-z}}$，因此：\n$$\\frac{\\partial {hx}}{\\partial \\theta} = \\frac {e^{-z}} { (1 + e^{-z})^2} * {\\frac{\\partial z}{\\partial \\theta}}$$\n如果 $y=0$，对数损失函数为 $-log(1 - hx)$。同样使用链式法则，我们计算关于 theta 的偏导数：\n$$\\frac{\\partial {(-log(1 - hx))}}{\\partial \\theta} = -\\frac{1}{1 - hx} * \\frac{\\partial{(1 - hx)}}{\\partial \\theta}$$\n由于 $1 - hx = 1 - \\frac{1}{1 + e^{-z}}$，我们可以计算 $\\frac{\\partial{(1 - hx)}}{\\partial \\theta}$：\n$$\t\\frac{\\partial{(1 - hx)}}{\\partial \\theta} = -\\frac {e^{-z}} { (1 + e^{-z})^2} * {\\frac{\\partial z}{\\partial \\theta}}$$\n将上述两种情况合并，我们得到逻辑回归损失函数相对于 $\\theta$ 的梯度：\n$$\\nabla L_{\\theta}\t= (-\\frac{y}{hx} + \\frac{1 - y}{1 - hx}) * \\frac{e^{-z}} {(1 + e^{-z})^2} * \\frac{\\partial z}{\\partial \\theta}$$\n简化后：\n$$\\nabla L_{\\theta} = (hx - y)X$$\n支持向量机 支持向量机（Support Vector Machine，SVM）是一种强大的监督学习算法，主要用于分类和回归问题。它在许多应用领域中都表现出色，如文本分类、图像识别、生物信息学等。SVM的原理涉及到最大间隔分类和核技巧，以下是对SVM的详细介绍：\n1. SVM的基本思想：\nSVM的核心思想是找到一个最佳的超平面（或线性决策边界），以将数据点划分成不同的类别。这个超平面被选为可以最大化类别之间的间隔，因此SVM也被称为最大间隔分类器。SVM的目标是找到一个决策边界，使得两个不同类别的样本离这个边界的距离最大。\n2. 最大间隔分类：\nSVM寻找一个超平面，该超平面能够将不同类别的样本分开，并且使这两个类别最近的样本点到超平面的距离尽可能远。这两个最近的样本点被称为支持向量，它们决定了超平面的位置和方向。SVM的目标是最大化支持向量到超平面的间隔，这被称为最大间隔分类。\n3. SVM的优化问题：\nSVM的任务可以表述为一个凸优化问题。给定训练样本集，SVM的目标是最小化损失函数，其中包含两部分：\n惩罚项（正则化项）：用于控制模型复杂度，防止过拟合。 合页损失项：用于确保样本点距离超平面的间隔足够大。 这个优化问题通常形式为二次规划（Quadratic Programming），可以使用优化算法（如SMO、梯度下降等）来解决。\n4. 核技巧（Kernel Trick）：\nSVM还引入了核技巧，允许SVM在高维特征空间中进行非线性分类。核技巧可以将原始特征映射到更高维的特征空间，从而使数据在新的特征空间中线性可分。常见的核函数包括线性核、多项式核、径向基函数（RBF）核等。内核函数可以看作是一种相似性度量，它度量了两个数据点在高维特征空间中的相似程度。\n5. SVM的分类和回归：\nSVM最常见的应用是二元分类问题，但它也可以扩展到多类分类问题。此外，SVM也可以用于回归问题，称为支持向量回归（Support Vector Regression，SVR），其原理类似，但目标是拟合一个回归曲线，使支持向量到回归曲线的距离尽可能小。\n6. 优点和缺点：\nSVM的优点包括能够处理高维数据，对小样本数据效果好，支持非线性分类，以及具有很强的泛化能力。然而，SVM的计算复杂性较高，对大规模数据和高维数据的处理需要谨慎。此外，选择合适的核函数和调整超参数也可能需要一些经验和实验。\n总之，支持向量机是一种强大的机器学习算法，主要用于二元分类和回归问题。它的原理基于最大间隔分类和核技巧，使其在许多应用领域中表现出色。通过合适的参数调整和特征工程，SVM可以构建出强大的分类器和回归模型。\n合页损失（hinge loss） 合页损失（Hinge Loss）是支持向量机（SVM）中常用的损失函数，用于最大间隔分类。合页损失的主要目标是使正确分类的样本的预测分数远离分类决策边界，同时确保错误分类的样本的预测分数尽可能接近分类边界。\n合页损失的构成：\n合页损失通常由两部分组成：\n合页损失项（Hinge Loss Term）： 这一部分用于衡量模型对数据点的分类情况。对于一个样本，假设它的真实标签为 y（通常是 -1 或 1），而模型的预测值为 X.dot(theta)，其中 X 是特征向量，theta 是模型参数（权重）。合页损失项的公式如下：\n1 loss = max(0, 1 - y * X.dot(theta)) 这个公式表示了真实标签 y 与模型预测之间的差距。如果差距小于1，损失为0；如果差距大于1，损失随着差距的增加线性增加。\ny 是样本的真实标签，可以是+1或-1，表示两个不同的类别。 f(x) 是模型对样本 x 的预测分数，通常是一个线性函数。 在这个公式中，如果 y * f(x) 大于或等于1，合页损失将为0，表示正确分类。如果 y * f(x) 小于1，合页损失将是正数，表示错误分类，且错误分类的程度与 y * f(x) 与1之间的差距成正比。 正则化项（Regularization Term）： 这一部分用于控制模型的复杂度，防止过拟合。通常使用 L2 正则化，它是模型参数 theta 的平方和除以2，如下：\n1 reg = (1/2) * sum(theta^2) 正则化项有助于使模型的参数保持较小的值，以防止过度拟合。\n合页损失的作用：\n分类器边界确定： 合页损失用于确定SVM的分类器边界，即找到一个能够将不同类别的数据点分开的超平面。在训练中，SVM的目标是最小化合页损失项，这使得分类边界能够尽可能远离不同类别的数据点。\n支持向量确定： 合页损失也有助于确定支持向量，这些是距离分类边界最近的数据点。这些支持向量对SVM的分类决策起关键作用，它们帮助确定分类边界的位置。\n平衡间隔与错误： 合页损失在SVM的训练中平衡了最大间隔分类和分类错误之间的权衡。它惩罚了那些被错误分类的样本，并鼓励最大间隔分类。\n参数 t 的作用：\n参数 t 通常用于平衡合页损失项和正则化项的相对重要性。t 控制了损失项和正则化项之间的权重。增加 t 的值会加大合页损失项的重要性，可能导致更强烈地对分类边界进行优化，但也可能增加过拟合的风险。减小 t 的值则相反。 t 的选择通常需要根据特定问题和数据进行调整。\n示例代码\n1 2 3 4 5 #定义 hinge loss 函数 def hinge_loss(X, y, theta, t): loss = np.maximum(0, 1 - np.multiply(y, X.dot(theta))).mean() reg = np.multiply(theta,theta).sum() / 2 return t * loss + reg 合页损失梯度下降函数 python代码实现\n1 2 3 4 5 6 7 8 9 #定义 hinge gradient 函数 def hinge_gradient(X, y, theta, C): error = np.maximum(0, 1 - np.multiply(y, X.dot(theta))) index = np.where(error==0) x = X.copy() x[index,:] = 0 grad = theta - C * x.T.dot(y) / len(y) grad[-1] = grad[-1] - theta[-1] return grad 现在，我们来推导梯度：\n合页损失项贡献的梯度 首先，计算合页损失项对模型输出的梯度，L(y, f(x)) = max(0, 1 - y * f(x)),即 $L$ 对 $f(x)$ 的梯度。合页损失是一个分段函数，它在 $1 - y * f(x)$ 大于零时梯度为 $-y$，否则梯度为零。\n$$ \\frac{dL}{df(x)} = \\begin{cases} -y \u0026amp; \\text{if } 1 - y * f(x) \u0026gt; 0 \\ 0 \u0026amp; \\text{otherwise } \\end{cases} $$\n接下来，我们需要计算 $f(x)$ 对模型参数 $\\theta$ 的梯度。因为$f(x) = X^T \\theta$,所以：\n$$\\frac{df(x)}{d\\theta} = X$$\n现在，我们可以计算合页损失对 $\\theta$ 的梯度,如果 $1 - y * f(x) \u0026gt; 0$: $$\\frac{dL}{d\\theta} = \\frac{dL}{df(x)} * \\frac{df(x)}{d\\theta} = -y * X$$ 否则 $$\\frac{dL}{d\\theta} = 0$$ 正则化项贡献的梯度 最后，我们需要添加正则化项的梯度，以减小权重参数的幅度，防止过拟合。\n$${hinge\\_loss} = t * loss + reg$$ 如果 $1 - y * f(x) \u0026gt; 0$: $$\\frac{d({hinge\\_loss})}{d\\theta} = -t * y * X + \\theta$$，否则 $$\\frac{d({hinge\\_loss})}{d\\theta} = \\theta$$\n为了让梯度下降更稳定，通常还会单独处理截距项（theta[-1]），将其从梯度中减去，以防止截距项被正则化。这是因为截距项通常不需要正则化。\n其中,这一部分是为了处理正则化的截距项。在梯度下降中，通常不对截距项进行正则化，因此这一步减去了正则化项中截距项的影响。\n代码示例\n1 grad[-1] = grad[-1] - theta[-1] Adam优化方法 Adam（Adaptive Moment Estimation）是一种自适应学习率的优化算法，通常用于训练神经网络和深度学习模型。它结合了RMSprop（Root Mean Square Propagation）和动量（momentum）方法的优点，以有效地调整学习率，并且可以适应不同参数的不同学习速度。\n以下是Adam优化方法的详细介绍：\n动量（Momentum）：Adam引入了动量的概念，类似于随机梯度下降中的动量项。它帮助加速梯度下降的过程，尤其在曲线陡峭或弯曲的区域，能够减小学习的波动。\n自适应学习率：Adam调整每个参数的学习率，根据其历史梯度信息来自适应地更新学习率。这意味着对于不同参数，学习率可以自动缩放，从而更好地适应不同参数的特性。\nRMSprop：Adam中包含了RMSprop的思想，它使用了指数移动平均来估计梯度的二阶矩，以便自适应地调整每个参数的学习率。这有助于减小在峡谷区域的学习率，以避免震荡。\nBias-Correction：由于Adam的学习率和移动平均都初始化为零，可能会在初始阶段有较大的偏差。为了纠正这一问题，Adam引入了偏差修正项，确保在开始时有更稳定的学习。\n参数更新：Adam的参数更新规则如下：\n计算梯度：使用当前的小批量训练数据计算梯度。 计算动量：更新动量项，考虑历史梯度信息。 计算RMSprop项：更新历史梯度的平方项。 更新参数：结合动量和RMSprop项，以及学习率来更新模型参数。 应用偏差修正：应用偏差修正项以纠正参数更新。 Adam在训练深度神经网络时通常能够更快地收敛，因为它具有自适应的学习率和动量控制。然而，对于不同的问题和数据集，最佳的优化算法可能会有所不同，因此在实践中通常需要尝试不同的优化算法以找到最佳性能。\n以下是Adam在随机梯度下降中的基本实现步骤：\n初始化参数：\n学习率（learning rate）: 通常设置为一个较小的正数，例如0.001。 梯度一阶矩估计（momentum）: 初始化为0。 梯度二阶矩估计（RMSProp）: 初始化为0。 在每次迭代中，对于每个小批量样本： a. 计算该小批量的梯度。\nb. 更新梯度一阶矩估计（momentum）：\n使用指数加权平均更新一阶矩估计。这类似于随机梯度下降中的动量更新。 具体更新规则：momentum = beta1 * momentum + (1 - beta1) * gradient c. 更新梯度二阶矩估计（RMSProp）：\n使用指数加权平均更新二阶矩估计。 具体更新规则：squared_momentum = beta2 * squared_momentum + (1 - beta2) * (gradient ** 2) d. 修正一阶矩估计偏差（bias correction）：\n随着时间的推移，一阶矩估计和二阶矩估计可能会偏向零。因此，需要进行偏差修正以获得更准确的估计。 具体修正规则：bias_corrected_momentum = momentum / (1 - beta1^t)，其中t表示迭代次数。 e. 修正二阶矩估计偏差（bias correction）：\n具体修正规则：bias_corrected_squared_momentum = squared_momentum / (1 - beta2^t) f. 更新模型参数：\n使用修正后的一阶矩估计和二阶矩估计来计算参数更新。 具体更新规则：parameter = parameter - learning_rate * bias_corrected_momentum / (sqrt(bias_corrected_squared_momentum) + epsilon)，epsilon是一个小正数，用于防止分母为零。 重复步骤2，直到达到停止条件（例如，达到最大迭代次数或损失函数收敛）。\n总之，Adam算法在随机梯度下降中结合了动量和RMSProp，使学习率自适应地调整，以更好地适应不同参数的更新情况。这有助于提高训练的稳定性和收敛速度。\n理解优化方法的相关文章 https://zhuanlan.zhihu.com/p/32230623\nhttps://zhuanlan.zhihu.com/p/32626442\n","date":"2023-11-04T15:45:20+08:00","image":"https://blog-wine-six-14.vercel.app/p/%E9%80%BB%E8%BE%91%E5%9B%9E%E5%BD%92%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB/logic_hu_d8fe1bcfa380592e.png","permalink":"https://blog-wine-six-14.vercel.app/p/%E9%80%BB%E8%BE%91%E5%9B%9E%E5%BD%92%E5%92%8C%E7%BA%BF%E6%80%A7%E5%88%86%E7%B1%BB/","title":"逻辑回归和线性分类"},{"content":" tip 持续更新中\u0026hellip;\u0026hellip; 闭式解 闭式解是线性回归模型参数的精确解，通过解析数学方法获得，而不需要进行迭代优化。下面是闭式解的公式和推导过程：\n线性回归模型： 线性回归的模型假设目标变量（或因变量） y 和特征变量（或自变量） X 之间存在线性关系。它可以表示为：\n$$y = X\\theta + ε$$\n其中，$y$ 是目标变量，$X$ 是特征矩阵，$\\theta$ 是模型参数，$ε$ 是误差项。\n损失函数： 通常，线性回归使用均方误差（Mean Squared Error, MSE）作为损失函数。$MSE$ 表示实际观测值与模型预测值之间的差异的平方的均值。$MSE$ 的公式为：\n$$MSE = \\frac{1}{n} * \\sum(y_i - \\hat{y}_i)^{2}$$\n其中，$n$ 是样本数量，$y_i$ 是实际观测值，$\\hat{y}_i$ 是模型的预测值。\n最小化损失函数： 为了找到最优的模型参数 $\\theta$，我们需要最小化损失函数 $MSE$。这可以通过计算损失函数对参数 $\\theta$ 的偏导数，令偏导数等于零来实现。\n$$\\frac{\\partial(MSE)}{\\partial \\theta} = 0$$\n闭式解的推导： 推导闭式解涉及求解 $\\frac{\\partial(MSE)}{\\partial \\theta} = 0$ 的方程。这里简要描述一下推导的过程：\n首先，我们将 $MSE$ 展开并对参数 $\\theta$ 求偏导数。\n我们将损失函数对参数 $\\theta$ 的偏导数设置为零，以找到最小化 $MSE$ 的 $\\theta$ 值。\n进一步，通过代数运算，我们得到闭式解的公式：\n$$\\theta = (X^TX)^{-1}X^Ty$$\n其中，$X$ 是特征矩阵，$X^T$ 是 $X$ 的转置，$y$ 是目标变量。\n闭式解的含义： 闭式解给出了一个可以直接计算最佳参数 θ 的公式，而无需迭代的优化过程。这是在假设线性关系的情况下，对线性回归模型的最佳参数进行求解的一种有效方法。然而，它的适用范围受限于数据集的大小和矩阵的可逆性。对于较大的数据集，计算矩阵的逆可能会变得昂贵，此时使用迭代方法如梯度下降可能更合适。\npython代码示例\n1 2 3 # 闭式解函数 def normal_equation(X, y): return (np.linalg.inv(X.T.dot(X))).dot(X.T).dot(y) ","date":"2023-11-04T15:40:24+08:00","image":"https://blog-wine-six-14.vercel.app/p/%E7%BA%BF%E6%80%A7%E5%9B%9E%E5%BD%92%E5%92%8C%E6%A2%AF%E5%BA%A6%E4%B8%8B%E9%99%8D/linerRegress_hu_15f2ba4f02cb8af9.jpeg","permalink":"https://blog-wine-six-14.vercel.app/p/%E7%BA%BF%E6%80%A7%E5%9B%9E%E5%BD%92%E5%92%8C%E6%A2%AF%E5%BA%A6%E4%B8%8B%E9%99%8D/","title":"线性回归和梯度下降"},{"content":"1.基本概念 简介 聚类是一种无监督学习的机器学习技术，它旨在将数据集中的对象分成几个相似的组，每个组通常被称为一个簇，以便簇内的对象之间具有高度相似性，而不同簇之间的对象具有较低的相似性。聚类的目标是根据数据的内在结构，将相似的数据点聚集在一起，以便识别模式、发现隐藏的结构以及实现数据的压缩和汇总。 聚类分析的目标是，组内的对象相互之间是相似的，而不同组中的对象是不相似的，组内的相似性越大，组间的差别越大，聚类就越好。\n1.1一个简单的例子 当我们将鱼塘中的鱼按其相似性进行分组，这个过程就是聚类。种类的相似性或者颜色的相似性都可以作为相似性度量的方法。在一般的聚类算法中，我们常用欧氏距离、曼哈顿距离、余弦相似性等方法来度量。\n1.2 不同的聚类类型 层次的与划分的\n划分聚类就是简单的将数据对象集划分为不重叠的簇，下图中b，c，d都是一个划分聚类 层次聚类是嵌套簇的集族，组织成一棵树。层次聚类可以看做划分聚类的序列。下图中(a~d)显示的簇依次形成一个层次聚类，每层分别有1,2,4,6个簇。 互斥的、重叠的、模糊的\n互斥的：每个对象都指派到单个簇 重叠的：一个对象可指派到多个簇，例如，在大学里，一个人可能既是学生又是雇员。 模糊的：每个对象以一个0到1之间的隶属权值属于每个簇。 完全的与部分的\n完全聚类中每个对象都会被指派到一个簇中 部分聚类存在未指派簇的对象 1.3 不同的簇类型 1）明显分离的：图a中显示的就是明显分离的簇的例子，不同组中的任意两点之间的距离都大于组内任意两点的距离。明显分离的簇不必是球形的，可以具有任意形状。 2）基于原型的：簇内对象到定义该簇的原型的距离比到其他簇的原型的距离更近。通常把基于原型的簇看作基于中心的簇，一般这种簇趋近球形。 3）基于图的： 如果数据点作为图的节点，边代表数据对象之间的联系来构成一个图，那么簇就可以定义为连通分支，连通的一组数据点可以指派到一个簇。 4）基于密度的：簇是对象的稠密区域，被低密度的区域环绕。 5）概念簇：概念簇的基本思想是将相关的概念或主题归为一组，从而形成一个聚类，以帮助用户更容易找到相关信息或了解数据的结构。 2.几种经典的聚类算法的实现 2.1.基本的K均值算法(KMeans) K均值是基于原型的、划分的聚类技术。\n基本算法: 随机选择K个初始质心，其中K是用户指定的参数，即所期望簇的个数，然后将所有的数据点指派到距离最近的质心的簇。指派完后根据簇中的点更新每个簇的质心。重复指派和更新步骤，直到簇不发生变化。\n伪代码:\nPython代码实现\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent): \u0026#34;\u0026#34;\u0026#34; k-Means聚类算法,返回最终的k各质心和点的分配结果 \u0026#34;\u0026#34;\u0026#34; m = dataSet.shape[0] # 获取样本数量 # 构建一个簇分配结果矩阵，共两列，第一列为样本所属的簇类值，第二列为样本到簇质心的误差 clusterAssment = np.mat(np.zeros((m, 2))) # 1. 初始化k个质心 centroids = createCent(dataSet, k) clusterChanged = True while clusterChanged: clusterChanged = False for i in range(m): minDist = np.inf minIndex = -1 # 2. 找出最近的质心 for j in range(k): distJI = distMeas(centroids[j, :], dataSet[i, :]) if distJI \u0026lt; minDist: minDist = distJI minIndex = j # 3. 更新每一行样本所属的簇 if clusterAssment[i, 0] != minIndex: clusterChanged = True clusterAssment[i, :] = minIndex, minDist ** 2 print(centroids) # 打印质心 # 4. 更新质心 for cent in range(k): ptsClust = dataSet[np.nonzero(clusterAssment[:, 0].A == cent)[0]] # 获取给定簇的所有点 centroids[cent, :] = np.mean(ptsClust, axis=0) # 沿矩阵列的方向求均值 return centroids, clusterAssment 运行示例\n2.2.二分K均值算法(biKMeans) 二分K均值算法是K均值算法的直接扩充，是基于一种简单的想法：为了得到K个簇，将所有的点的集合作为初始簇，然后分裂成两个簇，从这些簇中选取一个簇进行分裂，重复选取和分裂，直到产生K个簇。\n伪代码\n待分裂的簇有许多种不同的选择方法，可以选择最大的簇，或者最大SSE的簇，或者使用一个基于大小和SSE的标准进行选择。不同的选择将导致不同的簇。\nSSE介绍\nbiKMean代码实现\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 def biKMeans(dataSet, k, distMeas=distEclud): \u0026#34;\u0026#34;\u0026#34; 二分k-Means聚类算法,返回最终各点的分配结果 \u0026#34;\u0026#34;\u0026#34; m = dataSet.shape[0] # 获取样本数量 # 构建一个簇分配结果矩阵，共两列，第一列为样本所属的簇类值，第二列为样本到簇质心的误差 clusterAssment = np.mat(np.zeros((m, 2))) n = dataSet.shape[1] # 获取数据的维度 centroids = np.mat(np.zeros((k, n))) centroids[0, :] = np.mean(dataSet[:, :], axis=0) # 初始簇的质心 for i in range(m): # 计算初始簇样本到簇质心的误差 clusterAssment[i, 1] = distMeas(centroids[0, :], dataSet[i, :]) ** 2 new_cluster_label = 1 # 每次分裂生成一个新簇，分裂K-1次完成 while new_cluster_label \u0026lt; k: largest_sse_cluster_label = -1 largest_sse = -1 # 找到现有簇中最大sse的簇 for cluster in range(new_cluster_label): cluster_sse = sum(clusterAssment[np.nonzero(clusterAssment[:, 0].A == cluster)[0], 1]) if cluster_sse \u0026gt; largest_sse: largest_sse_cluster_label = cluster largest_sse = cluster_sse # 将最大sse的簇进行多次分裂(3次)，选择最小总sse的两个簇 cluster_data_indexs = np.nonzero(clusterAssment[:, 0].A == largest_sse_cluster_label)[0] largest_sse_cluster = dataSet[cluster_data_indexs] lowest_sse = np.inf for j in range(3): sub_centroids, sub_clusterAssment = kMeans(largest_sse_cluster, 2, distMeas=distMeas) tol_subClusters_sse = sum(sub_clusterAssment[:, 1]) if tol_subClusters_sse \u0026lt; lowest_sse: best_newCentroids = sub_centroids best_assment = sub_clusterAssment lowest_sse = tol_subClusters_sse # 更新质心 centroids[new_cluster_label - 1, :] = best_newCentroids[0, :] centroids[new_cluster_label, :] = best_newCentroids[1, :] # 更新簇分配矩阵，子簇类别为0，分为原簇标签，子簇类别为1，则新分配一个类别 for i in range(len(cluster_data_indexs)): sub_cluster_label = best_assment[i, 0] clusterAssment[cluster_data_indexs[i], :] = largest_sse_cluster_label if sub_cluster_label == 0 else new_cluster_label, best_assment[i, 1] # 下一个新分配的簇标签 new_cluster_label += 1 return clusterAssment[:, 0].A[:, 0] 二分K均值（Bisecting K-Means）是对基本的K均值算法的一种改进，其主要提升在于以下几个方面：\n初始簇的选择更合理：在二分K均值中，一开始将整个数据集视为一个簇，然后通过反复的二分操作，将数据集一分为二，以生成两个初始簇。这有助于更合理地选择初始簇，减少了对初始质心的敏感性。 减少局部最小值问题：由于二分K均值从整个数据集开始，而不是一个随机初始簇，它更有可能避免陷入局部最小值问题，即更有可能找到更优的簇划分。 更均匀的簇大小：通过反复的二分，二分K均值可以生成具有相对均匀大小的簇，而不同于基本K均值，可能出现某些簇特别大或特别小的情况。 运行示例：\n2.3.KMeans++算法的实现 KMeans是质心敏感的聚类算法，其初始质心的选择是随机的。 K-Means++ 采用了一种智能化的方法来选择初始的簇中心，而不是随机选择。它通过权衡距离数据点较远的中心，减少了初始簇中心的偶然性。这有助于减少 K-Means 算法陷入局部最小值的风险，从而提高了算法的收敛性和稳定性。\nKMeans++对基本K均值算法的改进就是体现在初始K个质心的选择上。剩下的步骤和基本K均值算法一致。\n伪代码:\n首先随机选择一个初始质心，然后迭代地选择剩余的K-1个质心，确保这些质心相对分散，以减少陷入局部最小值的可能性。它遍历每个数据点，为每个数据点找到到当前所有质心中最近质心的距离，然后选择离最近质心距离最大的数据点作为新的质心，加入存放质心的数组。不断重复，最终函数最终返回K个初始化的质心。\n代码实现\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 def kpp_initialize(dataSet, k): \u0026#34;\u0026#34;\u0026#34; 用于K-Means++的初始化质心 \u0026#34;\u0026#34;\u0026#34; # 从数据点中随机选择第一个质心 centroids = [dataSet[np.random.choice(dataSet.shape[0])]] # 选择剩下的k-1个质心 for i in range(k - 1): dist = [] for j in range(dataSet.shape[0]): # 遍历每个点找到离现有质心最近距离的最大的点 min_dist = sys.maxsize for cent in range(len(centroids)): temp_dist = distEclud(centroids[cent], dataSet[j, :]) min_dist = min(min_dist, temp_dist) dist.append(min_dist) dist = np.array(dist) # 将找到的点作为新的质心，加入质心数组中 new_centroid = dataSet[np.argmax(dist), :] centroids.append(new_centroid) return np.array(centroids) 运行结果\n2.4.DBSCAN算法的实现 DBSCAN是一种简单、有效的基于密度的聚类算法。\n前置知识：核心点、边界点、噪声点的定义\nDBSCAN算法伪代码\n代码实现\n1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 def get_domain_point_mat(data_set, eps): # 获取距离矩阵 distance_mat = get_distance_mat(data_set) # 所有点的方阵，在领域内为1，不在为0 domain_point_mat = (eps \u0026gt; distance_mat).astype(int) return domain_point_mat def get_nearest_core_point(data_set, core_points, border_points): # 获取距离矩阵 distance_mat = get_distance_mat(data_set) # 选择子矩阵,边界点到核心点距离的 temp_mat = distance_mat[border_points, :] result_mat = temp_mat[:, core_points] border_nearest_core_points = np.argmin(result_mat, axis=1) return border_nearest_core_points # 请补全 def dbscan(data_set, eps, min_pts): \u0026#34;\u0026#34;\u0026#34; DBSCAN聚类算法,返回每个样本的cluster类别 \u0026#34;\u0026#34;\u0026#34; m = data_set.shape[0] # 获取样本数量 # 簇类别数组，未分类的点标记为-1 cluster = np.full(m, -1) # 区别核心点，边界点，噪声点，噪声点类别分为-1 domain_point_mat = get_domain_point_mat(data_set, eps) # 获得的点的邻接矩阵，1表示在领域内，0反之 core_points_idx = np.nonzero(np.sum(domain_point_mat, axis=1) \u0026gt;= min_pts)[0] # 找到核心点索引 not_noise_point = np.nonzero(np.sum(domain_point_mat[core_points_idx], axis=0))[0] # 边界点和核心点的集合 border_point = list(set(not_noise_point) - set(core_points_idx)) # 将距离为eps之内的所有核心点赋予一条边，每组连同的核心点形成一个簇 new_cluster_label = 0 unallocated_core_point = set(core_points_idx.copy()) while len(unallocated_core_point) \u0026gt; 0: start_point = unallocated_core_point.pop() # 未分配核心点数组的第一个作为类似广度优先搜索的起始点 new_cluster = set([start_point]) allocated_core_point = [] # 由start_point开始寻找新的一个连通分支 while len(new_cluster) \u0026gt; 0: point = new_cluster.pop() cluster[point] = new_cluster_label allocated_core_point.append(point) adjc_points = np.nonzero(domain_point_mat[point, :])[0] adjc_core_points = set(adjc_points) \u0026amp; set(core_points_idx) - set(allocated_core_point) new_cluster = new_cluster | adjc_core_points new_cluster_label += 1 unallocated_core_point = unallocated_core_point - set(allocated_core_point) # 更新未分配核心点的集合 # 分配边界点，将边界点分配到最邻近的核心点 core_nearest = get_nearest_core_point(data_set, core_points_idx, border_point) # 获取边界点最近核心点的索引，这个索引是对于核心点数组而言的 for border_p in range(len(border_point)): cluster[border_point[border_p]] = cluster[core_points_idx[core_nearest[border_p]]] return cluster 运行示例\nK-距离图：所有点到其第k个最邻近点的距离排序（从小到大），横轴为排序后点的索引，从0 ~ m-1（m为数据点的数量）,纵轴为点到第k个最邻近点的距离。\n参考资料 数据挖掘导论(完整版)Pang-Ning Tan等主编 《数据挖掘》课程实验一 ","date":"2023-10-13T21:46:49+08:00","image":"https://blog-wine-six-14.vercel.app/p/%E8%81%9A%E7%B1%BB%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5%E5%92%8C%E7%AE%97%E6%B3%95/c_1697433832784_hu_55f0272d76c496d7.png","permalink":"https://blog-wine-six-14.vercel.app/p/%E8%81%9A%E7%B1%BB%E5%9F%BA%E6%9C%AC%E6%A6%82%E5%BF%B5%E5%92%8C%E7%AE%97%E6%B3%95/","title":"聚类基本概念和算法"},{"content":"这篇文章介绍的个人博客搭建是使用Hugo框架 + vercel部署 + twikoo评论系统\n准备工作 最好有一个域名（腾讯云、阿里云均有新人特惠首年1元的域名） github账号 Hugo安装 安装文档介绍 https://www.gohugo.org/（推荐使用二进制安装）\nwindows安装示例\n下载二进制文件 https://github.com/gohugoio/hugo/releases (注意下载的是扩展版本) 添加环境变量 在用户变量的path变量中添加hugo二进制文件的放置目录\n测试hugo是否安装成功 windows下需要使用PowerShell, cmd无效 winget安装powershell\n使用管理员打开cmd 输入命令查看powershell安装版本 1 winget search Microsoft.PowerShell 通过 id 下载稳定版的 PowerShell 1 winget install --id Microsoft.Powershell --source winget 打开powershell，输入hugo version 1 hugo version 此时表示hugo正确安装\nHugo使用 1.创建个人博客 在powershell中输入,\u0026lt;sitename\u0026gt;为自定义站名\n1 hugo new site \u0026lt;sitename\u0026gt; 输入 hugo new site blog 后，生成了blog文件夹\n2.下载主题并设置 进入hugo主题库 https://themes.gohugo.io/ 挑选合适的主题，并下载。这里以 stack主题为例， https://themes.gohugo.io/themes/hugo-theme-stack/ ，进入下载链接并下载 下载的zip解压至 blog/themes下 将 blog/themes/hugo-theme-stack-master/exampleSite/content 中的内容复制到 blog/content中 将 blog/themes/hugo-theme-stack-master/exampleSite/config.yaml 复制到 blog项目根目录下，并把 hugo.toml删除(最新版hugo生成的配置文件是 hugo.toml 其他版本可能是 config.yaml 或者 config.toml) 打开复制过来的 config.yaml 确保 theme 的值是刚才下载主题文件夹的名字,其他配置请根据需要更改 1 theme: hugo-theme-stack-master 切换到项目的根目录，运行hugo项目 1 hugo server --buildDrafts --watch 访问 http://localhost:1313 ，查看项目 3.写一篇文章测试 1.切换到根目录下，输入下面的命令 1 hugo new post/test/index.md 这个命令会在 blog/content/post 目录下生成test目录，其中包含 index.md ，用vscode或者其他markdown编辑器打开index.md编辑内容，并查看效果\n1 2 3 4 5 --- title: \u0026#34;Test\u0026#34; date: 2023-08-23T23:55:44+08:00 draft: true --- 这是初始index.md的内容，此时应该将 draft: true 改为 draft: false\n4.博客的语言设置 博客的语言在根目录下的config.yaml中设置。比如这个设置可选英文和中文。则config.yaml中的languages设置如下：\n1 2 3 4 5 6 7 8 9 10 11 12 13 languages: en: languageName: English title: aiden\u0026#39;s blog weight: 1 params: description: Example description zh-cn: languageName: 中文 title: aiden的博客 weight: 2 params: description: 演示说明 博客的默认语言设置，也是在配置文件中设置，默认进到博客就是英语。\n1 DefaultContentLanguage: en 发布博客时，index.md是在默认语言下能看到的，当切换到中文的时候，显示的内容是index.zh-cn.md中的内容。\n所以当你需要修改博文的不同语言表示时，请到相应的.md文件下。同理，博客左侧的菜单栏的不同的语言表示也是在/content/page相应的md文件中修改title。\n5.分类的创建 当你点进archives中时，能看到各种分类的归档。\n分类的创建是在/content/categories下创建类似于post的发布，注意文件夹需要与分类名同名。\nvercel部署 上传代码到github仓库 在github上创建一个新的仓库，开源、私有均可以\n在项目的根目录创建一个文件 vercel.json,比如我这个项目就是创建 blog/vercel.json 来指定部署使用的hugo版本，因为vercel使用的hugo版本比较旧\n1 2 3 4 5 6 7 8 9 10 { \u0026#34;github\u0026#34;: { \u0026#34;silent\u0026#34;: true }, \u0026#34;build\u0026#34;: { \u0026#34;env\u0026#34;: { \u0026#34;HUGO_VERSION\u0026#34;: \u0026#34;0.117.0\u0026#34; } } } 将代码推送到新建的仓库中\n使用vercel部署 打开vercel地址 https://vercel.com/\n使用github登录\n点击右上角的添加新的项目(project)\n导入仓库代码\n选择部署项目的框架为Hugo，然后点击开始部署\n下面则是部署成功的例子\n绑定域名 点击右上角的Domains\n在输入框内输入你的域名，点击add它会提示你应该在你的域名下添加哪些解析记录，例如，我输入 test.kellehod.top后\n按照提示添加解析记录,并开启解析(这里使用的是腾讯云的 dnspod https://www.dnspod.cn/)\nvercel域名完成绑定，自动生成SSL证书, 完成绑定后，注意将根目录中 config.yaml中的 baseurl改为你绑定的域名，例如这个是:\n1 baseurl: https://test.kellehod.top 现在便开始使用你的项目吧！\n嵌入评论系统 配置过程 vercel部署方式的链接 https://twikoo.js.org/quick-start.html#vercel-%E9%83%A8%E7%BD%B2\n详细视频介绍 https://www.bilibili.com/video/BV1Fh411e7ZH/\n上述工作做完后，修改项目根目录下的配置文件 config.yaml\n1.将comment的 provider改为twikoo 1 2 3 comments: enabled: true provider: twikoo 2.配置twikoo,其中 envid是上述部署twikoo的地址，建议使用绑定的域名，使用vercel提供的*.vercel.app地址在国内网络访问下评论系统可能会显示不出。 1 2 3 4 5 twikoo: envId: https://twikoo.kellehod.top/ region: path: lang: 设置博客消息通知 当有人在我们的博客下面留言时，我们希望及时的收到提示消息，这个时候我们就可以通过配置评论系统的通知功能来实现这一目标。twikoo支持即时通知和邮件通知两种不同的方式，当然也可以混合使用。因为个人觉得即时通知比较方便，所以这里我采用的是即时通知的方式。\n首先打开twikoo的配置面板，找到即时通知参数填写的地方。 打开https://pushoo.js.org网址，查看各个消息推送平台的设置方式。这里我采用的是飞书平台， https://www.feishu.cn/hc/zh-CN/articles/360024984973-%E5%A6%82%E4%BD%95%E5%9C%A8%E7%BE%A4%E7%BB%84%E4%B8%AD%E4%BD%BF%E7%94%A8%E6%9C%BA%E5%99%A8%E4%BA%BA，按照这个文档的指示创建自定义机器人(需要在PC端配置)，将生成的地址填写到twikoo的配置面板并保存。即时通知就配置好了。 ","date":"2023-08-23T20:16:25+08:00","image":"https://blog-wine-six-14.vercel.app/p/buildblog/hugo_hu_a06c8814bf2a76fe.png","permalink":"https://blog-wine-six-14.vercel.app/p/buildblog/","title":"Buildblog"},{"content":"aiden blog 你好Ablog\n测试代码块 1 for i in range(90): 测试admonition 注意 一个 提示 横幅 未添加到字库的字（手动添加） 1.昵称 2.邮箱 的一是在不了有和人这中大为上个国我以要他时来用们生到作地于出就分对成会可主发年动同工也能下过子说产种面而方后多定行学法所民得经十三之进着等部度家电力里如水化高自二理起小物现实加量都两体制机当使点从业本去把性好应开它合还因由其些然前外天政四日那社义事平形相全表间样与关各重新线内数正心反你明看原又么利比或但质气第向道命此变条只没结解问意建月公无系军很情者最立代想已通并提直题党程展五果料象员革位入常文总次品式活设及管特件长求老头基资边流路级少图山统接知较将组见计别她手角期根论运农指几九区强放决西被干做必战先回则任取据处队南给色光门即保治北造百规热领七海口东导器压志世金增争济阶油思术极交受联什认六共权收证改清己美再采转更单风切打白教速花带安场身车例真务具万每目至达走积示议声报斗完类八离华名确才科张信马节话米整空元况今集温传土许步群广石记需段研界拉林律叫且究观越织装影算低持音众书布复容儿须际商非验连断深难近矿千周委素技备半办青省列习响约支般史感劳便团往酸历市克何除消构府称太准精值号率族维划选标写存候毛亲快效斯院查江型眼王按格养易置派层片始却专状育厂京识适属圆包火住调满县局照参红细引听该铁价严龙飞啊爱吧吧白帮被本比别病不才菜参差常长场车成吃出穿次从打大当到道的地点电东动都对多饿儿二发反方房放分风服该干高告哥歌个给工公狗关光国果过还孩海好喝和很后话坏回会机几家见件讲角叫姐今经九觉开看可乐课快来了冷里力脸两亮聊买慢忙吗么没每门们面名明哪那难呢能你年女朋票平期气钱前情请去然让日三上少社谁身生师时识实市事是手书刷水睡说思四岁他她它台太谈天听通同头玩晚为文问我五西洗喜系下先现想向笑些心新信星行兴休学雪呀言眼阳要也业一已意因应影友有雨元再在怎找真正知中种主注自走作做坐爱安吧百北比便冰播步部才彩餐草茶差产唱超朝城吃充抽出处传窗床此答代带待蛋倒等低弟调丢懂短断队饿耳饭房费粉封否父复改感刚格跟够姑怪贵滚孩含汗行合黑猴呼互化画坏欢黄活击极记季加简见奖交脚接街姐借紧惊净久旧举决咖开考刻客空哭块困啦懒狼冷理礼脸凉料邻领流露乱码卖猫毛么妹门迷密秒模某母拿哪闹内您牛弄怕排旁跑配片漂扑普骑汽铅钱枪强悄切亲轻区取趣缺然热忍扔肉赛伞扫色杀傻闪伤商稍舍深神升胜失师试室收叔舒刷摔谁顺司松送诉虽随孙缩所它抬谈汤堂讨疼提体替甜贴厅挺偷投图推退托娃歪弯网忘危微闻卧握屋午务吸戏细吓鲜乡箱响像消小孝写醒幸兄休许选呀盐阳摇药爷页夜移已议阴引印应泳游友右鱼愉遇园远愿约越灾咱早澡怎增展站找折者珍真整证支直值止钟众重助抓专转桌仔紫总走租嘴尊左作做 帅 美 丽 俊 酷 靓 俏 甜 萌 俊 秀 娇 媚 艳 仙 俊 飒 俊 朗 俊 雅 俊 俏 俊 秀 俊 逸 俊 朗 俊 雅 俊 俏 俊 秀 俊 逸 酷 飒 霸 拽 痞 呆 憨 乖 骚 浪 奶 狼 御 柔 温 暖 冷 傲 凶 萌 甜 盐 奶 野 妖 仙 清 纯 欲 辣 丧 佛 系 高 矮 胖 瘦 壮 肥 匀 称 苗 条 魁 梧 娇 小 健 硕 骨 感 圆 润 大 小 圆 长 尖 方 弯 直 浓 淡 眉 眼 鼻 唇 齿 耳 肤 色 白 黑 黄 红 润 糙 嫩 皱 长 短 卷 直 秃 刘 海 辫 髻 蓬 松 油 亮 乱 顺 滑 潮 土 俗 洋 气 时 尚 复 古 运 动 休 闲 正 装 性 感 可 爱 清 新 华 丽 简 约 夸 张 好 看 丑 怪 丑 萌 惊 艳 路 人 路 人 甲 路 人 乙 路 人 丙 路 人 丁 路 人 戊 路 人 己 路 人 庚 路 人 辛 路 人 壬 路 人 癸 笑 哭 怒 嗔 痴 呆 懵 晕 醉 困 倦 懒 羞 臊 尴 尬 慌 张 傲 娇 害 羞 嘚 瑟 嚣 张 猥 琐 油 腻\n","date":"2023-08-22T17:14:49+08:00","image":"https://blog-wine-six-14.vercel.app/p/first/cover_hu_ea70462fa7f03685.webp","permalink":"https://blog-wine-six-14.vercel.app/p/first/","title":"First"}]