我眼中规范的开发流程

我眼中规范的开发流程 基于自建SVN的信息存储 存放开发文档 存放测试用例 存放三方对接文档 存放同事的学习记录与分享 存放会议纪要 基于git的开发流程 代码全部托管于git服务上 完善的分支规范,区分开发,测试,生产分支 基于gitflow的开发流程,区分feature,bugfix,hotfix等分支创建规则 完善的测试流程 产品出文档测试即开始编写测试用例 测试版本开发完成开始测试 使用bugout进行记录与跟踪bug 开发处理bug,在bugout上提交 测试再次测试直到通过 基于持续构建工具的构建流程 使用jenkin持续构建,单元测试,Sonar代码分析 每个项目至少3个分支,dev,master,release分支 测试在dev分支,预发布在master分支,线上使用release分支 dev分支自动提交构建 平台架构 分布式的微服务架构 保证单机宕机对整体服务没有影响,做到自动切换主备 统一开发环境与工具 后端开发统一Jetbrains全家桶 接口调试使用Postman 文档使用showdoc 代码管理使用git 统一使用邮件沟通 致谢:

July 22, 2017 · 1 min · 32 words · Jimmy

Spring Cloud 之actuator模块简介

Spring Cloud 之actuator模块简介 此模块提供监控与采集功能,通过在pom中引用此依赖,可以方便地使用其功能 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> 原生端点 应用配置类:获取应用程序中加载的应用配置,环境变量,自动化配置报告等与SpringBoot应用密切相关的配置类信息 度量指标类:获取应用程序运行过程中用户监控的度量指标,比如内存信息,线程池信息,HTTP请求统计等 操作控制类:提供了对应用的关闭操作类功能 应用配置类 /autoconfig:该端点用来获取应用的自动化配置报告.包括条件匹配成功以及不成功的配置 positiveMatches中返回是条件匹配成功的自动化配置 negativeMatches中返回的是条件匹配不成功的自动化配置 /beans:该端点用来获取应用上下文中创建的所有Bean [ { "context":"application", "parent":null, "beans":[ { "bean":"helloApplication", "aliases":[ ], "scope":"singleton", "type":"com.jimersylee.hello.HelloApplication$$EnhancerBySpringCGLIB$$d3ebe421", "resource":"null", "dependencies":[ ] }, 每个Bean中都包含了下面这些信息 bean:Bean的名称 scope:Bean的作用域 type:Bean的Java类型 resource:class文件的具体路径 dependencies:依赖的Bean名称 /configprops:该端点用来获取应用中配置的属性信息报告,可以通过使用endpoints.configprops.enabled=false来关闭 env:该端点与/configprops不同,它用来获取应用所有可用的环境属性报告 { "profiles":[ ], "server.ports":{ "local.server.port":8080 }, "servletContextInitParams":{ }, "systemProperties":{ "java.runtime.name":"Java(TM) SE Runtime Environment", "awt.useSystemAAFontSettings":"gasp", "sun.boot.library.path":"/opt/jdk1.8.0_144/jre/lib/amd64", "java.vm.version":"25.144-b01", "maven.multiModuleProjectDirectory":"/home/jimersylee/projects/java/spring-cloud-action/hello", ... /mappings:该端点用来返回所有Spring MVC的控制器映射关系报告. ...

April 29, 2017 · 1 min · 179 words · Jimmy

Spring Cloud 入门

Spring Cloud 入门 Spring Cloud Config:配置管理工具 Spring Cloud Netflix:核心组件 Eureka:服务治理组件 Hystrix:容错管理组件 Ribbon:客户端负载均衡的服务调用组件 Feign:基于Ribbon和Hystrix的生命是服务调用组件 Zuul:网关组件 外部化配置组件 Spring Cloud Bus:事件,消息总线 Spring Cloud Cluster:针对Zookeeper,Redis,Hazelcast,Consul的选举算法和通用状态模式的实现 Spring Cloud CloudFoundry:与Pivatal Cloudfoundy的整合支持 Spring Cloud Consul:服务发现与配置管理工具 Spring Cloud Stream:通过Redis,RabbitMQ和Kafka实现的消费微服务,可以通过简单的声明式模型来发送和接收消息 Spring Cloud AWS:用于简化整合Amazon Web Service的组件 Spring Cloud Security:安全工具包,提供在Zuul代理中对OAuth2客户端请求的中继器 Spring Cloud Sleuth:Spring Cloud的应用分布式跟踪系统,可以完美整合Zipkin Spring Cloud Zookeeper:基于Zookeeper的服务发现与配置管理组件 Spring Cloud Starters:Spring Cloud的基础组件,它是基于Spring Boot风格项目的基础依赖模块 Spring Cloud CLI:用于在Groovy中快速创建Spring Cloud应用的Spring Boot CLI的插件

April 28, 2017 · 1 min · 57 words · Jimmy

<深入理解Java虚拟机>学习笔记-第三章

<深入理解Java虚拟机>学习笔记-第三章 项目地址: http://github.com/jimersylee/javaStudy 3.1概述 垃圾收集(Garbage Collection,GC),大部分人都把这项技术当做Java语言的伴生产物,事实上,1960年诞生于MIT的Lisp蚕食第一门真正使用内存动态分配和垃圾收集技术的语言 GC的3件事情 那些内存需要回收 什么时候回收 如何回收 目前GC的技术已经相当成熟,为什么我们要了解 当需要排查各种内存溢出,内存泄露问题时 当垃圾收集成为系统达到更高并发量瓶颈时 3.2对象已死吗 Java堆中存在对象实例,垃圾收集器在对堆进行回收前,第一件事就是要确定哪些对象还"活着",哪些已经"死去" 3.2.1 引用计数算法 给对象中添加一个引用计数器:每当有一个地方引用它时,计数器加1;当引用失效时,计数器减1;任何时刻计数器为0的对象就是不可能再被使用的 引用计数算法(Reference Counting)的实现简单,判定效率也高,例如FlashPlayer,Python都使用引用计数算法了内存管理,但是Java虚拟机中没有选用引用计数算法来管理内存,其实最重要的原因是它很难解决对象之间相互循环引用的问题 testGC()方法,虽然两个对象已经不可能被访问,但是因为互相引用着,导致他们计数器都不为0,于是引用计数算法无法通知GC收集器来回收它们 GC日志中包含了6747K->416K(51200K),意味着虚拟机并没有因为这两个对象互相引用就不回收它们,这也从侧面说明虚拟机并不是通过引用计数算法来判断对象是否是存活的 3.2.2 可达性分析算法 在主流的商用程序语言(Java,C#,甚至古老的Lisp)的主流实现中,都是通过可达性分析(Reachability Analysis)来判定对象是否存活的.这个算法的基本思路就是通过一系列的称为"GC Roots"的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链(用图论的话来说,就是从GC Root到这个对象不可达),则证明此对象是不可用的. 在Java语言中,可作为GC Roots的对象包括下面几种: 虚拟机栈(栈帧中的本地变量表)中引用的对象 方法区中类静态属性引用的对象 方法区中常量引用的对象 本地方法栈中JNI(Native方法)引用的对象 3.2.3 再谈引用 jdk1.2后,对引用的概念进行了扩充 强引用 类型Object obj=new Object();这类的,只要强引用还在,垃圾收集器永远不会回收掉被引用的对象 软引用 软引用用来描述一些还有用但并非必需的对象.在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围内进行二次回收.如果这次回收还没有足够的内存,才会抛出内存溢出异常.在JDK1.2后,提供了SoftReference类来实现软引用. 弱引用 弱引用也是用来描述非必需对象.当垃圾收集器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象.在JDK1.2后,提供了WeakReference类实现弱引用. 虚引用 虚引用也称为幽灵引用或者幻影引用.一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来获得一个对象实例.为一个对象设置虚引用是为了能在这个对象被回收时能收到系统通知.在JDK1.2后,提供了PhantomReference类实现虚引用 3.2.4 生存还是死亡 即使在可达性分析算法中不可达的对象,也并非是"非死不可"的,要宣告一个对象死亡,至少经历两次标记过程 代码清单3-2 一次对象自我拯救的演示 /** * 此代码演示了两点 * 1.对象可以在被GC时自我拯救 * 2.这个自救机会只有一次 * * @author jimersylee */publicclassFinalizeEscapeGC { publicstatic FinalizeEscapeGC SAVE_HOOK =null; publicvoidisAlive() { System.out.println("yes,i am still alive"); } @Override protectedvoidfinalize() throws Throwable { super.finalize(); System.out.println("finalize method executed"); FinalizeEscapeGC.SAVE_HOOK =this; } publicstaticvoidmain(String[] args) throws Throwable { SAVE_HOOK =new FinalizeEscapeGC(); //对象第一次成功拯救自己演示//释放对象 SAVE_HOOK =null; System.gc(); //因为finalize方法优先度低,所以暂停0.5秒等待它 Thread.sleep(500); if (SAVE_HOOK !=null) { SAVE_HOOK.isAlive(); }else { System.out.println("no,i am dead :("); } //下面这段代码与上面的完全相同,但是这次自救却失败了 SAVE_HOOK =null; System.gc(); //因为finalize方法优先度低,所以暂停0.5秒等待它 Thread.sleep(500); if (SAVE_HOOK !=null) { SAVE_HOOK.isAlive(); }else { System.out.println("no,i am dead :("); } } } 3.2.5 回收方法区

August 20, 2016 · 1 min · 138 words · Jimmy

深入理解Java虚拟机 学习笔记-第二章

<深入理解Java虚拟机>学习笔记-第二章 项目地址: http://github.com/jimersylee/javaStudy 2.1 概述 内存管理领域 c,c++开发人员拥有最高权利,可以操作每一个对象,又需要维护每个对象的开始与销毁 java开发人员不需要为每一个对象写配对的delete/free代码,不容易出现内存泄露与内存溢出问题,不过,出现内存方面的问题,排查又是一项异常艰难的工作 2.2运行时数据区域 方法区Method Area 虚拟机栈VM Stack 本地方法栈Native Method Stack 堆 Heap 程序计数器 program Counter Register 2.2.1 程序计数器 java虚拟机通过线程轮换来分配处理器执行时间,为了线程切换后能恢复到正确的执行位置,每条线程都需要一个独立的程序计数器,为线程私有内存 2.2.2 Java虚拟机栈 与程序计数器一样,Java虚拟机栈也是线程私有的,它的生命周期与线程相同. 2.2.3 本地方法栈 本地方法栈为虚拟机使用到的Native方法服务 2.2.4 Java堆 Java堆(Heap)是Java虚拟机所管理的 内存中最大的一块,Java对是被所有线程共享的一块内存区域,在虚拟机启动时创建.此内存区域的唯一目的就是存放对象实例. Java堆是垃圾收集器管理的主要区域 现在的收集器基本采用分代收集算法 Java堆 新生代 老年代 更细致 Eden空间 From Survivor空间 To Survivor空间 Java堆可以处于物理上不连续的空间中,只要逻辑上连续即可,既可以实现成固定大小的,也可以是可扩展的,通过 -Xmx 和 -Xms控制,如果堆中没有足够的内存完成实例分配,则报 OutOfMemory 异常 2.2.5 方法区与Java堆一样,是各个线程共享的内存区域,用于存放已被虚拟机加载的类信息,敞亮,静态变量,即时编译器编译后的代码等数据 HotSpot上,方法区习惯性称为 永久代(Permanent Generation) 永久代有 -XX:MaxPermSize 上限 2.2.6 运行时常量池 运行时常量池(Runtime Constant Pool)是方法区的一部分.用于存放编译期生成的各种字面量和符号引用. 当常量池无法申请到内存报OutOfMemory异常 直接内存 JDK1.4中新加入NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O方式,它可以使用Native函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用记性操作. 作用:提高性能 直接内存不收Java堆大小的限制,但是受本机总内存限制.除了设置 -Xmx等参数信息,也要注意直接内存 ...

August 11, 2016 · 2 min · 380 words · Jimmy

我的Linux桌面环境配置与必备软件

我的Linux桌面环境配置与必备软件 Idea 主题 Monokai_2 字体 YaHei Consolas Hybrid phpstorm sublime jdk 设置环境变量 vim /etc/profile JAVA_HOME=/opt/jdk1.8.0_141 PATH=$JAVA_HOME/bin:$PATH CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar export JAVA_HOME export PATH export CLASSPATH source /etc/profile mysql workbench apt install mysql-workbench maven java包管理软件 shadowsocks,必备梯子 sudo apt install shadowsocks-qt5 tomcat redis-desktop-manager redis跨平台客户端 下载地址 配置lamp环境 安装xammp 到/opt 将bin路径加入path vim /etc/profile export $PTAH=$PATH:/opt/lampp/bin 这样就可以直接使用pecl来安装扩展了 pecl search redis pecl install redis nodejs npm apt install nodejs apt install npm 设置淘宝镜像 npm config set registry https://registry.npm.taobao.org 编译环境组件 sudo apt install build-essential Nginx 编译安装nginx 下载源码 tar zxvf nginx-x.tar cd nginx ./configure \ --prefix=/usr \ --sbin-path=/usr/sbin/nginx \ --conf-path=/etc/nginx/nginx.conf \ --error-log-path=/var/log/nginx/error.log \ --pid-path=/var/run/nginx/nginx.pid \ --user=jimersylee \ --group=jimersylee \ --with-http_ssl_module \ --with-http_flv_module \ --with-http_gzip_static_module \ --http-log-path=/var/log/nginx/access.log \ --http-client-body-temp-path=/var/tmp/nginx/client \ --http-proxy-temp-path=/var/tmp/nginx/proxy \ --http-fastcgi-temp-path=/var/tmp/nginx/fcgi \ --with-http_stub_status_module

July 5, 2016 · 1 min · 114 words · Jimmy

为域名配置免费SSL证书

为域名配置免费SSL证书 Nginx配置ssl 腾讯云申请证书 阿里云域名解析验证证书 安装证书 下载证书 上传配置证书 #将本地的jenkins.jimersylee.com.zip上传至jimersylee.com这个机子上的/data/ssl_cert目录scp jenkins.jimersylee.com.zip root@jimersylee.com:/data/ssl_cert #登录主机解压文件 ssh root@jimersylee.com cd /data/ssl_cert unzip jenkins.jimersylee.com.zip #各种web服务器的证书就解压完成了,然后去配置Nginx [root@VM_77_132_centos ssl_cert]# tree . ├── Apache │ ├── 1_root_bundle.crt │ ├── 2_blog.jimersylee.com.crt │ ├── 2_jenkins.jimersylee.com.crt │ ├── 2_jimersylee.com.crt │ ├── 3_blog.jimersylee.com.key │ ├── 3_jenkins.jimersylee.com.key │ └── 3_jimersylee.com.key ├── blog.jimersylee.com.cert.zip ├── IIS │ ├── blog.jimersylee.com.pfx │ ├── jenkins.jimersylee.com.pfx │ ├── jimersylee.com.pfx │ └── keystorePass.txt ├── jenkins.jimersylee.com.zip ├── jimersylee.com.cert.zip ├── Nginx │ ├── 1_blog.jimersylee.com_bundle.crt │ ├── 1_jenkins.jimersylee.com_bundle.crt │ ├── 1_jimersylee.com_bundle.crt │ ├── 2_blog.jimersylee.com.key │ ├── 2_jenkins.jimersylee.com.key │ └── 2_jimersylee.com.key └── Tomcat ├── jenkins.jimersylee.com.jks └── keystorePass.txt nginx配置 ...

May 8, 2016 · 1 min · 160 words · Jimmy

机器学习实战-学习笔记之Logistic

项目地址:http://github.com/jimersylee/MachineLearningAction Logistic回归 本章内容 Sigmoid函数和Logistic回归分类器 最优化理论初步 梯度下降最优化算法 数据中的缺失项处理 最优化算法 比如如何在最短时间内从A点到B点?如何投入最少的工作量获得最大的收益 Logistic回归的一般过程 收集数据:采用任意方法收集数据 准备数据:由于需要进行距离计算,因此要求数据类型为数值型.另外,结构化数据格式则最佳 分析数据:采用任意方法对数据进行分析 训练算法:大部分时间将将用于测试,训练的目的是为了找到最佳的分类回归系数 测试算法:一旦训练步骤完成,分类将会很快 使用算法:首先,我们需要输入一些数据,并将其转换成对应的结构化数值;接着,基于训练好的回归系数就可以对这些数值进行简单的回归计算,判定他们属于那个类别了;在这之后,我们就可以在输出的类别上做一些其他分析工作 基于Logistic回归和Sigmoid函数的分类 优点:计算代价不高,易于理解和实现 缺点:容易欠拟合,分类精度可能不高 适用数据类型:数值型和标称型数据 我们想要的函数,能够接受所有的输入然后预测出类别. 使用单位阶跃函数 Sigmoid函数 f(z)=1/(1+e^-z) 训练算法:随机梯度上升 梯度上升算法在每次更新回归系数时都需要遍历整个数据集,当数据集增加时,计算复杂度就太高了. 改进方法是一次禁用一个样本点来更新回归系数,该方法成为随机梯度上升算法. 报错,未解决 weights = weights + alpha error dataMatIn[i] ValueError: operands could not be broadcast together with shapes (3,) (0,) 示例:从疝气病预测兵马的死亡率 本节使用Logistic回归来预测患有疝气病的马的存货问题 样本数据包含368个样本和28个特征 有30%的数据的值是缺失的.下面将介绍如何处理数据集中的数据确实问题,然后再用Logistic回归和随机梯度上升算法来预测病马的生死 准备数据 数据缺失是个麻烦的问题.如何解决 使用可用特征的均值来填补缺失值 使用特殊值来填补缺失值,如-1 忽略有缺失值的样本 使用相似样本的均值填补缺失值 使用另外的机器学习算法来预测缺失值 from numpyimport * import matplotlib.pyplotas plt defloadDataSet(): """ 载入测试数据 :return: """ dataMat = [] labelMat = [] fr = open('testSet.txt') for linein fr.readlines(): lineArr = line.strip().split() dataMat.append([1.0, float(lineArr[0]), float(lineArr[1])])# 为了计算方便,将X0设置为1.0 labelMat.append(int(lineArr[2])) return dataMat, labelMat defsigmoid(inX): """ Sigmoid函数,单位阶跃函数 :param inX: :return: """ return 1.0 / (1 + exp(-inX)) defgradAscent(dataMatIn, classLabels): """ 梯度上升算法 :param dataMatIn: 输入的数据矩阵,存放的100*3的矩阵 :param classLabels: 输入的数据类别矩阵 :return:返回训练好的迭代次数 """ # 转换为NumPy矩阵类型 dataMatrix = mat(dataMatIn) labelMat = mat(classLabels).transpose()# 初始为1*100的行向量,为了便于矩阵运算,使用transpose转置为列向量100*1 m, n = shape(dataMatrix)# 得到矩阵大小 alpha = 0.001# 目标移动的步长 maxCycles = 500# 最大迭代次数 weights = ones((n, 1)) for kin range(maxCycles): # 矩阵相乘,下面两行,计算真实类别与预测类别的差值,接下来就是按照该差值的方向调整回归系数 h = sigmoid(dataMatrix * weights)# 代表的不是一次乘积计算,事实上该运算包含了300次的乘积,变量h不是一个数,而是一个列向量,100 error = (labelMat - h) weights = weights + alpha * dataMatrix.transpose() * error return weights defstocGradAscent0(dataMatIn, classLabels): m, n = shape(dataMatIn) alpha = 0.01 weights = ones(n) for iin range(m): h = sigmoid(sum(dataMatIn[i] * weights))# h是向量 error = classLabels[i] - h# error是向量 weights = weights + alpha * error * dataMatIn[i] return weights defstocGradAscent1(dataMatIn, classLabels, numIter=150): """ 改进的随机梯度上升算法 :param dataMatIn: :param classLabels: :param numIter: :return: """ m, n = shape(dataMatIn) weights = ones(n) for jin range(numIter): dataIndex = range(m) for iin range(m): alpha = 4 / (1.0 + j + i) + 0.01# alpha每次迭代时需要调整 randIndex = int(random.uniform(0, len(dataIndex)))# 随机选取更新 h = sigmoid(sum(dataMatIn[randIndex] * weights)) error = classLabels[randIndex] - h weights = weights + alpha * error * dataMatIn[randIndex] del (dataIndex[randIndex]) return weights defplotBestFit(weights): """ 画出数据集和Logistic回归最佳拟合直线的函数 :param weights:系数 :return: """ weights = weights.getA() dataMat, labelMat = loadDataSet() dataArr = array(dataMat) n = shape(dataArr)[0] xcord1 = [] ycord1 = [] xcord2 = [] ycord2 = [] for iin range(n): if int(labelMat[i]) == 1: xcord1.append(dataArr[i, 1]) ycord1.append(dataArr[i, 2]) else: xcord2.append(dataArr[i, 1]) ycord2.append(dataArr[i, 2]) fig = plt.figure() ax = fig.add_subplot(111) ax.scatter(xcord1, ycord1, s=30, c='red', marker='s') ax.scatter(xcord2, ycord2, s=30, c="green") x = arange(-3.0, 3.0, 0.1) y = (-weights[0] - weights[1] * x) / weights[2] ax.plot(x, y) plt.xlabel("X1") plt.ylabel("X2") plt.show() defclassifyVector(inX, weights): prob = sigmoid(sum(inX * weights)) if prob > 0.5: return 1.0 else: return 0.0 defcolicTest(): """ 疝气病马死亡分类测试 :return: """ frTrain = open('horseColicTraining.txt') frTest = open('horseColicTest.txt') trainingSet = [] trainingLabels = [] for linein frTrain.readlines(): currLine = line.strip().split('\t') lineArr = [] for iin range(21): lineArr.append(float(currLine[i])) trainingSet.append(lineArr) trainingLabels.append(float(currLine[i])) trainWeights = stocGradAscent1(array(trainingSet), trainingLabels, 500) errorCount = 0 numTestVec = 0.0 for linein frTest.readlines(): numTestVec += 1.0 currLine = line.strip().split('\t') lineArr = [] for iin range(21): lineArr.append(float(currLine[i])) if int(classifyVector(array(lineArr), trainWeights)) != int(currLine[21]): errorCount += 1 errorRate = (float(errorCount / numTestVec)) print "the error rate of this test is: %f" % errorRate return errorRate defmultiTest(): numTests = 10 errorSum = 0.0 for kin range(numTests): errorSum += colicTest() print "after %d iterations the average error rate is: %f" % (numTests, errorSum / float(numTests)) deftestCal(): dataArr, labelMat = loadDataSet() weights = gradAscent(dataArr, labelMat) print weights """ 得到一组回归系数,它确定了不同类别数据之间的分割线 [[ 4.12414349] [ 0.48007329] [-0.6168482 ]] """ deftestGradAscent(): """ 测试梯度上升算法,画图 :return: """ dataArr, labelMat = loadDataSet() weights = gradAscent(dataArr, labelMat) plotBestFit(weights) deftestStocGradAscent0(): """ 测试随机梯度上升算法,画图 :return: """ dataArr, labelMat = loadDataSet() weights = stocGradAscent0(dataArr, labelMat) plotBestFit(weights) deftestStocGradAscent1(): """ 测试随机梯度上升算法,画图 :return: """ dataArr, labelMat = loadDataSet() weights = stocGradAscent1(dataArr, labelMat) plotBestFit(weights) # testCal()#testGradAscent()# testStocGradAscent0() multiTest()

May 5, 2016 · 3 min · 553 words · Jimmy

机器学习实战 学习笔记之KNN-约会数据识别

<机器学习实战>学习笔记之KNN-约会数据识别 项目地址:http://github.com/jimersylee/MachineLearningAction # -*- coding: utf-8 -*-""" 约会数据kNN """ from numpyimport * import matplotlib.pyplotas plt import operator defclassify0(inX, dataSet, labels, k): dataSetSize = dataSet.shape[0] diffMat = tile(inX, (dataSetSize, 1)) - dataSet sqDiffMat = diffMat ** 2 sqDistances = sqDiffMat.sum(axis=1) distances = sqDistances ** 0.5 sortedDistIndicies = distances.argsort() classCount = {} for iin range(k): voteIlabel = labels[sortedDistIndicies[i]] classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1 sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True) return sortedClassCount[0][0] deffile2matrix(filename): fr = open(filename) numberOfLines = len(fr.readlines())# get the number of lines in the file returnMat = zeros((numberOfLines, 3))# prepare matrix to return classLabelVector = []# prepare labels return fr = open(filename) index = 0 for linein fr.readlines(): line = line.strip() listFromLine = line.split('\t') returnMat[index, :] = listFromLine[0:3] classLabelVector.append(int(listFromLine[-1])) index += 1 return returnMat, classLabelVector defautoNorm(dataSet): """ 归一化数值 因为计算距离的时候,差值最大的属性对计算结果的影响最大,如果对于此数据,我们认为权重一样,则需要将数据进行处理,将数值归一化 将属性的取值范围处理为0到1或者-1到1,使用下面的公式 newValue=(oldValue-min)/(max-min) :param dataSet:矩阵 :return:normDataSet:归一化后的矩阵 range:取值范围 minVals:最小值 """ minVals = dataSet.min(0)# 0代表第一列,取得第一列最小值 maxVals = dataSet.max(0)# 取得第一列最大值 ranges = maxVals - minVals# 可能的取值范围 normDataSet = zeros(shape(dataSet))# 创建新的返回矩阵 m = dataSet.shape[0] normDataSet = dataSet - tile(minVals, (m, 1)) normDataSet = normDataSet / tile(ranges, (m, 1))# element wise dividereturn normDataSet, ranges, minVals defdatingClassTest(): hoRatio = 0.50# hold out 10% datingDataMat, datingLabels = file2matrix('datingData/datingTestSet2.txt')# load data setfrom file normMat, ranges, minVals = autoNorm(datingDataMat) m = normMat.shape[0] numTestVecs = int(m * hoRatio) errorCount = 0.0 for iin range(numTestVecs): classifierResult = classify0(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 3) print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i]) if (classifierResult != datingLabels[i]): errorCount += 1.0 print "the total error rate is: %f" % (errorCount / float(numTestVecs)) print errorCount defshowNormal(): """ 最基本散点图 没有样本类别标签的约会数据散点图.难以辨识途中的点究竟属于那个样本分类 :return: """ datingDataMat, datingLables = file2matrix('datingData/datingTestSet2.txt') fig = plt.figure() ax = fig.add_subplot(111) ax.scatter(datingDataMat[:, 1], datingDataMat[:, 2]) plt.xlabel("Percentage of Time Spent Playing Video Games") plt.ylabel("Liters of Icc Cream Consumed Per Week") plt.show() defshowLable(): """ 带有样本分类标签的约会数据散点图 虽然能够比较容易区分数据点丛书类别,但依然很那根据这张图得出结论性信息 :return: """ datingDataMat, datingLables = file2matrix('datingData/datingTestSet2.txt') fig = plt.figure() ax = fig.add_subplot(111) ax.scatter(datingDataMat[:, 1], datingDataMat[:, 2], 15.0 * array(datingLables), 15.0 * array(datingLables)) ax.axis([-2, 25, -0.2, 2.0]) plt.xlabel("Percentage of Time Spent Playing Video Games") plt.ylabel("Liters of Icc Cream Consumed Per Week") plt.show() defshowClass(): """ 显示不同的分类 标识了三个不同的样本分类区域,具有不同爱好的人其类别区域也不同 每年赢得的飞行常客里程数与玩游戏视频游戏所占百分比的约会数据散点图 约会数据有三个分类标签,通过途中展示的两个特征更容易区分数据点从属的类别 :return: """ n = 1000# number of points to create xcord1 = []; ycord1 = [] xcord2 = []; ycord2 = [] xcord3 = []; ycord3 = [] markers = [] colors = [] fw = open('datingData/datingTestSet.txt', 'w') for iin range(n): [r0, r1] = random.standard_normal(2) myClass = random.uniform(0, 1) if (myClass <= 0.16): fFlyer = random.uniform(22000, 60000) tats = 3 + 1.6 * r1 markers.append(20) colors.append(2.1) classLabel = 1# 'didntLike' xcord1.append(fFlyer); ycord1.append(tats) elif ((myClass > 0.16)and (myClass <= 0.33)): fFlyer = 6000 * r0 + 70000 tats = 10 + 3 * r1 + 2 * r0 markers.append(20) colors.append(1.1) classLabel = 1# 'didntLike'if (tats < 0): tats = 0 if (fFlyer < 0): fFlyer = 0 xcord1.append(fFlyer); ycord1.append(tats) elif ((myClass > 0.33)and (myClass <= 0.66)): fFlyer = 5000 * r0 + 10000 tats = 3 + 2.8 * r1 markers.append(30) colors.append(1.1) classLabel = 2# 'smallDoses'if (tats < 0): tats = 0 if (fFlyer < 0): fFlyer = 0 xcord2.append(fFlyer); ycord2.append(tats) else: fFlyer = 10000 * r0 + 35000 tats = 10 + 2.0 * r1 markers.append(50) colors.append(0.1) classLabel = 3# 'largeDoses'if (tats < 0): tats = 0 if (fFlyer < 0): fFlyer = 0 xcord3.append(fFlyer); ycord3.append(tats) fw.close() fig = plt.figure() ax = fig.add_subplot(111) # ax.scatter(xcord,ycord, c=colors, s=markers) type1 = ax.scatter(xcord1, ycord1, s=20, c='red') type2 = ax.scatter(xcord2, ycord2, s=30, c='green') type3 = ax.scatter(xcord3, ycord3, s=50, c='blue') ax.legend([type1, type2, type3], ["Did Not Like", "Liked in Small Doses", "Liked in Large Doses"], loc=2) ax.axis([-5000, 100000, -2, 25]) plt.xlabel('Frequent Flyier Miles Earned Per Year') plt.ylabel('Percentage of Time Spent Playing Video Games') plt.show() showNormal() showLable() showClass() datingClassTest()

May 4, 2016 · 3 min · 602 words · Jimmy

我的后端开发书架2015版

原文出处: 江南白衣(@江南白衣Calvin) 小学生作文的开头:光阴似箭,日月如梭…..半年过去了,床底下又多了不少书,更新一个2.0版。 自从技术书的书架设定为”床底下“之后,又多了很多买书的空间。中国什么都贵,就是书便宜。 很多书没有全部看完,看一部分觉得值得推荐就放上来了,但在碎片化的阅读下难免错评,不定期更新修正。 书架主要针对Java后端开发。 更偏爱那些能用简短流畅的话,把少壮不努力的程序员所需的基础补回来的薄书,而有些教课书可能很著名,但干涩枯燥,喋喋不休的把你带回到大学课堂上昏昏欲睡,不录。 操作系统与网络的书 《Linux内核设计与实现 – Linux Kernel Development 第3版》 Robert Love用最薄的篇幅,顺畅的文字将Linux内核主要的算法讲清楚了,比《深入理解Linux内核》,《深入Linux内核架构》之类厚厚的全是代码的,不是专门的内核程序员看这本足够了。 《Linux系统编程 第2版》 继续是Robert Love,比起APUE也是以薄见长,专门针对重要的系统调用讲解。 《性能之巅》 操作系统的性能调优、监控、工具和方法论,看这本就够了,足够厚。还有本薄一点的,东抄西编格调没那么高的叫《Linux性能优化大师》。 《TCP/IP详解 卷1:协议》 这么多年过去了,TCP的书好像还是只有这一本,有点旧了,看了也还是半懂不懂。后人在2011年写了第二版,看目录清晰明了与时俱进了很多,机械工业正在翻译。 《现代操作系统 第3版》 如果看LKD未尽兴,可以回头看看这本基础概念,感觉比那本枯燥的《操作系统概念》(恐龙书)读起来舒服。 PS. 《UNIX环境高级编程》和《UNIX网络编程》,APUE和UNP更多作为一本超厚工具书存在。《Unix 编程艺术》,扯的都是闲篇,厚厚的一本其实略读一下就行。 算法的书 《数据结构与算法分析-Java语言描述 第2版》 够薄,数据结构与算法分析的点基本都涵盖了,而且示例代码还是Java写的。 《算法 第4版》 可与上一本对比着读,厚一些,也多些图,但知识点没上面的全,也是Java的。 《算法设计与分析基础 第3版》 数学系偏爱无比枯燥很多公式的《算法导论》, 计算机系喜欢这本实用主义的典型。翻开就看到一段很文艺很贴心的话:“效率能用数学的严密性进行精确定义,而简单性就像“美”一样,很大程度取决于审视者 的眼光。简单的算法更容易理解和实现,因而相应的程序也往往更少的Bug。当然对于简单性的美学诉求也是让人无法抗拒的。” PS. 《数学之美》、《编程珠玑》,都是专栏文章,讲得并不系统,可以当兴趣读物来看。 架构设计的书 《恰如其分的软件架构 – 风险驱动的设计方法》 由于人类与生俱来的惰性,计算机原本科学的、精准的设计方式,有了敏捷的借口之后就很难再维持了。本书就是在这种背景下,提出由风险来决定设计的度,当然,这个风险是广义的。除了开始的风险驱动部分,其余部分就是规规矩矩标标准准的架构师教科书。 《软件系统架构:使用视点和视角与利益相关者合作 第2版》 也是教科书,最难得的是,这本老书在十年后的去年升级了第二版。 《程序员必读之软件架构 – Software Architecture for Developers》 作者维护着codingthearchitecture.com 。不过中文书名叫“必读”有点过。薄书里的两部分内容: 编码的架构师:一直是我的职业模板,我记的笔记。 架构的表达: 当年我觉得RUP的4+1 UML视图不足以表达系统时,Simon Brown的模板给了很好的过渡范例。 《发布!软件的设计与部署 – Release It!: Design and Deploy Production-Ready Software 》 关于高可靠性的软件,学校里不会教,出来社会却要面对的那部分,英文的原标题更清晰。 ...

October 29, 2015 · 1 min · 167 words · Jimmy