to be continued
to be continued
to be continued
to be continued
测试 ssh 是否安装
1 | rpm -qa | grep ssh |
若返回的结果中包括 SSH client 和 SSH server ,则不需要再安装 若需安装,通过以下命令
1 | yum install openssh-clients |
查看主机名称
1 | hostname |
然后
1 | ssh hostname(自己的主机名) |
设置免密码登陆
1 | cd ~/.ssh |
通过 ssh-keygen 命令来生成密钥对在.ssh 目录下(会有提示,回车即可)。
此命令执行后,会在~/.ssh 目录下生成私钥 id_rsa 和公钥 id_rsa.pub
1 | cat id_rsa.pub >> authorized_keys |
将 id_rsa.pub 中的公钥信息保存到 authorized_keys 中
1 | chmod 600 ./authorized_keys |
修改文件授权 此时用 ssh hostname 命令,无需密码即可直接登陆。
Visual Studio Code 安装
导入Microsoft GPG key:
1 | sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc |
官网下载vscode
1 | sudo gedit /etc/yum.repos.d/vscode.repo |
将下面的内容粘贴进去,并且启用 VS Code 源:
1 | [code] |
保存文件,并且关闭你的文本编辑器。
安装最新版本的 Visual Studio Code,输入:
1 | sudo dnf install |
升级visualstudio code
当一个新版本发布时,你可以通过你的桌面软件升级工具或者通过在终端运行下面的命令,来升级 Visual Studio Code:
1 | sudo dnf update |
.net core 安装
注册 Microsoft 密钥和源
1 | sudo rpm -Uvh https://packages.microsoft.com/config/centos/7/packages-microsoft-prod.rpm |
依次执行安装SDK和运行时。
1 | sudo yum install dotnet-sdk-3.1 |
打开扩展页面,搜索C#,安装C#支持;
打开sln文件所在文件夹,配置好launch.json文件,然后ctrl+f5就可以进行调试了。
我的第一个AI应用是参考实战:从0搭建完整 AI 开发环境写出第一个 AI 应用和AI应用开发实战 - 从零开始配置环境两篇文章进行的实施,故以该文做出相应的补充。
命令行执行python –version提示’python’ 不是内部或外部变量,在命令行中输入
1 | set PATH="C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64";%PATH% |
之后,再输入
1 | python --version |
输出版本为3.6.5
但是关闭命令行之后,再输入python –version时,依旧提示 ‘python’ 不是内部或外部变量。
故在计算机→属性右键→高级系统设置→环境变量→选择PATH→点击新建→将C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64添加→确定,之后再运行python –version,显示正常。
单独参考第一篇文章进行配置时,发现没有samples-for-ai\export\saved_model.pb这个路径。
原因是没有启动examples\tensorflow\TensorflowExamples.sln这个解决方案,将MNIST项目设置为启动项目并运行,则会有samples-for-ai\export\saved_model.pb这个文件了。
安装scipy-1.1.0和mxnet_cu90-1.2.0时,命令行一直无响应,解决方案是到scipy-1.1.0和mxnet-cu90 1.2.0下载指定的文件,然后通过pip3命令来执行安装,其余问题也可以通过类似命令来解决。
1 | pip3 install D:\scipy-1.1.0-cp36-none-win_amd64.whl |
通过下载的文件可以得知,文件较大,命令行无法及时完成下载,所以需要有一定的耐心等待
注意需要将C:\Program Files (x86)\Microsoft Visual Studio\Shared\Python36_64\Scripts添加到PATH变量中。
现在官网https://developer.nvidia.com/cudnn提供的cudnn版本是7.4.1,而微软示例代码中的cudnn版本是7.0.3,高版本的cudnn也会导致编译失败,需要找低版本的7.0.的cudnn替换到*C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v9.0\bin\cudnn64_7.dll
解决了这部分问题之后,能正常展示winform界面,运行结果如下:
该部分涉及到训练模型是否足够多的问题,该文不做深入的研究。
参考资料中提及的两篇文章都已经是做手写识别非常好的入门资料,该文仅仅是对这两篇文章做一个相应的补充,以作备忘。
另外我希望早日掌握以下技能
识别开心消消乐的游戏界面,然后通过能够确定执行的最佳下一步,达到这个目的,我觉得我对人工智能的了解和我的AI编程就进入了新的层次了。
#参考资料
最近在经手一个Winform项目,里面有个需求:TreeView控件选择不同的TreeNode时,需要展示不同的右键菜单。记录一下重构过程。
现将公司内部需求初始需求转换如下:
如果TreeView选中的TreeNode是国家,则右键菜单展示”添加省”,一个选项。
如果TreeView选中的TreeNode是省份,则右键菜单展示”添加市”,”删除”两个选项。
如果TreeView选中的TreeNode是城市,则右键菜单展示”添加区”,”删除”两个选项。
如果TreeView选中的TreeNode是区,则右键菜单展示,”删除”一个选项。
这部分的伪代码如下:
1 | var area = TreeView.SelectedNode.Tag as Area; // |
后来业务发展了,除了AreaType.国家这个选项,右键菜单都需要添加一个”打开地图”的右键菜单,且位于右键菜单的最上方。
重构之后的示例代码变成了如下:
1 | var area = TreeView.SelectedNode.Tag as Area; // |
这次需求变动,已经让我闻到了代码中的坏味道。增删改一个右键菜单需要修改好几处地方,删除右键菜单也是同理。
故需要对代码进行重构。
提取函数,伪代码如下
1 | private ContextMenuStrip menuStrip = new ContextMenuStrip(); //菜单转为私有属性 |
故调用处的实现代码变成了如下
1 | var area = TreeView.SelectedNode.Tag as Area; // |
若以后需求变更,打开地图需要改成打开百度地图,然后新增打开高德地图也只需要修改一行代码,并新增一行代码即可。
该重构过程运用的是提取函数和函数添加参数。
AddToolStripMenuItem函数只关心菜单项是否添加,而不关心菜单项添加的逻辑是什么。
重构之后,右键菜单的可能的菜单项也一目了然,每一个菜单项对应的添加条件也一目了然。若isAdd参数对应的表达式过长,则可以将该表达式封装成函数进行传递。
通过该重构提高了项目的可维护性,也算是一种成就。
最近在工作中的一次重构过程中运用到了委托,记录一下。
有一段示例代码如下
1 | public class ProjectAClass |
后来因为业务的不断发展,需要把ProjectB从整个解决方案中移除掉。
ProjectB_StaticClassB.DoSomething();需要替换成 ProjectC_StaticClassC.DoSomething();
但是项目ProjectC需要引用ProjectA,故不能直接进行引用,否则会造成项目之间的循环依赖。
ProjectAClass添加一个委托事件,CallMethod函数添加一个Dosometing dosometing的参数。
1 | public class ProjectAClass |
具体的调用代码处就变成了
1 | ProjectAClass.CallMethod(true,()=>{ProjectC_StaticClassC.DoSomething();}); |
若ProjectAClass.CallMethod方法多地方出现,然而没有办法一下修改到位。可以通过参数默认值的方式来实现修改。
1 | public static void CallMethod(bool isTrue, Dosometing dosometing=null) |
该方法可以避免原来的调用方法进行大面积的修改。
重构之后的代码ProjectAClass只需要判断条件是否满足,满足则dosometing,而不需要知道dosometing这个委托方法中具体细节。
最近试图重构一段现做现卖的祖传代码,结果改完之后,性能急速下降,下面给出示意代码的截图,以便提醒自己工作需要更加认真和细心。
Dictionary的执行时间竟然是Switch case的四倍以上?原因是啥?我们来看一下各个动物的构造函数
即生成Dictionary的每一个键值对的值的时候,都实例化了一个Animal的子类,每个子类的实例化都等待了十秒钟,总实例化就耗费了40秒钟。
先获取对象的type,然后通过Activator.CreateInstance(type)创建对象。
switch case转换成dictionary算得上是一种重构,起到了减少代码量,提高可维护性的效果。
这次我的失误也算是明白了一个深刻的道理,所有的重构需要建立在完整的测试机制的前提下,否则可能会造成严重的损失。
最后一句箴言如无必要,勿动祖传代码