读书笔记-程序员的自我修养(四)

链接的接口:符号

  • 普及 : 链接的过程 实际上 就是 相互拼合 的过程,即目标文件中的(函数和变量) 地址引用符号 是拼合剂

  • 普及 : 我们将函数和变量统称为 符号(Symbol),函数名货变量名就是 符号名(Symbol Name)

  • 普及:符号统一存放在目标文件的 符号表(Symbol Table) 中,每个定义的符号有一个对应的 符号值(Symbol Value)

  • 主要关注的 链接对象 有:1. 定义在本目标文件的 全局符号,可以被其他目标文件引用 2. 在本目标文件中引用的 全局符号,却没有定义在本目标文件中,这一般叫做外部符号

  • ELF符号表 [.symtab] 结构详解

    • 逻辑结构Elf32_Sym 结构体 对应一个符号,符号表是一个 数组,其中

      • 符号类型和绑定信息(st_info):类型:局部,全局,弱引用,绑定信息:位置,对象,函数,段,文件

      • 符号所在段(st_shndx):符号定义在本目标文件中,即对应段的下表,如不在,则跟 深入静态链接COMMON块 有关

      • 符号值(st_value):依据符号所在段不同,值也会有不同的类型

    • 特殊符号:有些符号并没有在你的程序中定义,但是你可以直接声明并且引用它,称之为特殊符号,比如:__executable_start__etext__edata__end 这些符号当且仅在 链接过程中控制

    • 符号的管理

      • 修饰与函数签名:为了防止程序中的符号冲突,先后发明了 名称空间(namespace)符号修饰(Name Decoration) 等机制,以 函数签名(Function Signature) 作为符号的唯一标识,避免多个符号冲突,链接器无法识别

      • exten “C”:C++中用来声明或定义一个 C 符号的语法,配合 __cplusplus 来定义变量,这样就可以在 C 或 C++ 中正确的定义符号,使得链接器能够找到目标符号进行链接

      • 弱符号和强符号: 都是针对定义而言的,编译器默认函数和初始化了的全局变量为 强符号(Strong Symbol),未初始化的全局变量为 弱符号(Weak Symbol),链接器会在链接的时候,遵循3种选择规则,来选择强符号还是弱符号:1. 相同变量强弱都定义,选择强,2. 不允许强符号被多次定义,3. 都是弱,选择占用空间最大的

      • 弱引用和强引用:当链接器在引用决议时未发现符号就报错时,就是强引用,相反,不报错的就是弱引用。之所以有弱引用的存在,是为了使得程序可以在未发现符号的时候,使用原来库的定义,即便去掉了某个模块,也不会报错,方便解耦

  • 调式信息 DWARF(Debug With Arbitrary Record Format)

    • 使用命令 strip 来去掉 ELF 文件中的调试信息, 大幅度减少文件大小
如需转载,请注明出处

读书笔记-程序员的自我修养(三)

目标文件(ELF) 详解

  • 目标文件 里有什么?

    • 目标文件的格式,从 结构 上讲,它是已经 编译后的可执行文件,只是还 没有经过链接 的过程,其中可能有些符号或有些地址还没有被 调整,本身就是按照可执行文件格式存储的

    • 普及 : 可执行文件格式(Executable) 主要是 Windows 下的 PE(Portable Executable)Linux 下的 ELF(Executable Linkable Format),都隶属于 COFF(Common file format) 的变种

    • 普及 : 动态链接库(DLL,Dynamic Linking Library) 即(Windows 上的 .dll 和 Linux 上 .so),静态链接库(Static Linking Library) 即(Windows 上的 .lib 和 Linux 上的 .a

    • 普及 : ELF 格式的文件归为四类:可重定位文件(Relocatable File)可执行文件(Executable File)共享目标文件(Shared Object File)核心转储文件(Coredump File),可以用 file 命令查看

    • 概述 ELF 剖析 目标文件是什么样的 ?

      • 包含的内容: 机器指令代码、数据、符号表、调试信息、字符串

      • 按照信息的不同属性,存储的单位:节(Section)段(Segment)

    • 结构详解:使用 binutils 的工具 objdump 可以查看 .o 文件内部的结构

      • 工具命令

        • 查看主要段的基本信息:objdump -h SimpleSection.o

        • 查看各个段的信息:readelf -S SimpleSection.o

        • 查看ELF文件的长度:size SimpleSection.o

        • 查看段的内容:objdump -s -d SimpleSection.o

        • 查看ELF文件头:readelf -h SimpleSection.o

      • 逻辑划分

        • 代码段[ .text ]:机器指令代码(一般是执行语句

        • 数据段和只读数据段[ .data 和 .rodata ]已初始化 的全局变量和局部静态变量

        • BSS段 [ .bss ]未初始化 的全局变量和局部静态变量,只是预留位置而已,值得注意的是:即便初始化为 0,也会放到 bss 中,因为未初始化的都是 0

        • 其他段:列举几个:.comment 存放编译器版本信息.debug 存放调试信息.dynamic 存放动态链接信息.hash 存放哈希表.symtab 存放符号表.plt/.got 动态连接的跳转表和全局入口表 等等

        • 自定义段:GCC提供了一个扩展机制,是的程序员可以制定变量所处的段:attribute((section(“name”))) int global = 42 ,global变量即会存放于 name 作为段名的段中

      • 物理划分

        • 文件头(File Header):描述文件 属性,其中定义了 ELF魔数(e_ident)、文件机器字节长度、数据存储方式、版本、运行平台(e_machine)、ABI版本、ELF重定位类型(e_type)、硬件平台、硬件平台版本、入口地址、程序头入口地址、段表的位置和长度(e_shoff)、段的数量 ,常定义于:/usr/include/elf.h 中,根据版本分为:Elf32_EhdrElf64_Ehdr

        • 段表(Section Table):描述包含的所有段信息,比如每个段名、段的长度、在文件中的偏移、读写权限及段的其他属性。每个段的结构是由 Elf32_Shdr 的结构体组成,对于编译器和链接器来说,主要决定段的属性是类型(sh_type)(12种)和标志位(sh_flags)(读写可分配),如果段的类型是与连接相关的,那么段的链接信息就是控制如此的(sh_linksh_info

          • 重定位表sh_type = SHT_RELA[.rel]:重定位代码段和数据段中那些对绝对地址的引用的位置

          • 字符串表sh_type = SHT_STRTAB[.symtab]:ELF文件中用到的很多字符串,比如段名和变量名等,比较聪明的做法是,具体字符串存放在字符串表中,段中直接引用 偏移量 即可

如需转载,请注明出处

读书笔记-程序员的自我修养(二)

编译和链接

  • 编译和链接: 通常将编译和链接合并到一起的过程称为 构建(Build),可以分解成以下 4 个步骤

    • 预编译(Propressing)

      源文件 和 头文件 被预编译器预编译成一个 .i 或者 .ii(cpp)的文件

      期间主要处理那些源代码文件中的以 # 开始的预编译命令,比如 #include,#define

      经过预编译后的 .i 文件 不包含任何宏定义并且引用的文件已经全部被插入到 .i 文件中删除了所有注释处理了所有条件预编译指令(#if,#ifdef,#elif,#else,#endif)保留了所有#progma编译器命令

      为此,当需要判断 宏定义包含的头文件是否正确时,可以查看预编译后的文件来确定问题(gcc -E hello.c -o hello.i)

    • 编译(Compilation)

      编译过程就是把预编译完的文件(.i / .ii)进行一些列 词法分析,语法分析,语义分析及优化 后生成相应的 汇编代码文件(.s)

      如今GCC已经把预编译和编译两个步骤合二为一了,使用叫做 cc1 的程序来完成(gcc -S hello.c -o hello.s)

      实际 gcc 这个命令只是这些后台程序的 包装,它会根据不同的参数要求去调用预编译编译程序 cc1,汇编器 as,链接器 Id

    • 汇编(Assembly)

      汇编过程只是根据汇编指令和机器指令的对照表一一翻译就可以了(gcc -c hello.s -o hello.o),生成 目标文件(Object File)

    • 链接(Linking)

      目标文件 到 可执行文件,需要链接许多内容(静态链接和动态链接),后文会详细介绍

      ld -static crt1.o crti.o crtbeginT.o hello.o –start-group -lgcc -lgcc_eh -lc -end-group crtend.o crtn.o

  • 编译的过程: 编译器 从源代码(Source Code)到最终目标代码(Final Target Code)过程,做了以下 6 个步骤

    • 词法分析

      通过扫描器,运用一种类似于 有限状态机(Final State Machine) 的算法,将源代码的字符序列分割成一系列的 记号(Token)

      词法分析产生的记号一般分为以下几类:关键字、标识符、字面量(包含数字、字符串等)和 特殊符号(如加号、等号),并将它们放到对应的

      lex 程序可以实现词法分析,支持自定义词法规则

    • 语法分析

      通过 语法分析器(Grammar Parser),采用 上下文无关语法(Context-free Grammar) 的分析手段,将由扫描器产生的记号生成 语法树(Syntax Tree)

      语法树就是以 表达式(Expression) 为节点的树,如果出现了表达式不合法,编译器就会报告语法分析阶段的错误

      yacc 程序可以实现语法分析,构建一颗语法树,支持自定义语法规则

    • 语义分析

      语义分析器(Semantic Analyzer) 只对表达式完成语法层面的分析,不关心是否真正有意义,通常可以分为以下两种

      静态语义(Static Semantic) 通常包括声明和类型的匹配,类型的转换,最简单的例子:赋值类型转换

      动态语义(Dynamic Semantic) 一般指在运行期出现的语义相关问题,比如将0作为除数

      经过语义分析之后,整个语法树的表达式都被标识了 类型,如果有些类型需要做隐式转换,语义分析程序会在语法树中 插入 相应的转换节点

    • 中间语言生成

      现代的编译器都包含 源码级优化器(Source Code Optimizer),在源代码级别有一个优化过程(比如能在编译期间确定表达式值)

      直接在语法树上做优化比较困难,所以将整个语法树转换成 中间代码(Intermediate Code),比较常见的有:三地址码(Three-address Code)P-代码(P-Code)

      跨平台原理:中间代码使得编译器可以被分为前端和后端。编译器前端负责产生机器无关的中间代码,编译器后端将中间代码转换成目标机器代码。这样对于一些可以跨平台的编译器而言,他们可以针对不同的平台使用同一个前端和针对不同机器平台的数个后端

    • 目标代码生成与优化

      源代码级优化器产出的结果:中间代码,标志着下面的过程都属于编译器后端,包括 代码生成器(Code Generator)目标代码优化器(Target Code Optimizer)

      代码生成器(Code Generator) 主要是将中间代码转换成目标机器代码,依赖于目标机器的环境

      目标代码优化器(Target Code Optimizer) 主要针对目标代码,在合适的寻址方式,使用位移来代替乘法运算,删除多余的指令等方面,进行优化,涉及到的技术比如: 基址比例变址寻址(Base Index Scale Addressing)

      问题:此时,目标机器代码(汇编)已经生成,但是目标代码中的变量地址还没有确定,这个地址可以是本程序内定义的,也可以是其他程序模块中的,那么运行时该如何寻址?在介绍链接器之前,先说明下链接器的作用对象:目标文件都包括什么

如需转载,请注明出处

读书笔记-程序员的自我修养(一)

计算机基础知识回顾

  • SMP(Symmetrical Multi-Processing)对称多处理器:每个CPU在系统中所处的地位和所发挥的功能都是一样的。通常情况下的程序不可能分解成多个不相干的子问题,除非商用的计算环境(充分发挥每个CPU的能力),所以多核处理器(Mutli-core Processor)和 SMP 通常是一个概念。

  • 层次结构,计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决。开发工具与应用程序属于同一个层次,因为它们都使用运行库提供的 应用程序编程接口(Application Programming Interface)。运行库使用操作系统提供的 系统调用接口(System call Interface),通常以软件中断方式实现提供。操作系统内核层使用硬件层提供的 硬件规格(Hardware Specification)

  • 操作系统的一个功能是提供抽象的接口,另一个主要功能是管理硬件资源(CPU,存储器(内存和磁盘)和 I/O 设备)

    • 不要让CPU打盹:早期的CPU是 单一 服务式,简直浪费,后来出现了分时系统(Time-Sharing System),以 协作 的方式主动让闲CPU,供其他程序使用,再到现在,操作系统接管了所有硬件资源,本身运行在一个受硬件保护的级别,所有程序都以进程的方式运转,并且允许 抢占式 的CPU分配方式

    • 设备驱动(Device Driver),操作系统 将硬件逐渐抽象成一些列的概念。比如:UNIX 中硬件设备的访问形式跟访问普通的文件形式一样,Windows 中,图像硬件被抽象成 GDI,声音和多媒体设备被抽象成 DirectX 对象等,向上提供统一的接口供程序使用,设备驱动完成向下对硬件的适配

    • I/O 设备:内存和磁盘的读取和写入是通过 I/O 端口寄存器来实现的,提供读取和写入的地址,来完成磁盘数据操作

      即操作系统以进程概念,使得每个进程从逻辑上来看都是独占计算机资源,实质上操作系统以抢占式的 CPU 策略,I/O 抽象模型的方式来管理这些资源

  • 操作系统是如何管理内存的

    • 解决的问题:如何将计算机 有限 的物理内存分配给 多个 程序使用

    • 直接分配物理内存的弊端:地址空间不隔离(程序直接访问物理内存),内存使用效率低(缺乏有效的内存管理机制,使得频繁换入换出数据,内存的使用分配以程序为单位(粒度太大)),程序运行的地址不固定(程序每次装入内存执行时,数据和指令跳转涉及到重定位问题)

    • 解决方法: 增加中间层来 隔离,把程序给出的地址看作是一种 虚拟地址(Virtual Address),通过某些映射方法,保证任意一个程序所能够访问的物理内存区域跟另外一个程序相互不重叠,以达到地址空间隔离的效果

    • 分段(Segmentation):段映射,以程序所使用的的内存为单位,从虚拟地址映射到物理地址,映射结果唯一,解决了隔离和程序地址不固定的问题

    • 分页(Paging):页分割,把常用的数据和代码页装载到内存中,把不常用的代码和数据保存在磁盘里,当用到的时候再取出来。若用到的页不在内存中,操作系统会受到页错误(Page Fault),然后将需要的页装载到内存中。硬件级别:MMU(Memory Management Unit)用来支持虚拟地址到物理地址的转换,已集成到CPU内部

  • 程序执行流最小单元:线程(Thread),又称为轻量级进程(Lightweight Process,LWP)

    • 基础概念

      线程私有(局部变量,函数的参数,TLS数据),线程之间共享(全局变量,堆数据,函数里的静态变量,程序代码,打开的文件,这些就是进程所有的东西)

      调度(线程数>处理器时(或者单处理器应对多线程时),会模拟出来一种并发的状态,即切换不同的线程行为,称之为线程调度

      至少三种状态:运行,就绪,等待,以时间片的改变作为区分

      调度算法:优先级调度(Priority Schedule),轮转法(Round Robin),也区分出 IO密集型线程(IO Bound Thread)CPU密集型线程(CPU Bound Thread),IO 总比 CPU 能获得更高的优先级

      为了防止 饿死(Starvation) 现象: 用户指定优先级/根据进入等待状态的频繁程序提升或降低优先级/长时间得不到执行而被提升优先级,也出现了 可抢占式线程(Preemption)

    • 线程安全

      竞争与原子操作:多个线程同时访问一个共享数据,为此引出 原子性(Atomic),但原子性操作只适用于简单的操作,更复杂的数据结构访问,通常用 的手段

      同步与锁同步(Synchronization) 是一种机制:保证线程访问数据的原子性。锁(Lock) 是一种手段,每个线程在访问数据或资源之前,首先试图 获取(Accquire) 锁,并在访问结束之后 释放(Release)

      锁的演进二元信号量(Binary Semaphore),只允许一个线程独占,其状态有两个:占用 和 非占用,可以由一个线程获取,另一个线程释放;多元信号量(N Semaphore),允许 N 个线程并发访问共享资源;互斥量(Mutex),类似于二元信号量,但谁获得谁负责释放;临界区(Critical Section):不同于之前的信号量,互斥量(作用域为进程内的所有线程),临界区的作用范围仅限于本线程,其他线程无法获取临界区的锁,因此也就无法访问;条件变量(Condition Variable),使用条件变量可以让许多线程一起等待某个事件的发生,当事件发生时,所有线程可以一起恢复执行

      读写锁(Read-Write Lock):三种状态分别是,自由(Free),共享(Shared)和独占(Exclusive),当处于自由状态时,试图以任何一种方式获取锁都能成功,并将锁至于对应的状态。如果锁处于共享状态,其他线程以共享的方式获取锁仍会成功(读),此时这个锁分配给了多个线程。如果其他线程试图以独占的方式获取已经处于共享状态的锁,那么他将必须等在锁被所有的线程释放后,才能将锁的状态置成独占(写)

      可重入(Reentrant):即幂等性的函数,可以称为可重入函数

      过度优化:使用 volatile 关键字,解决 1. 阻止编译器为了提高速度将一个变量缓存到寄存器内而不写回,2. 阻止编译器调整操作 volatile 变量的质量顺序,但还是无法阻止CPU动态调度换序

    • 线程内部三种模型

      多线程库的实现方式:对用户来说如果有三个线程在同时执行(用户态线程(User Thread)),对内核来说很可能只有一个线程(内核线程(Kernel Thread)),下面提及的模型都是 UT:KT

      一对一模型:真正意义上的并发调度,缺点是受内核线程数量限制,内核线程上下文切换调度开销较大,使得用户线程执行效率低下

      多对一模型:高效的上下文切换和几乎无限制的线程数量,缺点是一个用户线程阻塞了,那么所有线程都将无法执行

      多对多模型:多个用户线程映射到多个内核线程,切换方便且避免了一个阻塞全局的情况

如需转载,请注明出处

SonarQube - 安装使用调试

最近研究了下SonarQube工程,发现其如此强大,可以用于质量保证的任何阶段,刚好由于项目需要建立一个完整的基础质量保证”设施”,所以快马加鞭,赶紧安装部署了下,这里总结一些问题和经历

安装与运行

SonarQube分为两个部分:Server 和 Scanner,其中

Server:https://www.sonarqube.org/downloads/

Scanner:https://docs.sonarqube.org/display/SCAN/Analyzing+Source+Code

其余安装环境就不赘述了:MySQL 和 Java

参考这篇文章:http://blog.csdn.net/hunterno4/article/details/11687269

问题
  1. 在配置了 sonar-project.properties 之后,运行 sonar-scanner 报如下错误:
1
org.sonarqube.ws.client.HttpException: Error 500 on http://localhost:9000/api/ce/submit?projectKey=xxx&projectName=yyy : {"errors":[{"msg":"An error has occurred. Please contact your administrator."}]}

解决方法如下:

  • 查看 /logs/web.log 得知详细原因是:Packet for query is too large (6082109 > 4194304). You can change this value on the server by setting the max_allowed_packet' variable

  • 修改 MySQL 的配置,用命令行登入执行:show VARIABLES like '%max_allowed_packet%'; SET GLOBAL max_allowed_packet=268435456;

  • 重启 MySQL 和 Sonar-Server 服务

尝试分析一个工程,发现已经成功打通的整套流程,SonarQube的高集成特性以及丰富的插件,可以根据实际项目需要丰富的定制。接下来我会围绕它打造一个后期的基础质量保障“设施”,首先来看看如何调试自定义扩展插件

扩展插件

官方给出了扩展插件的示例:https://github.com/SonarSource/sonar-custom-plugin-example,下载下来导入工程,可以清晰的看到

  • org.sonarsource.plugins.example, 插件入口目录,相当于 Main 函数的作用

  • org.sonarsource.plugins.example.hooks ,工具钩子,可以在各个阶段自定义一些需要的操作,继承自:PostJob/PostProjectAnalysisTask

  • org.sonarsource.plugins.example.languages ,自定义语言支持,继承自:AbstractLanguage

  • org.sonarsource.plugins.example.measures, 自定义质量阀的衡量标准,继承自:Metrics

  • org.sonarsource.plugins.example.rules,自定义代码规则,继承自:Sensor

  • org.sonarsource.plugins.example.settings,自定义设置,继承自:Sensor

  • org.sonarsource.plugins.example.web,自定义网页显示部分,继承自:web.xxx

以上这些自定义的各个模块,分别作用于 SonarQube 的基本流程里,即:

1
2
3
4
5
6
7
8
9
10
11
12
13
public void execute(Project project) {  
...
sensorsExecutor.execute(sensorContext);
decoratorsExecutor.execute();
persistenceManager.dump();
persistenceManager.setDelayedMode(false);
if (project.isRoot()) {
if (updateStatusJob != null) {
updateStatusJob.execute();
}
postJobsExecutor.execute(sensorContext);
}
...

首先,初始化整个分析过程,包括加载所有的分析任务,其次,分析这些任务(Sensor和Decorator),并且把结果存储到数据库,最后,执行postjob,做相关的一些分析,因此需要根据插件作用需要,可以自行在各个阶段模块中进行扩展

调试

官方提供了调试方法:https://docs.sonarqube.org/display/DEV/Build+Plugin#BuildPlugin-Debug

这里总结下步骤,避免踩坑:

  1. 在 conf/sonar.properties 中设置sonar.web.javaAdditionalOpts=-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8001

  2. 将插件打包部署到 extensions/plugins 中

  3. 如果你安装了SonarQube服务,请先关掉,然后用 bin/StartSonar启动,可以检查是否出现:Listening for transport dt_socket at address: 8001

  4. 在IDE中新建远程调试,打上断点,启动调试,打开localhost:8001,此时IDE会进到debug模式

好了,学会了调试,接下来就可以进一步打造我们的插件了

如需转载,请注明出处

疑难杂症-解决MSYS2在Window上越用越慢的方法

最近折腾电脑真是费了不少脑细胞,谁让咱用着 window 还操着 linux 的心呢,事情起因是因为习惯了在 cmd 中使用 linux 的命令,但是 cygwin 新版的界面真是不该恭维的美感,所以就把 git/bin 目录加到了 PATH 中,这样一举两得,谁知 git for windows 现在用的是 MSYS2 的环境,运行个 ls,grep要等上 1 分钟才能出结果,于是乎忍无可忍,终于在今天解决了这个问题

问题描述

解决 MSYS2 在使用过程中越用越慢的问题

解决方法
1
2
3
4
5
6
7
8
9
10
11
12

mkpasswd -l -c > /etc/passwd

mkgroup -l -c > /etc/group

# 如果是window系统就在 git/etc 下面执行

# 修改 /etc/nsswitch.conf,其中

passwd: files #db

group: files #db
参考

终于,系统恢复了丝滑版的顺畅~

如需转载,请注明出处

机器学习

分类

机器学习 有监督学习(Supervised) 无监督学习(UnSupervised)
理解 有一组称之为”正确”的数据提供给算法,用于监督每次的训练成果 从数据集中发掘出规律,从而将数据进行某种程度划分
问题
  • 回归预测(Regression Predict)
  • 特征分类(Feature Classification)
  • 聚类(Cluster)
  • 线性回归

    • 模型表示

      • 关键词:训练集(Training Set)| 学习算法(Learning Algorithm)| 假说(Hypothesis)

      • 通过学习算法找到某种假说使得训练集的数据呈现该假说规律,即:H maps from TraningSet

      • 如何检测假说的效果,使用成本函数(cost function or loss function),有时候也叫损失函数,通常来说,假说越准确,越接近真实,其值就越小。成本函数的出现通常伴随着目标,即 When cost function defined,the goal has appearanced

        线性回归通常使用的成本函数和目标为:

      • 学习算法:

        1. 梯度下降法(Gradient Descent)

          • 梯度下降法的缺点包括:1)靠近极小值时速度减慢,2)直线搜索可能会产生一些问题,3)可能会“之字型”地下降。
      • 如何调节机器学习的结果:

        1. 特征缩放(Feature Scaling)

          解释:在运用一些机器学习算法的时候不可避免地要对数据进行特征缩放(feature scaling),比如:在随机梯度下降(stochastic gradient descent)算法中,特征缩放有时能提高算法的收敛速度

    如需转载,请注明出处

    Tensorflow学习-环境搭建

    耳闻 Tensorflow 已经很久了,一直没有时间亲自动手体验,忙里抽闲把环境都配置好了,以此来记录学习的开始

    环境配置

    • VMware Player 12 (免费)

    • Ubuntu 16.04 LTS

    • Anaconda 4.3.0

    • Tensorflow Library

    • Sublime Text + Plugin

    • 翻墙

    基于 Anaconda 搭建 Tensorflow 的环境非常方便,避免GFW的干扰,提供一个环境网站:https://mirrors.tuna.tsinghua.edu.cn/

    创建虚拟机的步骤就不赘述了,用过VMware的很简单,记得安装VMware Tools ,这个很关键

    下载好 Anaconda 之后,有 2 和 3 两个版本,分别对应 python 2.7 和 python 3.5,chmod 之后就可以一路安装了,记得添加到PATH中,这样默认的python环境就升级了

    打开终端,输入以下命令

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ conda create -n tensorflow python=2.7

    $ source activate tensorflow

    (tensorflow)$ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.12.1-cp27-none-linux_x86_64.whl

    (tensorflow)$ pip install --ignore-installed --upgrade $TF_BINARY_URL

    $ source deactivate

    下载安装 Sublime Text,安装 Package Control 之后依次添加以下插件:

    • Anaconda

    其中 Anaconda 配置参考:http://www.cnblogs.com/nx520zj/p/5787393.html

    去掉代码检测提示框:https://segmentfault.com/q/1010000002415020

    这样,Tensorflow 的环境就搭建成功了,总体来说还是非常方便的,保证一个通畅的网络,翻墙很关键!

    试运行一个线性拟合 Demo 点此下载:line.py

    得到如下输出:

    如需转载,请注明出处

    Tensorflow学习-神经网络

    学校里人工智能的课程,都会以神经网络作为入门,因此,也以神经网络(NNs)作为回顾和新的学习开始

    首先来回忆几个概念

    神经元

    神经元是神经网络中的一个基本单元,作用是:求得输入向量与权向量的内积后,经一个非线性传递函数得到一个标量结果

    这个非线性传递函数也称之为:激励函数(ReLu)

    因此对于一个基本单位神经元,他的目的就是汇合其所有的输入(外界刺激),与该神经元上的所有权值相乘(神经敏感度),通过激励(激励函数)产生相应的反应(标量结果)

    神经网络

    神经网络由多个神经元组成,通过层的概念划分,可以分为输入层,隐含层和输出层。

    神经元之间的信息传递强度,是通过权向量来定义的,结合一定的训练学习算法,权向量会不断的进行调整,即学习算法(learning algorithm)会不断的调整神经元的敏感度,让神经元在训练过程中产生不同的刺激反应

    同时,神经网络结合学习算法,依赖于大量的数据来训练,每一次的训练都需要有一个评估方法,称之为成本函数(cost function),用来定量评估根据特定输入值, 计算出来的输出结果,离正确值有多远,结果有多靠谱,换句话说就是神经网络的反应与预期是否一致

    为此,一个神经网络的基本可变关键因素就是:网络拓扑设计(输入层,隐含层和输出层的关系),学习算法(以何种方式来调整神经元敏感度),激励函数(神经元对外界刺激做出如何的反应),成本函数(衡量评估神经网络距离预期的差距),当然,随着深入的研究,神经网络还有许多高级可变因素,比如,dropout等

    成果
    • 最常用的两个激活函数:Sigmoid系(Logistic-Sigmoid、Tanh-Sigmoid)
    实战

    来源:维基百科-人工神经网络 斯坦福大学UFLDL-神经网络

    如需转载,请注明出处

    2017书单

    思想类

    • 《世界很大,幸好有你》 杨澜

    • 《局座的悄悄话》 张召忠

    • 《有味》 汪涵

    • 《道德经》 老子

    • 《你从未真正拼过》 Linkedin

    小说类

    • 《摆渡人》 克莱儿麦克福尔

    • 《殉罪者》 雷米

    技术类

    • 《Tensorflow》

    • 《程序员的自我修养》 潘爱民

    • 《利用Python进行数据分析》 Wes McKinney

    • 《Spring Boot 实战》 Craig Walls

    如需转载,请注明出处