Ubuntu双系统重装Windows后修复grub2引导 UEFI

如果你在安装了Ubuntu和Windows双系统后,又重装了Windows系统。那么Grub引导项大概率会被Windows Boot Manager覆盖,这时候你就进不了Ubuntu了。但不要慌,按照下面的步骤可以修复grub2引导,而且不需要安装额外的软件。 制作Ubuntu的U盘启动盘 为了修复引导项,我们需要用到Ubuntu系统提供的软件工具。虽然我们暂时进不去原来的Ubuntu系统,但是我们可以使用写在Ubuntu U盘中的镜像来获得一个可用的基本Ubuntu环境。 在Ubuntu官网下载镜像文件。 制作U盘启动盘可以使用免安装、小巧好用的rufus。你可以使用rufus快速创建一个U盘启动盘,注意选择GPT模式。 引导U盘启动盘 重启电脑,在BIOS引导设置中引导U盘,然后进入Ubuntu引导安装程序后,在安装界面选择Try Ubuntu进入Ubuntu Live。 执行Grub2重建操作 使用fdisk,找到EFI分区,/boot挂载点所在的分区(如果你没有设置/boot挂载点则为/挂载点)。 挂载/boot挂载点所在的分区到/mnt下(我的分区在nvme固态硬盘上)。 % sudo mount /dev/nvme0n1p6 /mnt/ 挂载EFI分区,在这里你需要知道在你的硬盘中那一个分区是EFI系统分区(我这里是第五个分区)。 % sudo mount /dev/nvme0n1p5 /mnt/boot/efi 连接其他必要的目录 % sudo mount --bind /dev /mnt/dev % sudo mount --bind /dev/pts /mnt/dev/pts % sudo mount --bind /proc /mnt/proc % sudo mount --bind /sys /mnt/sys 转换根目录到/mnt下 % sudo chroot /mnt 修复Grub2引导 对于32位系统和64位系统,在这里你需要运行的命令是不同的。下面分别给出了它们对应的命令。 32位系统 % sudo grub-install --target=i386-efi /dev/nvme0n1 64位系统 % sudo grub-install --target=x86\_64-efi /dev/nvme0n1 执行完上面命令当中的一条后,再执行一下Recheck % grub-install --recheck /dev/nvme0n1 后续清理步骤(可要可不要) % exit % sudo umount /mnt/sys % sudo umount /mnt/proc % sudo umount /mnt/dev/pts % sudo umount /mnt/dev % sudo umount /mnt 然后重新启动,你会发现已经能够成功进入grub2界面,并且grub2已经识别到了Ubuntu系统和Windows Boot Manager。 ...

十一月 26, 2021

解决yarn安装electron、chromedriver等软件包超时、缓慢的问题

在国内使用yarn安装electron、chromedriver是经常出现无法连接的问题,这个时候,相对于设置代理,我们可能更希望使用在国内的镜像仓库来加速这个过程。并且安装electron的时候,单单设置yarn的全局代理是没有用的。那如何根据不同的软件包设置代理呢?你可以按照以下列表中提供的命令样例来设置。 yarn全局设置 设置yarn安装一般的软件包时使用的仓库地址。 yarn config set registry https://r.npm.taobao.org 注册模块镜像 yarn config set disturl https://npm.taobao.org/dist # node-gyp 编译依赖的 node 源码镜像 这是运行以上命令的结果,你可以很清楚地看到设置是否成功。 yarn安装特定软件包设置 设置yarn安装electron 、chromedriver 等软件包安装使用到的仓库地址。你可以按照需要选择一两个命令来设置,一股脑全部加上是被必要的。 yarn config set sass\_binary\_site https://npm.taobao.org/mirrors/node-sass # node-sass 二进制包镜像 yarn config set electron\_mirror https://npm.taobao.org/mirrors/electron/ # electron 二进制包镜像 yarn config set puppeteer\_download\_host https://npm.taobao.org/mirrors # puppeteer 二进制包镜像 yarn config set chromedriver\_cdnurl https://npm.taobao.org/mirrors/chromedriver # chromedriver 二进制包镜像 yarn config set operadriver\_cdnurl https://npm.taobao.org/mirrors/operadriver # operadriver 二进制包镜像 yarn config set phantomjs\_cdnurl https://npm.taobao.org/mirrors/phantomjs # phantomjs 二进制包镜像 yarn config set selenium\_cdnurl https://npm.taobao.org/mirrors/selenium # selenium 二进制包镜像 yarn config set node\_inspector\_cdnurl https://npm.taobao.org/mirrors/node-inspector # node-inspector 二进制包镜像 和上面的类似,运行命令后你可以很清楚地看到设置是否成功。 ...

十一月 22, 2021

oh my zsh 在Ubuntu下的配置教程

oh my zsh是十分好用的基于zsh的配置框架,它能简化Linux终端用户的很多日常操作。而且,它的界面相对于原始的bash来说,非常好看。这篇文章就是用来介绍如何在Ubuntu下安装并配置oh my zsh及其常用插件的。 oh my zsh 安装与基本配置 在oh my zsh 安装前需要先执行以下命令安装下列git、curl、zsh。 % sudo apt install git curl zsh 安装完依赖项目后,直接执行下面的命令来一键安装: % sh -c "$(curl -fsSL https://raw.github.com/ohmyzsh/ohmyzsh/master/tools/install.sh)" 设置zsh为默认shell: % chsh 按照提示一步一来,输入/bin/zsh即可。 常用插件安装 单单配置oh my zsh本身是远远不够的,你可能需要以下常用插件来真正达到简化操作的目的。 z 历史目录管理 zsh-autosuggestions 命令提示 zsh-syntax-highlighting 高亮 sudo 忘记加sudo前缀之时 extract 一个命令解压几乎所有安装包 z 无需额外安装,直接在plugins中填写即可。 zsh-autosuggestions 先执行以下命令,然后在plugins中填写。 % git clone git://github.com/zsh-users/zsh-autosuggestions ${ZSH\_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-autosuggestions zsh-syntax-highlighting 先执行以下命令,然后在plugins中填写。 % git clone https://github.com/zsh-users/zsh-syntax-highlighting.git ${ZSH\_CUSTOM:-~/.oh-my-zsh/custom}/plugins/zsh-syntax-highlighting sudo 无需额外安装,直接在plugins中填写即可。 extract 无需额外安装,直接在plugins中填写即可。 设置代理 我们可以通过在.zshrc中加入以下配置来启动可开关的代理功能: proxy() { export https\_proxy=http://127.0.0.1:1234 export http\_proxy=http://127.0.0.1:1234 export all\_proxy=socks5://127.0.0.1:1234 } unproxy() { unset https\_proxy unset http\_proxy export all\_proxy } 你可以将1234改为你任何想要的端口。 ...

十一月 22, 2021

使用 space-vim-dark 一键配置、美化vim编辑器

一直以来我都使用一些成熟的配置文件来帮助我配置、美化vim编辑器,然而我原来使用的spf13-vim.sh已经很久不更新了,它的插件列表中有些插件已经不能正常下载了。所以我想寻找它的替代品,最后发现 space-vim-dark还不错。 space-vim-dark基本介绍 经过我的寻找,找到了一个比较好用且美观的配置文件space-vim-dark。这个space-vim-dark可能是国人编写的vim配置文件,它能很好使得vim适应暗色模式。 先贴出仓库地址:https://github.com/liuchengxu/space-vim-dark 这是它的效果图,整体看还是不错的。 用它配置、美化vim编辑器 设置space-vim-dark非常简单,你只需要在你的vim插件管理器中添加下面的设置。 Plug 'liuchengxu/space-vim-dark' 整体使用下来,我觉得该有的插件还是有的,并且用起来顺手不少。 加入额外配置 在~/.spacevim中可以加入你自己的一些配置。

十一月 22, 2021

求解三维装箱问题的混合模拟退火算法的实现 MATLAB

由于要数学建模中需要解决一个三维装箱的问题,我经过搜寻选定了张德富教授等在计算机学报上发表的《求解三维装箱问题的混合模拟退火算法》这篇论文作为解决问题的理论基础。 该论文的摘要如下: 提出了一个高效求解三维装箱问题(Three Dimensional Container Loading Problem 3D-CLP)的混合模拟 退火 算法 .三维装箱问题要求装载给定箱子集合的一个子 集到容器中 , 使得被装载 的箱子总体 积最大 .文中介绍 的 混合 模拟退火算法基于三个重要算法 :(1)复合块生成算法 , 与传统算法 不同的是文中提出的复合块 不只包含单 一 种类的箱子 , 而是可以在一定的限制条件下包含 任意种类的箱子 .(2)基础启发式算法 , 该算法 基于块装 载 , 可以 按 照指定装载序列生成放置方案.(3)模拟退火算法,以复合块生成和基础启发式算法为基础, 将装载序列作为可行 放置 方案的编码 , 在编码空间中采用模拟退火算法进行搜 索以寻找问题的近似最 优解 .文 中采用 1 50 0 个弱异构 和 强异构的装箱问题数据对算法进行测试 .实验结 果表明 , 混合模拟退火算法的填充率超过了目前已知的 优秀算法 . DOI 号 :10.3724/ SP .J.1016 .2009.02147 本文算法实现其计算结果 该实现的核心函数MATLAB代码 function \[solution, newPlan, rate\] = container\_packeting(bcon, plan, blockTable, blockNeed) %UNTITLED2 根据大小容器的规格以及小容器的数量信息计算出打包的方案 % bigContainer 大容器的规格向量 \[L W H\] % smallContainers 小容器的规格矩阵\[L W H;\] % smallContainersNumber 小容器的数量向量 \[n\] solution = {}; newPlan = \[\]; searchDeep = 40960; clf; draw\_container(\[0,0,0\], bcon); % 剩余空间栈 lspace\_s = get\_stack(); % 空隙栈 iterval\_s = get\_stack(); itervalSpace\_s = get\_stack(); % 初始化剩余空间为大容器空间 lspace\_s = stack\_push(lspace\_s, get\_space(\[0,0,0\], bcon)); psCount = 0; while lspace\_s.count > 0 psCount = psCount + 1; % 从剩余空间栈中取得可用的剩余空间 lspace = stack\_top(lspace\_s); lspace\_s = stack\_pop(lspace\_s); lspace\_size = lspace.size; lspace\_base = lspace.base\_point; if\_input = 0; \[blockList, blockListNeed\] = get\_block\_list(blockTable, blockNeed, lspace\_size(1), lspace\_size(2), lspace\_size(3)); theBlockNeed = NaN; find\_idx = 1; if size(blockList, 1) == 0 find\_avaliable = 0; else find\_avaliable = 1; if plan(psCount) <= size(blockListNeed, 1) theBlockNeed = blockListNeed(plan(psCount),:); find\_idx = plan(psCount); else theBlockNeed = blockListNeed(size(blockListNeed, 1),:); find\_idx = size(blockListNeed, 1); end newPlan = \[newPlan, find\_idx\]; end %% locate container if find\_avaliable == 1 newLocatedBlock = {lspace\_base, blockList(find\_idx, :), theBlockNeed{1}, theBlockNeed{2}}; solution(size(solution, 1) + 1, :) = newLocatedBlock; spaceInfo = newLocatedBlock{4}; spaceLastInfo = spaceInfo(size(spaceInfo,1), :); locateInfo = newLocatedBlock{2}; hold on; draw\_container(lspace\_base, locateInfo(1:3)); itervalSpace\_s = stack\_push(itervalSpace\_s, (1-spaceLastInfo(1)) \* prod(locateInfo(1:3))); if\_input = 1; % 剩余空间计算 % H方向剩余空间 location = lspace\_base; location(2) = location(2) + locateInfo(2); iterval\_space = get\_space(location, \[locateInfo(1) , lspace\_size(2) - locateInfo(2), locateInfo(3)\]); lspace\_s = stack\_push(lspace\_s, iterval\_space); % L方向剩余空间 location = lspace\_base; location(1) = location(1) + locateInfo(1); left\_space = get\_space(location, \[lspace\_size(1) - locateInfo(1), lspace\_size(2), lspace\_size(3)\]); lspace\_s = stack\_push(lspace\_s, left\_space); % W方向剩余空间 location = lspace\_base; location(3) = location(3) + locateInfo(3); iterval\_space = get\_space(location, \[locateInfo(1) , lspace\_size(2), lspace\_size(3) - locateInfo(3)\]); lspace\_s = stack\_push(lspace\_s, iterval\_space); end if if\_input == 1 else % 压入空隙栈 iterval\_s = stack\_push(iterval\_s, lspace); % lspace\_s = stack\_push(lspace\_s, lspace); end end rate = space\_used\_rate(bcon, solution); end function rate = space\_used\_rate(container, solution) spaceHasTotal = 0.0; for i = 1:1:size(solution, 1) mergeMessage = solution{i, 4}; for k = 1:1:size(mergeMessage,1) spaceHasTotal = spaceHasTotal + prod(mergeMessage(k, 3:5)); end end rate = spaceHasTotal / prod(container); end 箱体产生函数 function \[blockTable, boxNeedTable\] = simple\_block\_generate\_indepent(container, box, num) simBlockCount = 0; simBlockTable = zeros(256, 8); for type = 1:1:size(box, 1) for nx = 1:1:num(type) for ny = 1:1:num(type)/nx for nz = 1:1:num(type)/ny/nx if box(type,3) \* nx < container(3) && box(type, 1) \* ny < container(1) && box(type, 2) \* nz < container(2) newSimBlock = \[box(type, :), nx, ny, nz, type, prod(box(type, :)) \* nx \* ny \* nz\]; simBlockTable(simBlockCount + 1, :) = newSimBlock; simBlockCount = simBlockCount + 1; end end end end end simBlockTable = simBlockTable(1:simBlockCount, :); simBlockTable = sortrows(simBlockTable, 8); simBlockTable = simBlockTable(:, 1:7); % 处理成启发式算法可以处理的格式 simBlockTable(:, 13) = ones(size(simBlockTable, 1), 1); simBlockTable(:, 11) = simBlockTable(:,4) .\* simBlockTable(:,3); simBlockTable(:, 12) = simBlockTable(:,5) .\* simBlockTable(:,1); % ly = ay simBlockTable(:, 8) = simBlockTable(:, 12); % lx = ax simBlockTable(:, 10) = simBlockTable(:, 11); % lz = lz0 \* nz simBlockTable(:, 9) = simBlockTable(:, 2) .\* simBlockTable(:, 6); boxNeedTable = cell(size(simBlockTable, 1), 2); for i = 1:1:size(simBlockTable, 1) boxNeedTable{i, 1} = zeros(1, size(box ,1)); boxNeedTable{i, 1}(simBlockTable(i, 7)) = simBlockTable(i, 4) \* simBlockTable(i, 5) \* simBlockTable(i, 6); boxNeedTable{i, 2} = \[simBlockTable(i, 7), 0, simBlockTable(i, 8:10)\]; end blockTable = simBlockTable(:, 8:13); blockTable(:,7) = blockTable(:, 1) .\* blockTable(:, 2) .\* blockTable(:, 3); \[blockTable, idx\] = sortrows(blockTable, \[ 7 \]); boxNeedTable = boxNeedTable(idx, :); end 箱体组合产生函数 function \[blockTable, boxNeedTable\] = complex\_block\_genrate(container, box, num, level) simBlockTable = simple\_block\_generate(container, box, num); simBlockTable(:, 13) = ones(size(simBlockTable, 1), 1); simBlockTable(:, 11) = simBlockTable(:,4) .\* simBlockTable(:,3); simBlockTable(:, 12) = simBlockTable(:,5) .\* simBlockTable(:,1); spaceUsedRateMin = 0.90; % ly = ay simBlockTable(:, 8) = simBlockTable(:, 12); % lx = ax simBlockTable(:, 10) = simBlockTable(:, 11); % lz = lz0 \* nz simBlockTable(:, 9) = simBlockTable(:, 2) .\* simBlockTable(:, 6); boxNeedTable = cell(size(simBlockTable, 1), 2); for i = 1:1:size(simBlockTable, 1) boxNeedTable{i, 1} = zeros(1, size(box ,1)); boxNeedTable{i, 1}(simBlockTable(i, 7)) = simBlockTable(i, 4) \* simBlockTable(i, 5) \* simBlockTable(i, 6); boxNeedTable{i, 2} = \[simBlockTable(i, 7), 0, simBlockTable(i, 8:10)\]; end blockTable = simBlockTable(:, 8:13); for level = 1:1:level newBlockTable = zeros(128,6); newBlockCount = 1; boxNeedCount = size(boxNeedTable, 1); for a = 1:1:size(blockTable,1) for b = a:1:size(blockTable, 1) if b == a continue; end if blockTable(a, 6) == blockTable(b, 6) % x 方向合并 if blockTable(a, 1) == blockTable(a, 5) && blockTable(a, 3) == blockTable(a, 4) && blockTable(a, 2) == blockTable(b, 2) tempBlockMerged = \[max(blockTable(a,1), blockTable(b,1)), max(blockTable(a,2), blockTable(b, 2)), blockTable(a,3) + blockTable(b,3), blockTable(a,4) + blockTable(b,4), min(blockTable(a,5), blockTable(b,5)), max(blockTable(a, 6), blockTable(b, 6)) + 1\]; rate = space\_used\_rate(tempBlockMerged(1:3), blockTable(a,1:3), blockTable(b,1:3)); if rate > spaceUsedRateMin newBlockTable(newBlockCount, :) = tempBlockMerged; boxNeedCount = boxNeedCount + 1; newBlockCount = newBlockCount + 1; boxNeedTable{boxNeedCount, 1} = boxNeedTable{a,1} + boxNeedTable{b,1}; boxNeedTable{boxNeedCount, 2} = \[boxNeedTable{a, 2}; rate, 1, blockTable(b, 1:3)\]; end end % y 方向合并 if blockTable(a, 5) == blockTable(a, 1) && blockTable(b, 5) == blockTable(b, 1) && blockTable(a, 2) == blockTable(b, 2) tempBlockMerged = \[blockTable(a,1) + blockTable(b,1), max(blockTable(a, 2), blockTable(b, 2)), max(blockTable(a, 3), blockTable(b, 3)), min(blockTable(a, 4), blockTable(b, 4)), blockTable(a, 5) + blockTable(b, 5), max(blockTable(a, 6), blockTable(b, 6)) + 1\]; rate = space\_used\_rate(tempBlockMerged(1:3), blockTable(a,1:3), blockTable(b,1:3)); if rate > spaceUsedRateMin newBlockTable(newBlockCount, :) = tempBlockMerged; newBlockCount = newBlockCount + 1; boxNeedCount = boxNeedCount + 1; boxNeedTable{boxNeedCount, 1} = boxNeedTable{a,1} + boxNeedTable{b,1}; boxNeedTable{boxNeedCount, 2} = \[boxNeedTable{a, 2}; rate, 2, blockTable(b, 1:3)\]; end end % z 方向合并 if blockTable(a,4) >= blockTable(b,3) && blockTable(a, 5) >= blockTable(b, 1) tempBlockMerged = \[max(blockTable(a,1), blockTable(b, 1)), blockTable(a, 2) + blockTable(b, 2), max(blockTable(a, 3), blockTable(b, 3)), blockTable(b, 4), blockTable(b, 5), max(blockTable(a, 6), blockTable(b, 6)) + 1\]; rate = space\_used\_rate(tempBlockMerged(1:3), blockTable(a,1:3), blockTable(b,1:3)); if rate > spaceUsedRateMin newBlockTable(newBlockCount, :) = tempBlockMerged; newBlockCount = newBlockCount + 1; boxNeedCount = boxNeedCount + 1; boxNeedTable{boxNeedCount, 1} = boxNeedTable{a,1} + boxNeedTable{b,1}; boxNeedTable{boxNeedCount, 2} = \[boxNeedTable{a, 2}; rate, 3, blockTable(b, 1:3)\]; end end end end end blockTable = cat(1, blockTable, newBlockTable(1:newBlockCount-1, :)); % 消除等价复杂块 blockTableTemp = blockTable(:, 1:5); \[~, ia\] = unique(blockTableTemp, 'stable', 'rows'); blockTable = blockTable(ia, :); boxNeedTable = boxNeedTable(ia, :); end blockTable(:,7) = blockTable(:, 1) .\* blockTable(:, 2) .\* blockTable(:, 3); \[blockTable, idx\] = sortrows(blockTable, \[ 7 \]); boxNeedTable = boxNeedTable(idx, :); end function \[rate\] = space\_used\_rate(container, box1, box2) rate = (prod(box1) + prod(box2)) /prod(container); end Main函数 ts = 1; tf = 0.005; dt = 0.98; length = 50; maxSeq = 64; maxChoice = 1024; click = 1; tempRate = \[\]; tempRateX = \[\]; numList = \[64,64,64,64,64,64,64,128,128,128\]; container = StandardISOContainer; % \[blockTable, blockNeed\] = complex\_block\_genrate(StandardISOContainer, Packets, numList, 1); ps = ones(1, maxSeq); ps(1) = 1; \[solution, plan, rate\] = container\_packeting(container, ps, blockTable, blockNeed); best = plan; best\_rate = rate; best\_solution = solution; t = ts; while t > tf for i = 1:1:length k = randi(size(ps)); nps = ps; nps(k) = randi(maxChoice); \[solution, nplan, nrate\] = container\_packeting(container, nps, blockTable, blockNeed); % disp(\['TempPlan: ', mat2str(nplan)\]); % fprintf("TempRate: %f\\n",nrate); click = click + 1; if nrate > rate ps = nps; plan = nplan; rate = nrate; tempRateX = \[tempRateX, click\]; tempRate = \[tempRate, nrate\]; elseif rand(0, 1) > exp((nrate - rate) \* 10 / t) ps = nps; plan = nplan; rate = nrate; end if nrate > best\_rate best = nplan; best\_rate = nrate; best\_solution = solution; disp(\['BestPlan: ', mat2str(best)\]); fprintf("BestRate: %f\\n",best\_rate); end end t = (1 - t \* dt) \* t; end disp(\['BestPlan: ', mat2str(best)\]); fprintf("BestRate: %f\\n",best\_rate); figure(1) draw\_solution(container, best\_solution); figure(2) plot(tempRateX, tempRate); save Solution best\_solution best\_rate tempRateX tempRate

九月 30, 2021

TransRepair: Automatic Testing and Improvement of Machine Translation(机器翻译的自动化测试和改进)

最近,我阅读了一篇名为 TransRepair: Automatic Testing and Improvement of Machine Translation 的研究论文。该论文介绍了一种名为TransRepair的方法,用于在软件测试领域下自动测试机器翻译模型。下面,我将从几个方面对论文的内容进行总结,并讨论其中的关键点。 TransRepair简介 TransRepair是一种用于自动检测和修复机器翻译软件一致性问题的方法。它提供了黑盒和灰盒两种方法来解决机器翻译软件的一致性问题。TransRepair的主要步骤包括生成测试用例、创建测试准则和自动修复过程。该方法提供了清晰、严谨和详细的测试用例生成算法,并采用了四种句子差异的量化方法进行比较。此外,TransRepair还运用了结构一致性原理作为断言,并提供了全面的实验设计和多样化的结果。 关键问题的理解 一致性问题是指机器翻译软件在处理一组具有相似语义和结构但某些特定词语上略有不同的句子时,在对应翻译句集合中的某一句或几句中的某个或几个部分出现的语义、结构不一致的现象。 TransRepair生成测试用例的方法是对输入的原句进行词语替换,形成突变句组。为了实现这一操作,TransRepair使用了词向量模型来计算词语之间的关联性。在选择候选词后,还会将其带入句子中进行成分分析,以确定句子的语义和语法是否发生较大变化。 在验证测试用例输出句子对的一致性时,TransRepair首先使用Widiff进行字符串成分的差异性比较分析。为了增强相似度量化的可靠性,TransRepair还构造了原句和翻译句中涉及的差异成分的部分删除集合,并计算集合中每个元素之间的相似度,选择最大相似值。论文中使用了四种不同的方法来量化相似度,其中部分方法与之前提到的SIT方法有相似之处。 论文中的实验设计具有独特的特点。它首先提出问题并对解决方法进行探讨,然后围绕这四个问题设计实验并提供适当形式的实验数据。实验从多个角度论证了该方法的有效性,包括准确度、有效性、修复能力以及与人工方式的对比等。实验数据的呈现直观易懂。 TransRepair在处理阈值上与SIT方法不同。它通过机器小步遍历运算来获得统计上最优的阈值,并采用人工辅助和统计学分析的方式进行一致性判别,其阈值设定逻辑更具说服力。而SIT方法的阈值设定大多依靠经验,说服力和可操作性较低。 在TransRepair中,自动修复可以分为黑盒和灰盒两种方式。黑盒对应于Google Translate,由于该软件未开源,对于输入输出的相关参数了解有限,因此只能对输入和输出本身进行操作。灰盒对应于Transformer,它的源码和训练集可获取,因此可以对其输出结果的可能性进行把握,并在训练集和模型结构上进行修复操作。 TransRepair的优势在于对一致性问题的自动检测和修复。该方法具有高准确度、可行性和可复现性,这与其准确的实施方法以及对现有方法缺陷的考虑和补充密切相关。然而,该方法的效率较低,有效性仅限于一致性问题。 总体而言,论文 TransRepair 介绍了TransRepair方法作为一种有效的自动测试和改进机器翻译软件的方法,特别解决了一致性问题。论文详细解释了该方法,并提供了实验证据和比较分析。

九月 30, 2021

Structure-Invariant Testing for Machine Translation (SIT) 论文阅读总结

我之前阅读了 Structure-Invariant Testing for Machine Translation 这篇论文,它提出了一种关于机器翻译软件系统鲁棒性问题的检测方法。下面我将从几个方面详细介绍我对其中内容的理解。 主要内容 SIT是关于机器翻译软件系统鲁棒性问题的检测方法。这种方法利用了一个蜕变测试中的蜕变关系,即"结构不变性"。通过选择原始句子、生成相似句子、从翻译软件获取结果、进行成分解析并量化句子差异、根据设定的阈值筛选并发现问题,SIT可以高效地检测出机器翻译软件系统的鲁棒性问题。根据实验结果,SIT在19秒内可以处理2k+句子,并且对于Google/Bing Translate的准确度达到了70%。然而,仍有提升的空间,可能是由于阈值选择的原因。 对几个关键问题的理解 为什么机器翻译软件存在鲁棒性问题? 机器翻译软件系统的核心模块通常采用深度学习方法或技术。深度学习模型中每层的维度较高,导致训练模型在向量空间中对不同标签区域的界定可能模糊不清。当输入值接近边界时,稍微做出微小改变可能导致模型输出剧烈变化。 什么是结构不变性? 结构不变性是指经过对某种语言的句子进行一些特定且微小的词单位修改后,其语义和语法上的结构在转换为对应翻译后通常保持不变。结构不变性是研究机器翻译软件系统相关问题的经验和统计学意义上的一个切入点。 为什么要引入结构不变性? 引入结构不变性是为了进行蜕变测试,以探索机器翻译软件系统的鲁棒性问题。引入结构不变性的目的有两个:一是由于自然语言关系和变化复杂多样,难以得到一种通用的测试定理作为基准进行测试,因此通过控制变量,得到类似于经验或统计意义上正确的起点,展开测试研究;二是自然语言相关测试的测试用例难以人工构建,引入结构不变性可以方便地利用现有少量样本生成大量测试用例。 如何利用结构不变性生成语义与语法相似的语句? 在SIT中,使用了BERT模型来生成语义与语法相似的语句。SIT依赖于BERT的大型语料训练以及遮罩和双向反馈学习等技术,以抑制词语替换后整个句子的语义改变或不符合语法和使用习惯等问题。SIT通过在BERT之后增加一个轻量级的分类器来辅助生成预备替换词语的候选列表。 如何量化句子的差异以判断机器翻译软件系统是否存在鲁棒性问题? SIT使用了三种方法来量化句子差异:字符串差异分析、成分解析树分析和依存解析树分析。SIT直接对翻译软件的输出结果进行以上三种分析,并对它们的效果进行比较。然而,这三种句子差异分析方法都有一定的局限性,可以在进一步的工作中探索综合使用这三种方法进行判定的方式。 SIT具有哪些优势?有哪些不足? 在论文中,作者讨论了SIT的优势和不足。总的来说,SIT的优势在于其能够检测多种类型错误(未翻译、过度翻译、错误调整、逻辑不清)。然而,我认为其测试用例的生成方式、错误量化和检测方法相对粗糙,导致实验下准确性并不高。修复和阈值设定需要人工参与,这也是其另一个不足之处。 SIT可以有哪些应用? SIT主要应用于对运用了AI模型的机器翻译软件系统进行鲁棒性测试。通过SIT的自动检测和人工修复训练样本,机器翻译软件的鲁棒性可以得到提升。 总结 SIT是一种检测机器翻译软件系统鲁棒性问题的方法。通过选择原始句子、生成相似句子、获取翻译结果、进行成分解析和量化句子差异,SIT可以高效地检测机器翻译软件系统的鲁棒性问题。实验结果显示,SIT可以在19秒内处理2k+句子,并且对于Google/Bing Translate的准确度达到了70%。然而,仍有改进的空间,可能是由于阈值选择的原因。SIT利用BERT模型生成语义和语法相似的语句,并使用三种方法来量化句子差异。总体而言,SIT的优势在于能够检测多种类型的错误,但其测试用例生成方式和检测方法仍有改进空间。SIT主要应用于对应用AI模型的机器翻译软件系统进行鲁棒性测试,并通过自动检测和人工修复训练样本来提升鲁棒性。

九月 30, 2021

掌握C++右值引用的十大要点:如何正确处理纯右值和将亡值

最近由于工作需要,我阅读了很多关于C++右值方面的材料。在C++中,右值是一个非常重要的概念,它对于理解C++的内部机制和实现高效代码至关重要。本文将总结了10个关于右值的实践经验。 C++右值有两种:纯右值、将亡值。右值引用可以延长将亡值的生命周期,使得将亡值能够被正常使用,而不会被错误地释放。 右值引用的一个作用是延长右值的生命周期。右值引用可以延长将亡值的生命周期,使得将亡值能够被正常使用,而不会被错误地释放。 临时对象作为右值处理。这种对象往往会在一些表达式中自动创建,然后被立即使用。使用右值引用来绑定临时对象,可以让程序更高效地处理这些对象,避免了不必要的内存拷贝操作。 移动构造函数尽可绑定右值非常量。这是因为右值非常量可以被修改,而右值常量则不能。移动构造函数会破坏源对象,所以只有右值非常量才能被移动构造函数绑定。 对于一个右值对象,允许调用成员函数。这与左值对象类似。但需要注意的是,对于一个将亡值,如果其生命周期结束,那么调用其成员函数可能会导致程序出现未定义行为。 右值可以被修改(这也说明了其可以被破坏)。因此,在使用右值时需要谨慎处理,以避免因为修改了右值而导致程序出现问题。 右值不能当作左值使用,左值可以当作右值使用。这是因为左值具有实际地址,并且与右值有同样地表现。 常量左值引用可以绑定到右值。这种引用可以避免将右值对象修改的风险,同时还可以延长右值的生命周期,使其能够被正常使用。 返回右值引用的函数在几乎所有情况下是糟糕的。因为返回右值引用往往会导致右值的生命周期延长,从而使其可能被错误地使用。对于返回右值的函数,建议使用值返回的方式。 在大部分情况下return中使用是std::move并不会将事情变得更好,相反该操作会阻止编译器进行返回值优化。

九月 30, 2021

探究计算机中断处理:了解Intel x86处理器下的外部中断、异常和陷入

处理器中断处理是计算机体系架构中必须掌握的知识之一。在Intel的x86处理器下,中断可以分为外部中断、异常和陷入。外部中断来自硬件,是随机发生的,而异常则是处理器内部执行指令过程中检测到错误条件的结果。陷入则是由程序产生的,通常是由INT n、INTO等指令触发的。 在x86处理器中,中断处理程序负责处理中断,异常处理程序负责处理异常,而系统调用服务程序则负责处理陷入。这些处理程序可以位于内存空间的任何位置,并且可以有不同的特权级。Intel处理器使用中断门、陷阱门和任务门来定义处理程序的入口地址。其中,中断门和陷阱门是进入异常处理程序的门户。选择符和偏移量合起来定义了一个处理程序的入口地址。中断门进入处理程序时IF标志被清掉,而陷阱门进入处理程序时IF标志保持不变。 Intel处理器为每个中断和异常定义了一个中断向量号,并通过中断描述符表(IDT)建立中断向量号和门之间的对应关系。IDT可以驻留在线性地址空间的任何位置。Intel处理器专门提供了一个IDTR寄存器来记录IDT的基地址和界限信息。Intel处理器定义了256个中断向量号,其中0~31被处理器保留。 处理器中的异常可以分为故障类异常和终止类异常。故障类异常可以被更正,而终止类异常则是无法被处理器自行解决的严重错误。为了保证安全性,通过中断门或陷阱门只能向同级或更高特权级的代码段转移控制。通常情况下,处理程序定义在内核代码段中(0特权级代码段)。 在中断发生时,处理器会自动在栈顶压入一些参数,其中EFLAGS是中断或异常发生前的系统状态,SS:ESP是中断或者异常发生前用户堆栈的栈顶,CS:EIP是中断或者异常的返回地址。64位模式中,处理程序必须在64位代码段中,因而中断和陷阱门描述符被扩充到了16字节,其中偏移量被扩充到了64位;IDT找那个仅有新格式的门描述符;堆栈宽度变成了64位,而且当中断发生时,会无条件地压入栈指针(SS:RSP)当需要切换堆栈时SS被强制设置为NULL;新增了中断堆栈表(IST)机制,允许特定的中断或者异常指定专门的堆栈。

九月 30, 2021

Intel x86处理器内存保护 概要知识点

一旦处理器内存保护机制被启动,处理器就会对每一次内存访问进行保护性检查,以确保所有的访问都满足保护策略。保护检查和地址转换是并行进行的。 保护检查包含段级检查和页级检查。检查顺序是先段后页,检查依据是段描述符,页目录和页表,检查的基础是特权级。 特权级是Intel为实现保护而定义的特权编号。 段一级的检查包括段界限检查,段类型检查,特权级检查,长指针检查等。段一级检查的原则是: 低特权级的代码不能访问高特权级的数据 高特权级的代码可以访问低特权级的数据 代码只能使用与其特权级相同的堆栈,当特权级切换时,堆栈也要随之切换。 只能向具有相同特权级的非相容代码段转移控制(长JMP和长CALL) 可以向同等或者较高特权级的相容代码段转移控制,但不能向低特权级的相容代码段转移控制(长JMP和长CALL)。 即使调用门、中断门、陷阱门,也不能从高特权级向低特权级转移控制。 不允许使用长RET向高特权级转移控制。 页一级的检查包括特权级检查和读写检查。相关标志是页目录/页表项中的U/S和R/W位。U/S位0的页是超级页,为1是代表用户页。一般情况下,超级页中的代码可以访问所有页(不管R/W标志),用户页中的代码只能访问用户页。当CR0.WP被设置为1时,超级页中的代码也不能写只读用户页。 NXB为1的页只能用作数据页,试图执行数据页的指令会引起处理器异常。

九月 30, 2021