int main(int argc, char** argv) { MPI_Init(&argc, &argv); int flag; int* max_tag; MPI_Comm_get_attr(MPI_COMM_WORLD, MPI_TAG_UB, &max_tag, &flag); printf("Maximum tag : %d.\n", *max_tag); MPI_Finalize(); return 0; }
多个进程允许重复使用相同的标签:无论通信的模式如何,接收顺序与发送顺序相同。
MPI基本数据类型
MPI C 字节数 MPI_CHAR | char | 1 MPI_SHORT | short | 2 |
---|
MPI_INT | int | 4 | MPI_LONG | long | 8 | MPI_UNSIGNED_CHAR | unsigned char | 1 | MPI_UNSIGNED_SHORT | unsigned short | 2 | MPI_UNSIGNED_LONG | unsigned long | 8 | MPI_UNSIGNED | unsigned int | 4 | MPI_FLOAT | float | 4 MPI_DOUBLE | MPI_LONG_DOUBLE double | long double 8 | 16 | 所有MPI_ *类型的大小均为8个字节。 只有收到指定标签的全部消息时,接收过程才会退出对MPI_Recv的调用。 发送过程的行为更加复杂。 MPI_STATUS_IGNORE是一个可以用来代替状态变量的预定义常量。 可以创建和传达更复杂的数据结构。 「深度学习福利」大神带你进阶工程师,立即查看>>> include_directories(${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/include) set(RC_NNET_FILES ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/activation_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/activation_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/activations.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/activations.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/avgpool_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/avgpool_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/batchnorm_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/batchnorm_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/blas.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/blas.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/box.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/box.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/classifier.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/col2im.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/col2im.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/compare.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/connected_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/connected_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/convolutional_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/convolutional_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/cost_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/cost_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/crnn_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/crnn_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/crop_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/crop_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/cuda.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/cuda.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/data.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/data.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/deconvolutional_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/deconvolutional_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/demo.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/demo.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/detection_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/detection_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/dropout_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/dropout_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/gemm.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/gemm.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/gru_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/gru_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/im2col.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/im2col.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/image.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/image.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/image_opencv.cpp ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/stb_image_write.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/iseg_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/iseg_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/l2norm_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/l2norm_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/list.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/list.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/local_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/local_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/logistic_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/logistic_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/lstm_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/lstm_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/matrix.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/matrix.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/maxpool_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/maxpool_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/network.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/network.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/normalization_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/normalization_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/option_list.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/option_list.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/parser.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/parser.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/region_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/region_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/region_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/region_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/reorg_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/reorg_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/rnn_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/rnn_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/route_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/route_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/shortcut_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/shortcut_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/softmax_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/softmax_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/stb_image.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/tree.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/tree.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/upsample_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/upsample_layer.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/utils.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/utils.h ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/yolo_layer.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/src/yolo_layer.h ) set(YOLO3 ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/darknet.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/detector.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/dice.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/rnn.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/rnn_vid.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/segmenter.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/super.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/swag.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/tag.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/voxel.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/writing.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/coco.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/art.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/attention.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/captcha.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/cifar.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/classifier.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/lsd.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/regressor.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/nightmare.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/instance-segmenter.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/go.c ${PROJECT_SOURCE_DIR}/src/rc_cv/rcnet/examples/yolo.c ) add_executable(rcnetapp ${YOLO3}) target_link_libraries(rcnetapp rcnet pthread stdc++ ${OpenCV_LIB} pthread m) 「深度学习福利」大神带你进阶工程师,立即查看>>> 各位童鞋们,如果您已经拼了别人的团,但是还不知道怎么玩?小编来告诉你! 最后一天了,大家就不要再开团了,马上进入官方热荐团直享最低折扣:http://click.aliyun.com/m/1000023288/ 您拼团后将享受以下福利: 福利1:拉新赢红包 您拼团后可通过专属分享链接,邀请好友来参团。每成功邀请1个新用户参团购买您团里的云产品,您将获得1个拉新红包!几十块——1111元红包都有可能! 最大的红包有1111元的现金红包,将即时发放到您的阿里云账户中!拉新人数越多,红包越多! 福利2:享受云产品折扣 参团新用户在活动期间,通过活动页面首次购买指定云产品的,可根据同一团内的拼团人数,享受不同的拼团折扣价格,具体如下: 以2核8G5M配置的云服务器为例: 3年版的配置原价14850元,活动起拼价4140元,相当于28折起购,团首购满6人即低至2070元,相当于14折,最高省12780元。 福利3:云大使返现 参加开团/拼团活动都将加入阿里云云大使。 您参团后即加入阿里云云大使,可获取专属分享链接,邀请其他用户参团。如果您是新用户,不仅能享受以上云产品折扣,和拉新红包,还能获得首单返25%,30天内拉的用户再消费会再返现15%。 举个例子: 如果您所在的团当前团购的云产品为2070元的ECS云服务器,您每拉一个新人,可获得2070*25%=517.5元的返佣。 如果30天内您拉的新人再次购买ECS云服务器,如4140元的云产品,您可再获得4140*15%=621元的返佣。 老用户如何赚钱? 拉新用户即得红包,再享云大使25%的额外返现,如果拉一个新人购买2核8G5M的配置,拼团价4140元,您将会得到(4140元*25%)1035元+1111元(最高)=2146元的最高返现,平均能得>1035元的现金红包及返现。 原文链接 本文为云栖社区原创内容,未经允许不得转载。 「深度学习福利」大神带你进阶工程师,立即查看>>> 2018 年 10 月 12 日,七牛云与北京锐安科技有限公司签署战略合作协议。锐安科技总经理谢永恒、副总经理帅佩章,七牛云总裁吕桂华、七牛云人工智能实验室负责人彭垚、市场副总裁钱骥华出席签约仪式。 七牛云与锐安科技将在警务安防、网络信息安全、大数据服务等重要领域达成全面长期战略合作。通过深度整合七牛云人工实验室自研的城市慧眼系统、内容安全、深度学习平台、智能城管、智能人像等久经实战检验的机器视觉产品和解决方案,锐安科技将与七牛云一起,打造国内顶尖的网络大数据产品。 双方将从以下三个层面达成全面合作,充分发挥各自优势,为构建大数据合作生态链在国内各行业的应用落地而不懈努力。 共建公安标准体系 蓝图规划,标准先行。在全国公安领域处于领先地位的锐安科技,将与七牛云等十余家生态合作伙伴一起,共同发布最新标准体系,为公安大数据产业发展提供最先进的规划。 达成产品深度结合 灵活组合,优势互补。七牛云人工智能实验室将提供内容安全、智能多媒体处理、OCR、智能人像、城市慧眼系统、智能人像等 10 余种性能优秀的计算机视觉产品,与生态合作伙伴共同打造千种安防产品货架,在应用落地过程中实现产品效果最大化。 建设全国服务团队 服务至上,全面支撑。七牛云将与锐安科技一同打造全国服务团队,计划在明年十余个省市实现应用落地,并提供高水平专业服务。 随着公安大数据时代来临,人工智能、大数据等技术注定将在今后的行业应用中扮演更重要的角色。在公安领域全国领先的锐安科技,与七牛云人工智能实验室走在行业之先,达成全面战略合作,进一步促进公安大数据行业生态稳步发展。 点击 「阅读原文」 了解七牛云人工智能实验室 「深度学习福利」大神带你进阶工程师,立即查看>>> 1.英文题目 Given an array of integers, return indices of the two numbers such that they add up to a specific target. You may assume that each input would have exactly one solution, and you may not use the same element twice. Example: Given nums = [2, 7, 11, 15], target = 9, Because nums[ 0 ] + nums[ 1 ] = 2 + 7 = 9, return [ 0 , 1 ]. 2.解题 public static int[] twoSum(int[] nums, int target) { for (int i=0; i < nums.length; i++) { for (int j=i+1; j < nums.length; j++) { if (nums[i] + nums[j] == target) { return new int[]{i,j}; } } } throw new IllegalArgumentException("No two sum solution"); } 「深度学习福利」大神带你进阶工程师,立即查看>>> STOCHRSI 指标理解 这几天帮一个朋友解决一个关于指标的问题 ,这个指标就是 STOCHRSI 。在网上查了很多资料,中文的真是甚少。而且仅有的也不是讲的很清楚。对于我这样的 交易小白,简直是天书。 不过只要研究多少会有点收获的,下面分享下经验,需要用这个的朋友可以借鉴。 在网上找到了一些 关于这个指标的计算公式。 /* LC := REF(CLOSE,1); //REF(C,1) 上一周期的收盘价 RSI:=SMA(MAX(CLOSE-LC,0),N,1)/SMA(ABS(CLOSE-LC),N,1) *100; %K: MA(RSI-LLV(RSI,M),P1)/MA(HHV(RSI,M)-LLV(RSI,M),P1)*100; LLV(l,60)表示:检索60天内的最低价,可适应于检索任何股票 %D:MA(%K,P2); LC := REF(CLOSE,1); RSI:=SMA(MAX(CLOSE-LC,0),N,1)/SMA(ABS(CLOSE-LC),N,1) *100; STOCHRSI:MA(RSI-LLV(RSI,M),P1)/MA(HHV(RSI,M)-LLV(RSI,M),P1)*100; */ 天哪! 我竟然耐心看完了。(当时看见这个的时候,就感觉碰到钉子了。) 这个描述是通用 公式。但是有点编程经验的我也只能 猜!猜!猜! 在网上找到的资料说,这个指标有大概3个不同形态。上面的公式是其中2个。 但是资料也没说,这3个不同形态的其他详细信息。 在各个平台的图表行情中看、对比。发现,关于这个指标的描述各不相同。平台上的 talib指标库 中的指标函数 STOCHRSI 的参数描述也没有完全明白。 用talib指标库 传入参数 14,14,3,3 这组参数,得出的数据和其他平台的对比,发现差异较大。看了看参数描述发现不一样。于是放弃现成的。 有点想动手撸这个指标…(有点怕怕,弄不好就被代码虐了)。 经过了一番痛苦挣扎… 总结: 这个指标不管哪种形态,RSI 指标是这个指标的基础数据。对比了其他平台描述和上述公式。确定STOCHRSI指标的参数必然有一个是RSI的参数。 又发现 这个指标的不同描述,有的描述是指标输出的是 %K , %D两条线。 有的描述是 输出的为 STOCHRSI , MA(3) (这个描述的参数是14,14,3,3) 分析了一下, 其实 虽然是2种不同形态, %K === STOCHRSI , %D === MA(3) 输出的2条线(数据)计算公式是一样的。 确定 MA(3)中的3是一个参数。 剩下2个参数,动手往上面的公式里面带入,就是M 和 P1了 。14、3 都试试。最终发现撸出来的指标数据 ,终于对的上其他平台上的数据了。 绿色是快线 %K ,橙色是 %D 自己写的指标,可以对比下 OKCoin的 。 如有问题欢迎留言 ^^ function LLV(array,period){ if(!array || array.length - period < 0){ throw "error:" + array; } var min = array[array.length - period]; for(var i = array.length - period; i < array.length; i++){ if( array[i] < min ){ min = array[i]; } } return min; } function HHV(array,period){ if(!array || array.length - period < 0){ throw "error:" + array; } var max = array[array.length - period]; for(var i = array.length - period; i < array.length; i++){ if( array[i] > max){ max = array[i]; } } return max; } function DeleteNullEle(initArr){ var dealArr = []; var initArrLen = initArr.length; for(var i = 0,j = 0 ; i < initArrLen ; i++,j++){ if(initArr[i] === null || isNaN(initArr[i]) ){ j--; continue; } dealArr[j] = initArr[i]; } return dealArr; } /* LC := REF(CLOSE,1); //REF(C,1) 上一周期的收盘价 RSI:=SMA(MAX(CLOSE-LC,0),N,1)/SMA(ABS(CLOSE-LC),N,1) *100; %K: MA(RSI-LLV(RSI,M),P1)/MA(HHV(RSI,M)-LLV(RSI,M),P1)*100; LLV(l,60)表示:检索60天内的最低价,可适应于检索任何股票 %D:MA(%K,P2); LC := REF(CLOSE,1); RSI:=SMA(MAX(CLOSE-LC,0),N,1)/SMA(ABS(CLOSE-LC),N,1) *100; STOCHRSI:MA(RSI-LLV(RSI,M),P1)/MA(HHV(RSI,M)-LLV(RSI,M),P1)*100; */ function FstochRSI(records,n,m,p1,p2){ var len = records.length; //var LC = records[len-2];//上一周期收盘价 //var rsi = TA.RSI(records,n);// RSI 数组 ,talib var rsi = talib.RSI(records,n); rsi = DeleteNullEle(rsi);//ceshi var arr1 = []; var arr2 = []; var arr3 = []; var arr4 = []; var rsi_a = []; var rsi_b = []; var k = []; var d = null; /*不包含当前柱 for(var a = 0 ;a < rsi.length ; a++ ){//改造 不用 LLV for(var aa = 0 ; aa <= a; aa++ ){ rsi_a.push(rsi[aa]); } arr1.push(rsi[a] - TA.Lowest(rsi_a,m)); } for(var b = 0 ;b < rsi.length ; b++ ){//改造 不用 HHV for(var bb = 0 ; bb <= b; bb++ ){ rsi_b.push(rsi[bb]); } arr2.push(TA.Highest(rsi_b,m) - TA.Lowest(rsi_b,m)); } */ for(var a = 0 ;a < rsi.length ; a++ ){//改造 不用 LLV if(a < m){ continue; } for(var aa = 0 ; aa <= a; aa++ ){ rsi_a.push(rsi[aa]); } arr1.push(rsi[a] - LLV(rsi_a,m)); } for(var b = 0 ;b < rsi.length ; b++ ){//改造 不用 HHV if(b < m){ continue; } for(var bb = 0 ; bb <= b; bb++ ){ rsi_b.push(rsi[bb]); } arr2.push(HHV(rsi_b,m) - LLV(rsi_b,m)); } arr1 = DeleteNullEle(arr1); arr2 = DeleteNullEle(arr2); //Log("arr1:",arr1.length,"-",arr1);//ceshi //Log("arr2:",arr2.length,"-",arr2);//ceshi arr3 = talib.MA(arr1,p1); arr4 = talib.MA(arr2,p1); arr3 = DeleteNullEle(arr3); arr4 = DeleteNullEle(arr4); //Log("ceshi");//ceshi var c = 0; var diff = 0; if(arr3.length !== arr4.length){//实测 长度不相等 throw "error: !=" + arr3.length + "----" + arr4.length; diff = arr4.length - arr3.length; //example diff = 10 - 6 }else{ //throw "error:" + arr3.length + "----" + arr4.length; } for( ;c < arr3.length ; c++ ){ k.push(arr3[c] / arr4[c + diff] * 100); } d = talib.MA(k,p2); return [k,d,rsi]; } 原文地址:https://quant.la/Article/View/43/ 「深度学习福利」大神带你进阶工程师,立即查看>>> 【一】综述 利用jieba进行关键字提取时,有两种接口。一个基于TF-IDF算法,一个基于TextRank算法。TF-IDF算法,完全基于词频统计来计算词的权重,然后排序,在返回TopK个词作为关键字。TextRank相对于TF-IDF,基本思路一致,也是基于统计的思想,只不过其计算词的权重时,还考虑了词的上下文(通过窗口滑动来实现),而且计算词的权重时,也考虑了相关联系词的影响。可以说,TextRank实际上是依据位置与词频来计算词的权重的。下面,结合基于jieba源码,来分别解释两种算法的实现。 【二】TF-IDF 1. 原理解析 假设,共有N篇文档,分别用 d1,d2,d3,,,,,,,dn来表示。 TF = 某个词在di篇文章中出现的次数/di篇文章的总词数 = count(W in di)/ count(di)。因此,TF计算的是单个词在单个文档中出现的词频。 IDF = 总的文档数 / 出现词W的文档数 。 IDF其实反映了词W在文档之间的区别度。如果W在仅在一篇文档中出现,则说明可以使用W将该文档与其他文档区别开来。即IDF可以反映W的独特性 。 TF*IDF,可以得到词的重要性。比如: 北京和西安在同一篇文档中的词频均为20%,那如何估计北京是该文的关键字,还是西安呢?如果同时有10篇文章均提到了北京,恰好只有这篇文章提到了西安,则西安作为这篇文章的关键字更为合理。 2. idf.txt jieba有统计好的idf值,在 jieba/analyse/idf.txt中。 劳动防护 13.900677652 生化学 13.900677652 奥萨贝尔 13.900677652 考察队员 13.900677652 岗上 11.5027823792 倒车档 12.2912397395 3. idf.txt 加载 代码在 jieba/analyse/tfidf.py class IDFLoader(object): def __init__(self, idf_path=None): self.path = "" self.idf_freq = {} # 初始化idf的中位数值 self.median_idf = 0.0 if idf_path: # 解析idf.txt self.set_new_path(idf_path) def set_new_path(self, new_idf_path): if self.path != new_idf_path: self.path = new_idf_path content = open(new_idf_path, 'rb').read().decode('utf-8') self.idf_freq = {} # 解析 idf.txt,拿到词与idf的对应值,key = word,value = idf for line in content.splitlines(): word, freq = line.strip().split(' ') self.idf_freq[word] = float(freq) # 取idf的中位数 self.median_idf = sorted( self.idf_freq.values())[len(self.idf_freq) // 2] 4. 利用tfidf算法提取关键字的接口:extract_tags def extract_tags(self, sentence, topK=20, withWeight=False, allowPOS=(), withFlag=False): """ Extract keywords from sentence using TF-IDF algorithm. Parameter: - topK: return how many top keywords. `None` for all possible words. - withWeight: if True, return a list of (word, weight); if False, return a list of words. - allowPOS: the allowed POS list eg. ['ns', 'n', 'vn', 'v','nr']. if the POS of w is not in this list,it will be filtered. - withFlag: only work with allowPOS is not empty. if True, return a list of pair(word, weight) like posseg.cut if False, return a list of words """ # 判断提取出哪些词性的关键字 if allowPOS: allowPOS = frozenset(allowPOS) # 如果需要提取指定词性的关键字,则先进行词性分割 words = self.postokenizer.cut(sentence) else: # 如果提取所有词性的关键字,则使用精确分词 words = self.tokenizer.cut(sentence) freq = {} # 按照分词结果,统计词频 for w in words: if allowPOS: if w.flag not in allowPOS: continue elif not withFlag: w = w.word wc = w.word if allowPOS and withFlag else w # 该词不能是停用词 if len(wc.strip()) < 2 or wc.lower() in self.stop_words: continue #统计该词出现的次数 freq[w] = freq.get(w, 0.0) + 1.0 # 计算总的词数目 total = sum(freq.values()) for k in freq: kw = k.word if allowPOS and withFlag else k # 依据tf-idf公式进行tf-idf值,作为词的权重。其中,idf是jieba通过语料库统计得到的 freq[k] *= self.idf_freq.get(kw, self.median_idf) / total # 对词频做个排序,获取TopK的词 if withWeight: tags = sorted(freq.items(), key=itemgetter(1), reverse=True) else: tags = sorted(freq, key=freq.__getitem__, reverse=True) if topK: return tags[:topK] else: return tags 5. jieba实现tf-idf总结 1):idf的值时通过语料库统计得到的,所以,实际使用时,可能需要依据使用环境,替换为使用对应的语料库统计得到的idf值。 2):需要从分词结果中去除停用词。 3):如果指定了仅提取指定词性的关键词,则词性分割非常重要,词性分割中准确程度,影响关键字的提取。 【三】TextRank 1. 算法原理介绍 TextRank采用图的思想,将文档中的词表示成一张无向有权图,词为图的节点,词之间的联系紧密程度体现为图的边的权值。计算词的权重等价于计算图中节点的权重。提取关键字,等价于找出图中权重排名TopK的节点。 如上图所示:有A B C D E五个词,词之间的关系使用边连接起来,词之间连接的次数作为边的权值。比如:A和C一起出现了2次,则其边的权重为2,A与B/C/E都有联系,而D仅与B有联系。 所以说,TextRank背后体现的思想为:与其他词关联性强的词,越重要。通俗一点就是:围着谁转,谁就重要。就像大家基本都会围着领导转一样。 2. 图的构建 图的构建分为两部分: 1):确认图的节点之间的联系 2):确认边的权值 jieba是如何做的呢? def textrank(self, sentence, topK=20, withWeight=False, allowPOS=('ns', 'n', 'vn', 'v'), withFlag=False): """ Extract keywords from sentence using TextRank algorithm. Parameter: - topK: return how many top keywords. `None` for all possible words. - withWeight: if True, return a list of (word, weight); if False, return a list of words. - allowPOS: the allowed POS list eg. ['ns', 'n', 'vn', 'v']. if the POS of w is not in this list, it will be filtered. - withFlag: if True, return a list of pair(word, weight) like posseg.cut if False, return a list of words """ # 初始化关键字词性过滤条件 self.pos_filt = frozenset(allowPOS) # 初始化一个无向权值图 g = UndirectWeightedGraph() cm = defaultdict(int) # 使用精确模式进行分词 words = tuple(self.tokenizer.cut(sentence)) # 遍历分词结果 for i, wp in enumerate(words): # 词wp如果满足关键词备选条件,则加入图中 if self.pairfilter(wp): # span为滑动窗口,即词的上下文,借此来实现此的共现,完成词之间的连接。 for j in xrange(i + 1, i + self.span): if j >= len(words): break # 后向词也要满足备选词条件 if not self.pairfilter(words[j]): continue if allowPOS and withFlag: # 共现词作为图一条边的两个节点,共现词出现的次数,作为边的权值 cm[(wp, words[j])] += 1 else: cm[(wp.word, words[j].word)] += 1 # 将 备选词和与该词连接的词加入到graph中,即完成graph的构造 for terms, w in cm.items(): g.addEdge(terms[0], terms[1], w) # 调用graph的rank接口,完成TextRank算法的计算,即计算出各节点的权重 nodes_rank = g.rank() if withWeight: # 对graph中的阶段的权重进行排序 tags = sorted(nodes_rank.items(), key=itemgetter(1), reverse=True) else: tags = sorted(nodes_rank, key=nodes_rank.__getitem__, reverse=True) if topK: return tags[:topK] else: return tags 3. TextRank算法的实现 def rank(self): ws = defaultdict(float) outSum = defaultdict(float) # 计算初始化节点的weight值 wsdef = 1.0 / (len(self.graph) or 1.0) # 初始化各个节点的weight值,并计算各个节点的出度数目 for n, out in self.graph.items(): ws[n] = wsdef outSum[n] = sum((e[2] for e in out), 0.0) # this line for build stable iteration sorted_keys = sorted(self.graph.keys()) # 循环迭代10,迭代计算出各个节点的weight值 for x in xrange(10): # 10 iters for n in sorted_keys: s = 0 # 依据TextRank公式计算weight for e in self.graph[n]: s += e[2] / outSum[e[1]] * ws[e[1]] ws[n] = (1 - self.d) + self.d * s (min_rank, max_rank) = (sys.float_info[0], sys.float_info[3]) for w in itervalues(ws): if w < min_rank: min_rank = w if w > max_rank: max_rank = w for n, w in ws.items(): # to unify the weights, don't *100. ws[n] = (w - min_rank / 10.0) / (max_rank - min_rank / 10.0) return ws 【四】TF-IDF与TextRank算法的比较 1. 从算法原理上来看,基础都是词频统计,只是TD-IDF通过IDF来调整词频的权值,而TextRank通过上下文的连接数来调整词频的权值。TextRank通过滑动窗口的方式,来实现词的位置对词的权值的影响。 2. TD-IDF计算简单,运行性能更好。 「深度学习福利」大神带你进阶工程师,立即查看>>> 最近几年随着大数据技术快速发展与应用,智慧城市随即被正式提出。而且,我们也可以深刻感受到“智慧”正在慢慢改变我们的生活方式和城市。要让城市变智慧的地方太多太多,当前我们接触做多的可能就是外出停车,比如很多商场的停车系统,很多商城的停车场都实现了无人值守。这就是得益于智慧城市停车云平台。 很多人对智慧停车云的概念不是明白,智慧停车平台就是利用云计算、物联网、大数据处理技术等手段,通过可持续运营的商业服务模式,面向各类停车场实现跨区域、多层级的集中监控和管理,为政府、相关主管部门和运营企业提供远程监控、决策支持、统计分析和数据展现等服务,同时可面向公众提供多渠道停车即时讯息的平台。 汽车已经成为了家庭的重要代步工具,车方便了我们的出行,但停车却成为了最大的难题。传统的停车场存在的问题,如:车辆进出场的效率低、找车位难、找车也难、管理难度大、管理成本高。 为了解决传统停车的这些问题,智慧停车解决方案应用而生。市面上做智慧停车解决方案的可以说也是比较多的吧,这里就不与大家讨论解决方案了,还是聊一聊智慧停车云平台的体系与架构! 做智慧停车方案的很多,但能够做智慧停车云平台的就明显的比较少了,之所以少的原因也很简单,技术难度比较大!这里分享一个大快的城市智慧停车云平台解决方案的体系与架构。 关于大快的智慧停车云平台的体系与架构,我直接截图展示一下给大家看,结构脉络比较清晰,比起我用文字来说要简单明了! 这是城市智慧停车云平台的产品体系图! 这是城市智慧停车云平台的系统架构! 这两张图是我找的大快站点上的解决方案里的,看起来可能有点不怎么清晰。感兴趣的可以去看下大快站点的对于城市智慧停车云平台的详细介绍。 「深度学习福利」大神带你进阶工程师,立即查看>>> 摘要: 本文通过使用Keras及一个预训练模型的实例,教你如何通过迁移学习快速简便地解决图像分类问题。 摘要:如何快速简便地解决图像分类问题呢?本文通过使用Keras及一个预训练模型的实例,教你如何通过迁移学习来解决这个问题。 深度学习 正在迅速成为人工智能应用开发的主要工具。在计算机视觉、自然语言处理和语音识别等领域都已有成功的案例。 深度学习擅长解决的一个问题是 图像分类 。图像分类的目标是根据一组合理的类别对指定的图片进行分类。从深度学习的角度来看,图像分类问题可以通过 迁移学习 的方法来解决。 本文介绍了如何通过迁移学习来解决图像分类的问题。 本文中所提出的实现方式是基于Python语言的Keras。 本文结构: 1)迁移学习 2)卷积神经网络 3)预训练模型的复用 4)迁移学习过程 5)深度卷积神经网络上的分类器 6)示例 7)总结 1、迁移学习 迁移学习在计算机视觉领域中是一种很流行的方法,因为它可以 建立精确的模型,耗时更短 。利用迁移学习,不是从零开始学习,而是从之前解决各种问题时学到的模式开始。这样,你就可以利用以前的学习成果(例如VGG、 Inception、MobileNet),避免从零开始。我们把它看作是站在巨人的肩膀上。 在计算机视觉领域中,迁移学习通常是通过使用 预训练模型 来表示的。预训练模型是在大型基准数据集上训练的模型,用于解决相似的问题。由于训练这种模型的计算成本较高,因此,导入已发布的成果并使用相应的模型是比较常见的做法。 2、卷积神经网络(CNN) 在迁移学习中,常用的几个预训练模型是基于大规模 卷积神经网络 的(Voulodimos)。一般来说,CNN被证明擅长于解决计算机视觉方面的问题。它的高性能和易训练的特点是最近几年CNN流行的两个主要原因。 典型的CNN包括两个部分: (1) 卷积基 ,由卷积层和池化层的堆栈组成。卷积基的主要目的是由图像生成特征。为了直观地解释卷积层和池化层,请参阅Chollet 2017。 (2) 分类器 ,通常是由多个全连接层组成的。分类器的主要目标是基于检测到的特征对图像进行分类。全连接层是其中的神经元与前一层中的所有激活神经元完全连接的层。 图1显示了一个 基于CNN的模型体系结构 。这是一个简化的版本,事实上,这种类型的模型,其实际的体系结构比我们在这里说的要复杂得多。 图1.基于CNN的模型体系结果 这些深度学习模型的一个重要方面是,它们可以自动学习分层的特征表示。这意味着由第一层计算的特征是通用的,并且可以在不同的问题域中重用,而由最后一层计算的特征是较特殊的,并且依赖于所选择的数据集和任务。根据Yosinski等人在2014年提出的“如果第一层的特征是通用的并且最后一层的特征是特殊的,那么网络中必定有一个从一般到特殊的转变。因此,我们的CNN的卷积基特别是它下面的层(那些更接近输入的层)适用于一般特征,而分类器部分和卷积基中一些较高的层适用于特殊的特征。 3、预训练模型的复用 当你根据自己的需要重用预训练模型时,首先要删除原始的分类器,然后添加一个适合的新分类器,最后必须根据以下的三种策略之一对模型进行微调: (1)训练整个模型 在这种情况下,利用预训练模型的体系结构,并根据数据集对其进行训练。如果你从零开始学习模型,那么就需要一个大数据集,和大量的计算资源。 (2)训练一些层而冻结其它的层 较低层适用的是通用特征(独立问题),而较高层适用的是特殊特征。这里,我们通过选择要调整的网络的权重来处理这两种情况。通常,如果有一个较小的数据集和大量的参数,你会冻结更多的层,以避免过度拟合。相比之下,如果数据集很大,并且参数的数量很少,那么可以通过给新任务训练更多的层来完善模型,因为过度拟合不是问题了。 (3)冻结卷积基 这种情况适用于训练/冻结平衡的极端情况。其主要思想是将卷积基保持在原始形式,然后使用其输出提供给分类器。把你正在使用的预训练模型作为固定的特征提取途径,如果缺少计算资源,并且数据集很小,或者预训练模型解决了你正要解决的问题,那么这就很有用。 图2以图表的形式说明了这三种策略。 与策略3的这种直接简单的应用不同,策略1和策略2要求你小心谨慎地应对卷积部分中使用的学习率。学习率是一个超参数,它控制你调整网络权重的大小。当你正在使用基于CNN的预训练模型时,使用一个低学习率是比较明智的,因为使用高学习率会增加失去之前所积累知识的风险。假设预训练模型经过了比较好的训练,保持低学习率将确保你不会过早和过度地调整CNN权重。 4、迁移学习过程 从实践的角度来看, 整个迁移学习过程可以概括如下: (1)选择预训练模型. 从大量的预训练模型,可以选择一个适合你要解决的问题的。如果你正在使用Keras,可以立即使用一系列模型,例如VGG、InceptionV3和ResNet5。点击 这里 你可以看到Keras上所有的模型 (2)根据大小相似性矩阵进行分类. 在图3中你用矩阵来控制选择,这个矩阵是根据数据集的大小,以及预训练模型被训练之后的数据集的相似性,来对计算机视觉问题进行分类的。根据经验,如果每个类的图像少于1000个,则认为是小数据集。就数据集的相似性而言,常识占了上风。例如,如果是识别猫和狗,那么ImageNet将是一个类似的数据集,因为它有猫和狗的图像。然而,如果是识别癌细胞,ImageNet就不行了。 (3)微调模型. 这里可以使用大小和相似性矩阵来指导你的选择,然后参考前面提到的重用预训练模型的三个策略。请见图4。 象限 1. 大数据集,但不同于预训练模型的数据集。这种情况将会让你使用策略1。因为有一个大数据集,你就可以从零开始训练一个模型。尽管数据集不同,但在实践中,利用模型的体系结构和权重,通过预训练模型对初始化模型仍然是很有帮助的; 象限 2. 大数据集与类似于预训练模型的数据集。在这里任何选项都有效,可能最有效的是策略2。由于我们有一个大数据集,过度拟合不应该是个问题,所以我们可以尽可能多地学习。然而,由于数据集是相似的,我们可以通过利用以前的知识来节省大量的训练工作。因此,仅对卷积基的分类器和顶层进行训练就足够了。 象限 3. 小数据集,不同于预训练模型的数据集,这里唯一适合的就是策略2。很难在训练和冻结的层数之间平衡。如果你涉及的太深入,那么模型就会过度拟合;如果你仅停留在模型的表面,那么你就不会学到任何有用的东西。也许,你需要比象限2更深入,并且需要考虑数据增强技术。 象限 4. 小数据集,但类似于预训练模型的数据集。你只需删除最后一个全连接层(输出层),并且执行预训练模型作为固定的特征提取器,然后使用结果特征来训练新的分类器。 图3和图4. 尺寸相似性矩阵(左)和微调预训练模型的决策图(右) 5、深度卷积神经网络上的分类器 如前所述,由基于预训CNN的迁移学习方法得到的图像分类模型通常由以下两部分组成: (1)卷积基,实现特征提取; (2)分类器,通过卷积基提取的特征对输入图像进行分类; 由于在本节中我们主要关注分类器部分,所以必须首先说明可以遵循不同的方法来构建分类器: (1)全连接层 . 对于图像分类问题,标准的方法是使用一组下面是softmax激活层的全连接层。softmax激活层输出每个可能的类标签上的概率分布,然后只需要根据最可能的类对图像进行分类。 (2)全局平均池化层 . Lin在2013年提出了一种基于全局平均池化的方法。在这个方法中,我们没有在卷积基最上面添加全连接层,而是添加了一个全局平均池化层,并将其输出直接提供给softmax激活层。 (3)线性支持向量机 . 线性支持向量机(SVM)是另一种可能的方法。根据Tang在2013年所说的,可以利用卷积基在提取的特征上通过训练线性SVM分类器来提高分类精确度。SVM方法的优缺点细节可以在下文中找到。 6. 示例 6.1 准备数据 在例子中,我们将使用原始数据集的小版本,这可以更快地运行模型,适用于那些计算能力有限的任务。 为了构建小版本数据集,我们可以使用Chollet 2017所提供的代码。 # Create smaller dataset for Dogs vs. Cats importos , shutil original_dataset_dir = '/Users/macbook/dogs_cats_dataset/train/' base_dir = '/Users/macbook/book/dogs_cats/data' if not os . path . exists ( base_dir ) : os . mkdir ( base_dir ) # Create directories train_dir = os . path . join ( base_dir , 'train' ) if not os . path . exists ( train_dir ) : os . mkdir ( train_dir ) validation_dir = os . path . join ( base_dir , 'validation' ) if not os . path . exists ( validation_dir ) : os . mkdir ( validation_dir ) test_dir = os . path . join ( base_dir , 'test' ) if not os . path . exists ( test_dir ) : os . mkdir ( test_dir ) train_cats_dir = os . path . join ( train_dir , 'cats' ) if not os . path . exists ( train_cats_dir ) : os . mkdir ( train_cats_dir ) train_dogs_dir = os . path . join ( train_dir , 'dogs' ) if not os . path . exists ( train_dogs_dir ) : os . mkdir ( train_dogs_dir ) validation_cats_dir = os . path . join ( validation_dir , 'cats' ) if not os . path . exists ( validation_cats_dir ) : os . mkdir ( validation_cats_dir ) validation_dogs_dir = os . path . join ( validation_dir , 'dogs' ) if not os . path . exists ( validation_dogs_dir ) : os . mkdir ( validation_dogs_dir ) test_cats_dir = os . path . join ( test_dir , 'cats' ) if not os . path . exists ( test_cats_dir ) : os . mkdir ( test_cats_dir ) test_dogs_dir = os . path . join ( test_dir , 'dogs' ) if not os . path . exists ( test_dogs_dir ) : os . mkdir ( test_dogs_dir ) # Copy first 1000 cat images to train_cats_dir fnames = [ 'cat.{}.jpg' . format ( i ) for i in range ( 100 ) ] forfname in fnames : src = os . path . join ( original_dataset_dir , fname ) dst = os . path . join ( train_cats_dir , fname ) shutil . copyfile ( src , dst ) # Copy next 500 cat images to validation_cats_dir fnames = [ 'cat.{}.jpg' . format ( i ) for i in range ( 200 , 250 ) ] forfname in fnames : src = os . path . join ( original_dataset_dir , fname ) dst = os . path . join ( validation_cats_dir , fname ) shutil . copyfile ( src , dst ) # Copy next 500 cat images to test_cats_dir fnames = [ 'cat.{}.jpg' . format ( i ) for i in range ( 250 , 300 ) ] forfname in fnames : src = os . path . join ( original_dataset_dir , fname ) dst = os . path . join ( test_cats_dir , fname ) shutil . copyfile ( src , dst ) # Copy first 1000 dog images to train_dogs_dir fnames = [ 'dog.{}.jpg' . format ( i ) for i in range ( 100 ) ] forfname in fnames : src = os . path . join ( original_dataset_dir , fname ) dst = os . path . join ( train_dogs_dir , fname ) shutil . copyfile ( src , dst ) # Copy next 500 dog images to validation_dogs_dir fnames = [ 'dog.{}.jpg' . format ( i ) for i in range ( 200 , 250 ) ] forfname in fnames : src = os . path . join ( original_dataset_dir , fname ) dst = os . path . join ( validation_dogs_dir , fname ) shutil . copyfile ( src , dst ) # Copy next 500 dog images to test_dogs_dir fnames = [ 'dog.{}.jpg' . format ( i ) for i in range ( 250 , 300 ) ] forfname in fnames : src = os . path . join ( original_dataset_dir , fname ) dst = os . path . join ( test_dogs_dir , fname ) shutil . copyfile ( src , dst ) # Sanity checks print ( 'total training cat images:' , len ( os . listdir ( train_cats_dir ) ) ) print ( 'total training dog images:' , len ( os . listdir ( train_dogs_dir ) ) ) print ( 'total validation cat images:' , len ( os . listdir ( validation_cats_dir ) ) ) print ( 'total validation dog images:' , len ( os . listdir ( validation_dogs_dir ) ) ) print ( 'total test cat images:' , len ( os . listdir ( test_cats_dir ) ) ) print ( 'total test dog images:' , len ( os . listdir ( test_dogs_dir ) ) ) 6.2 从卷积基中提取特征 卷积基将用于提取特征,这些特征将为我们想要训练的分类器提供输入,以便能够识别图像中是否有狗或猫。 再次把Chollet 2017提供的代码修改了一下,请看代码2。 # Extract features importos , shutil fromkeras . preprocessing . image import ImageDataGenerator datagen = ImageDataGenerator ( rescale = 1 . / 255 ) batch_size = 32 defextract_features ( directory , sample_count ) : features = np . zeros ( shape = ( sample_count , 7 , 7 , 512 ) ) # Must be equal to the output of the convolutional base labels = np . zeros ( shape = ( sample_count ) ) # Preprocess data generator = datagen . flow_from_directory ( directory , target_size = ( img_width , img_height ) , batch_size = batch_size , class_mode = 'binary' ) # Pass data through convolutional base i = 0 forinputs_batch , labels_batch in generator : features_batch = conv_base . predict ( inputs_batch ) features [ i * batch_size : ( i + 1 ) * batch_size ] = features_batch labels [ i * batch_size : ( i + 1 ) * batch_size ] = labels_batch i += 1 ifi * batch_size >= sample_count : break return features , labels train_features , train_labels = extract_features ( train_dir , train_size ) # Agree with our small dataset size validation_features , validation_labels = extract_features ( validation_dir , validation_size ) test_features , test_labels = extract_features ( test_dir , test_size ) 代码2.从卷积基中提取特征。 6.3 分类器 6.3.1 全连接层 我们提出的第一个解决方案是基于全连接层的。在分类器中添加一组全连接层,把从卷积基中提取的特征作为它们的输入。 为了保持简单和高效,我们将使用Chollet2018上的解决方案,并稍作修改,特别地使用Adam优化器来代替RMSProp。 代码3显示了相关的代码,而图5和图6表示了学习曲线。 # Define model fromkeras import models fromkeras import layers fromkeras import optimizers epochs = 100 model = models . Sequential ( ) model . add ( layers . Flatten ( input_shape = ( 7 , 7 , 512 ) ) ) model . add ( layers . Dense ( 256 , activation = 'relu' , input_dim = ( 7 * 7 * 512 ) ) ) model . add ( layers . Dropout ( 0.5 ) ) model . add ( layers . Dense ( 1 , activation = 'sigmoid' ) ) model . summary ( ) # Compile model model . compile ( optimizer = optimizers . Adam ( ) , loss = 'binary_crossentropy' , metrics = [ 'acc' ] ) # Train model history = model . fit ( train_features , train_labels , epochs = epochs , batch_size = batch_size , validation_data = ( validation_features , validation_labels ) ) 代码3.全连接层解决方案 图5.全连接层方案的准确性 图6.全连接层方案的损失 结果简述: (1)验证精确度约为0.85,对于给定数据集的大小,这个结果是非常不错的。(2)这个模型过度拟合,在训练曲线和验证曲线之间有很大的差距。 (3)由于我们已经使用了dropout,所以应该增大数据集来改善结果。 6.3.2 全局平均池化层 这种情况与之前的不同之处在于,我们将添加一个全局平均池化层,并将其输出提供到一个sigmoid激活层,而不是添加一组全连接层。 请注意,我们所说的是sigmoid激活层,而不是SoftMax激活层。我们正在改为sigmoid激活,因为在Keras中,为了执行二进制分类,应该使用sigmoid激活和binary_crossentropy作为损失。 代码4是构建分类器的代码。图7和图8表示所得结果的学习曲线。 # Define model fromkeras import models fromkeras import layers fromkeras import optimizers epochs = 100 model = models . Sequential ( ) model . add ( layers . GlobalAveragePooling2D ( input_shape = ( 7 , 7 , 512 ) ) ) model . add ( layers . Dense ( 1 , activation = 'sigmoid' ) ) model . summary ( ) # Compile model model . compile ( optimizer = optimizers . Adam ( ) , loss = 'binary_crossentropy' , metrics = [ 'acc' ] ) # Train model history = model . fit ( train_features , train_labels , epochs = epochs , batch_size = batch_size , validation_data = ( validation_features , validation_labels ) ) 代码4.全局平均池化解决方案 图7.全局平均池化层方案的准确性 图8.全局平均池化方案的损失 结果简述 : (1)验证精确度与全连接层方案的类似; (2)模型不像以前那样过度拟合; (3)当模型停止训练时,损失函数的结果仍在减小,大概可以通过增加周期数来完善模型; 6.3.3 线性支持向量机 在这种情况下,我们将利用卷积基提取的特征来训练一个线性支持向量机(SVM)的分类器。 为了训练这种分类器,可以使用传统的机器学习方式。因此,我们将使用k-fold cross-validation来估算分类器的误差。由于将使用k-fold cross-validation,我们可以将训练集和验证集连接起来以扩大训练数据(像前面一样保持测试集不变)。 代码5显示了如何联系数据。 # Concatenate training and validation sets svm_features = np . concatenate ( ( train_features , validation_features ) ) svm_labels = np . concatenate ( ( train_labels , validation_labels ) ) 代码 5. 数据连接 最后,我们必须要知道SVM分类器有一个超参数,它是误差项的惩罚参数C。为了优化这个超参数,我们将使用穷举的方法进行网格搜索。 代码6表示用于构建该分类器的代码,而图9表示了学习曲线。 # Build model importsklearn fromsklearn . cross_validation import train_test_split fromsklearn . grid_search import GridSearchCV fromsklearn . svm import LinearSVC X_train , y_train = svm_features . reshape ( 300 , 7 * 7 * 512 ) , svm_labels param = [ { "C" : [ 0.01 , 0.1 , 1 , 10 , 100 ] } ] svm = LinearSVC ( penalty = 'l2' , loss = 'squared_hinge' ) # As in Tang (2013) clf = GridSearchCV ( svm , param , cv = 10 ) clf . fit ( X_train , y_train ) 代码6. 线性 SVM解决方案. 图9.线性支持向量机方案的精确度 结果简述 : (1)模型的精确度在0.86左右,类似于前一个方案; (2)过度拟合即将出现。此外,训练精确度始终是1,这是不正常的,可以解释为过度拟合的现象; (3)模型的精确度应随着训练样本数量的增加而提高。然而,这似乎并没有出现,这可能是由于过度拟合的原因。有趣的是,当数据集增加的时候,模型将会如何反应。 7. 总结 · 本文提出了迁移学习、卷积神经网络和预训练模型的概念; · 定义了基本的微调策略来重新调整预训练模型; · 描述了一种基于数据集的大小和相似度来决定应该使用哪种微调策略的结构化方法; · 介绍了三种不同的分类器,可用于通过卷积基提取的特征上面; · 为文中阐述的三个分类器中的任意一个都提供了关于图像分类的端到端的例子; 阿里云双十一1折拼团活动:已满6人,都是最低折扣了 【满6人】1核2G云服务器99.5元一年298.5元三年 2核4G云服务器545元一年 1227元三年 【满6人】1核1G MySQL数据库 119.5元一年 【满6人】3000条国内短信包 60元每6月 参团地址: http://click.aliyun.com/m/1000020293/ 原文链接 「深度学习福利」大神带你进阶工程师,立即查看>>> 安装 pip3 install --user jupyter 启动 python3 -m IPython notebook 启动界面如下; 安装数据分析和绘图 pip3 install pandas numpy matplotlib 安装可视化库 seaborn pip3 install seaborn if sys.getdefaultencoding() != 'utf-8': reload(sys) sys.setdefaultencoding('utf-8') default_encoding = sys.getdefaultencoding() pip3 install statsmodels pip3 install scikit-learn 「深度学习福利」大神带你进阶工程师,立即查看>>> 【一】词典加载 利用jieba进行分词时,jieba会自动加载词典,这里jieba使用python中的字典数据结构进行字典数据的存储,其中key为word,value为frequency即词频。 1. jieba中的词典如下: jieba/dict.txt X光 3 n X光线 3 n X射线 3 n γ射线 3 n T恤衫 3 n T型台 3 n 该词典每行一个词,每行数据分别为:词 词频 词性 2. 词典的加载 jieba/_init_.py,源码解析如下: # 加载词典 def gen_pfdict(self, f): # 定义字典,key = word, value = freq lfreq = {} # 记录词条总数 ltotal = 0 f_name = resolve_filename(f) for lineno, line in enumerate(f, 1): try: line = line.strip().decode('utf-8') # 取一行的词语词频 word, freq = line.split(' ')[:2] freq = int(freq) # 记录词频与词的关系,这里直接采用dict存储,没有采用Trie树结构 lfreq[word] = freq ltotal += freq # 对多个字组成的词进行查询 for ch in xrange(len(word)): # 从头逐步取词,如 电风扇,则会一次扫描 电,电风,电风扇 wfrag = word[:ch + 1] # 如果该词不在词频表中,将该词插入词频表,并设置词频为0 if wfrag not in lfreq: lfreq[wfrag] = 0 except ValueError: raise ValueError( 'invalid dictionary entry in %s at Line %s: %s' % (f_name, lineno, line)) f.close() return lfreq, ltotal 在词典初始化时,会调用该接口,将词频表存储到变量FREQ中,后续进行分词时,会直接进行该词频表的查询。 调用点如下: def initialize(self, dictionary=None): self.FREQ, self.total = self.gen_pfdict(self.get_dict_file()) 【二】分词 jieba进行分词时,使用词典的最大前缀匹配的方式。当使用精确匹配模型且启动HMM时,对于未登录词(即词典中不存在的词),jieba会使用HMM模型对未登录词进行分词,具体的算法是viterbi算法。 jieba分词的第一步是将待分配的文本,依据词典,生成动态图DAG。 1. 动态图的生成。 # 生成动态图 ''' 例如:sentence = '我爱北京天安门' id = 0 1 2 3 4 5 6 则 DAG = { 0:[0], 1:[1], 2:[2,3], 3:[3], 4:[4,5,6], 5:[5], 6:[6] } ''' def get_DAG(self, sentence): # 查看词典是否已经初始化,若没有,则加载词典,初始化词频表。 # 由此可以看出,jieba采用的是词典懒加载模式 self.check_initialized() # 使用字典结构存储动态图 DAG = {} # 获取待分词的句子的长度 N = len(sentence) # 从头到尾,逐字扫描 for k in xrange(N): tmplist = [] i = k # 获取句子中第k个位置的字 frag = sentence[k] # 如果该字在词频表中,则继续扫描,直到扫描出的词不再词频表中为止 # 即jieba采用的最大前缀匹配法来搜索词 # 例如: 句子为: 我爱北京天安门,frag = 北,则该while循环会一直搜索到京, # 即搜索到北京,而tmplist里面会存储:北,北京两个词 while i < N and frag in self.FREQ: if self.FREQ[frag]: tmplist.append(i) i += 1 frag = sentence[k:i + 1] # 存储一个字到动态图中 if not tmplist: tmplist.append(k) DAG[k] = tmplist return DAG 2. 分词接口流程分析 # 分词接口 def cut(self, sentence, cut_all=False, HMM=True): ''' The main function that segments an entire sentence that contains Chinese characters into seperated words. Parameter: - sentence: The str(unicode) to be segmented. - cut_all: Model type. True for full pattern, False for accurate pattern. - HMM: Whether to use the Hidden Markov Model. ''' # 对待分词的序列进行编解码,解码成utf-8的格式 sentence = strdecode(sentence) # 依据是否使用全模式,确定待使用的正则表达式式, # 结巴先使用正则表达式对待分割内容进行预处理,主要是去除标点符号 if cut_all: re_han = re_han_cut_all re_skip = re_skip_cut_all else: re_han = re_han_default re_skip = re_skip_default # 依据分割模式,设置分词接口,有点类似于函数指针的意思哈 if cut_all: # 全模式,使用__cut_all cut_block = self.__cut_all elif HMM: # 精确匹配模式,且使用HMM对未登录词进行分割,则使用__cut_DAG cut_block = self.__cut_DAG else: # 精确匹配模式,但不使用HMM对未登录词进行分割,则使用__cut_DAG_NO_HMM cut_block = self.__cut_DAG_NO_HMM # 使用正则表达式对待分词序列进行预处理 blocks = re_han.split(sentence) for blk in blocks: if not blk: continue if re_han.match(blk): # 调用分词接口进行分词 for word in cut_block(blk): yield word else: tmp = re_skip.split(blk) for x in tmp: if re_skip.match(x): yield x elif not cut_all: for xx in x: yield xx else: yield x 3. 全模式分词 def __cut_all(self, sentence): # 生成动态图 ''' 例如:sentence = '我爱北京天安门' id = 0 1 2 3 4 5 6 则 DAG = { 0:[0], 1:[1], 2:[2,3], 3:[3], 4:[4,5,6], 5:[5], 6:[6] } ''' dag = self.get_DAG(sentence) old_j = -1 # 扫描动态图 for k, L in iteritems(dag): # 如果只有一个字,且该字未在前面的词中出现过,则生成一个词,否则跳过 # 例如: ‘北京’已经成词了,再次扫描到‘京’时,需要跳过 if len(L) == 1 and k > old_j: yield sentence[k:L[0] + 1] old_j = L[0] else: #对于至少2个字的词,如 4:[4,5,6], 则分割为 天安,天安门 两个词 # 这符合jieba的全模式定义:尽量细粒度的分词 for j in L: if j > k: yield sentence[k:j + 1] old_j = j 4. 精确模式分词,且使用HMM对未登录词进行分割 def __cut_DAG(self, sentence): DAG = self.get_DAG(sentence) route = {} # 使用动态规划算法,选取概率最大的路径进行分词 ''' 例如:sentence = '我爱北京天安门' id = 0 1 2 3 4 5 6 则 DAG = { 0:[0], 1:[1], 2:[2,3], 3:[3], 4:[4,5,6], 5:[5], 6:[6] } ''' # 在进行 4:[4,5,6], 分词时,计算出成词的最大概率路径为4~6,即‘天安门’的概率大于‘天安’ self.calc(sentence, DAG, route) x = 0 buf = '' N = len(sentence) while x < N: y = route[x][1] + 1 l_word = sentence[x:y] if y - x == 1: buf += l_word else: if buf: if len(buf) == 1: yield buf buf = '' else: # 对于未登录词,使用HMM模型进行分词 if not self.FREQ.get(buf): recognized = finalseg.cut(buf) for t in recognized: yield t else: for elem in buf: yield elem buf = '' yield l_word x = y if buf: if len(buf) == 1: yield buf elif not self.FREQ.get(buf): recognized = finalseg.cut(buf) for t in recognized: yield t else: for elem in buf: yield elem 5. 动态规划算法求解最大概率路径。 jieba在使用精确模式进行分词时,会将‘天安门’分割成‘天安门’,而不是全模式下的‘天安’和‘天安门’两个词,jieba时如何做到的呢? 其实,求解的核心在于‘天安门’的成词概率比‘天安’大。 5.1 先看看jieba的动态规划后的结果 ''' 例如:输入的动态图如下 DAG = { 0:[0], 1:[1], 2:[2,3], 3:[3], 4:[4,5,6], 5:[5], 6:[6] } 则,返回值为: R = { 0:(f1,0), 1:(f2,1), 2:(f3,3), 3:(f3,3), 4:(f4,6), 5:(f5,5), 6:(f6,6) } 这个返回值是什么含义呢? 例如:0:(f1,0) ----> id从0到0成词概率最大,最大概率为f1 4:(f4,6), ----> id从4到6成词概率最大,最大概率为f4 依据返回值R,可以得到成词下标,0->0,1->1,2->3,4->6,即:我/爱/北京/天安门 ''' def calc(self, sentence, DAG, route): N = len(sentence) route[N] = (0, 0) logtotal = log(self.total) for idx in xrange(N - 1, -1, -1): route[idx] = max((log(self.FREQ.get(sentence[idx:x + 1]) or 1) - logtotal + route[x + 1][0], x) for x in DAG[idx]) 5.2 动态规划算法 jieba使用的是1-gram模型,即 P(S) = P(W1)*P(W2)*....P(W3). 要求得P(S)取得最大值时,P(W1)/P(W2)..../P(Wn)依次取得什么值。 这里采用动态规划算法来求解该问题。即:argmax P(S) = argmax ( P(Wn)*P(Sn-1)) <=> argmax (log(P(Wn))+log(P(Sn-1))) 当使用jieba中的Route来存储最大概率路径时,即得到 R[i] = argmax(log(Wi/V) + R[i-1]),jieba中使用了一个小技巧,即倒着扫描,这与DAG中的list存储着后向节点有关系。即R[i] = argmax(log(Wi/V) + R[i+1]),于是便有了上述代码。 6. 关于未登录词的HMM求解。 关于HMM介绍这里不做赘述,这里仅描述一下,jieba是怎么依据HMM模型进行分词的。 6.1 问题建模 jieba 使用 BMES对词进行建模。比如:我爱北京天安门,用BMES表示为:SSBEBME。只要拿到了SSBEBME这个字符串,就可以对“我爱北京天安门”进行分词,按照该字符串,分词结果为: 我/爱/北京/天安门。 那么问题来了,如何由“我爱北京天安门”得到“SSBEBME”这个字符串呢? 我们可以将“我爱北京天安门”理解为观察结果,“SSBEBME”理解为隐藏的词的状态的迁移结果,即HMM中的隐式状态转移。那么问题就成了:如何求解:P(S|O)= P(隐式状态迁移序列|观测序列). 6.2 问题求解 依据贝叶斯公式: P(S|O) = P(S,O)/P(O) = P(O|S)P(S)/P(O) 结合HMM相关知识,进一步求解P(S|O) = P(St|Ot) = P(Ot|St)*P(St|St-1)/P(Ot),由于每一个t时刻,P(Ot)都一样,可以去掉,因此: P(St|Ot) = P(Ot|St)*P(St|St-1),其中 P(Ot|St)为发射概率,即HMM的参数Bij,P(St|St-1)是HMM的状态转移矩阵参数,即Aij。 另外还已知初始状态向量参数,因此可以求解出P(S|O)的最大值时的概率路径,也就是 “SSBEBME”。 6.3 jieba中的HMM参数值 初始状态概率在 jieba/finalseg/prop_start.py里面。 P={'B': -0.26268660809250016, 'E': -3.14e+100, 'M': -3.14e+100, 'S': -1.4652633398537678} 状态转移矩阵参数在 jieba/finalseg/prop_trans.py P={'B': {'E': -0.510825623765990, 'M': -0.916290731874155}, 'E': {'B': -0.5897149736854513, 'S': -0.8085250474669937}, 'M': {'E': -0.33344856811948514, 'M': -1.2603623820268226}, 'S': {'B': -0.7211965654669841, 'S': -0.6658631448798212}} 发射概率在 jieba/finalseg/prop_emit.py 6.4 jieba中这些HMM的参数是怎么来的呢? 据jieba官方介绍,是采用人明日报的语料库 和另外一个分词工具训练来的。总而言之,这些参数是依据特殊语料统计得到的。如果使用jieba的默认参数导致分词不理想时,应该考虑到重新训练自己的HMM参数。 6.5 jieba HMM源码解析 源码路径在 jieba/finalseg/_init_.py 主体代码流程如下: def cut(sentence): # 先解码 sentence = strdecode(sentence) # 再按照正则表达式进行初步分割 blocks = re_han.split(sentence) for blk in blocks: if re_han.match(blk): # 依据HMM模型,对未登录词进行分割 for word in __cut(blk): if word not in Force_Split_Words: yield word else: for c in word: yield c else: tmp = re_skip.split(blk) for x in tmp: if x: yield x HMM分词如下: def __cut(sentence): global emit_P # 使用viterbi算法进行HMM求解,即生成 BMES的状态迁移序列 prob, pos_list = viterbi(sentence, 'BMES', start_P, trans_P, emit_P) begin, nexti = 0, 0 # print pos_list, sentence # 依据 BMES的状态迁移序列,进行分词 for i, char in enumerate(sentence): pos = pos_list[i] if pos == 'B': begin = i elif pos == 'E': yield sentence[begin:i + 1] nexti = i + 1 elif pos == 'S': yield char nexti = i + 1 if nexti < len(sentence): yield sentence[nexti:] 这里使用了viterbi算法求解状态转移序列。关于viterbi算法,注意两点:该算法的推导时自顶向下,但是最终的计算是自底向上,体现在分词上,就是从前往后计算。求解的目的也是找到一条最大概率路径,因此也是动态规划算法。这里就不推导了。 【三】总结 jieba分词,对于登录词,使用最大前缀匹配的方法,其中精确模式使用了动态规划算法来计算最大概率路径,进而得到最佳分词。对于未登录词,jieba使用HMM模型来求解最佳分词。 两种方式,都用到了词典与模型的HMM模型参数。因此,对于某些分词场景,可以使用自己的词典和自己的语料库训练出来的HMM模型参数进行中文分词,进而提升分词准确性。 jieba分词的核心理论基础为:统计和概率论。不知道基于深度学习的算法,是否可以进行中文分词。 「深度学习福利」大神带你进阶工程师,立即查看>>> 人工智能、机器学习都已走进了我们的日常,尤其是愈演愈热的大数据更是跟我们的生活息息相关,做 人工智能、数据挖掘的人在其他人眼中感觉是很高大上的,总有一种遥不可及的感觉,在我司也经常会听到数据科学部的同事们提到 机器学习、数据挖掘 之类的词。但这些名词真的跟我们移动开发就没直接关系了吗? 作为移动开发者来说,无时无刻不被这些名词狠狠地敲打着脆弱的内心。???? ???? ???? 何时才能够将机器学习、深度学习应用在移动端,敲响移动端机器学习工业化的大门呢? 想象一下,某一天你身处一个完全陌生的环境,周围都是陌生的事物,而运行在iPhone的某个APP却对这个环境了如指掌,你要做的就是打开这个APP,输入你需要了解的事物,iPhone告诉你这个事物的信息,你也就没有了陌生事物了。世界就在眼前! 如下图: 上面物体的识别准确率还是蛮不错的,基本识别出了键盘(49%的概率)、鼠标(46%的概率)和水杯(24%的概率)。 但是在某些事物的识别准确度方便却差强人意,比如下图: Phone 8被识别成了iPod(59%的概率),而iPod的却是不怎么敢认(10%的概率)。想想最崩溃的估计是iPhone 8了,身价直接被降了好几个等级。 上面的例子来自于TensorFlow官方iOSDemo,暂且不评述TensorFlow的识别准确度如何,毕竟它还年轻,但是仅凭其识别能力的体现,也给机器学习在移动端的运用带来了无限的可能。 一、TensorFlow(简称TF) 去年,Google资深系统专家Jeff Dean在湾区机器学习大会上隆重介绍了其第二代深度学习系统TensorFlow,一时间网络上针对TensorFlow的文章铺天盖地,揭秘TensorFlow:Google开源到底开的是什么?、Google开源TensorFlow系统,这背后都有什么门道?、如何评价Google发布的第二代深度学习系统TensorFlow?等等文章,TensorFlow的燎原之火一直在燃烧蔓延着,其GitHub上的开源库在此文撰写时,也已经被star:27550,fork:11054了。???? ???? ???? ???? ???? 不负众望,Google一直宣称平台移植性非常好的TensorFlow,终于在2016年6月27日,发布0.9版本,宣布移动端支持。TensorFlow v0.9 now available with improved mobile support( 有墙???? ),同时也给出了移动端的Demo,对于代码为生的程序员,身处大数据处理为主导的TalkingData,也小试身手了一把,下载TensorFlow源码,查看编译指南,开始跳坑、填坑之路,也成就了此篇拙文的产生。 如果对Python编程、网络爬虫、机器学习、数据挖掘、web开发、人工智能、面试经验交流。感兴趣可以519970686,群内会有不定期的发放免费的资料链接,这些资料都是从各个技术网站搜集、整理出来的,如果你有好的学习资料可以私聊发我,我会注明出处之后分享给大家。 二、从TensorFlow到iOS静态库 对于iOS平台下如何使用TensorFlow,TensorFlow也给出了详细的编译脚本命令,详情请查看官方文档的命令。 第一步. 工具准备 工欲善其事必先利其器,在开始编译工作之前,需要准备一些编译所必须的工具: Homebrew: Mac os x 上包管理工具 $ /usr/bin/ruby -e ``"$(curl -fsSL [https://raw.githubusercontent.com/Homebrew/install/master/install](https://raw.githubusercontent.com/Homebrew/install/master/install))" Homebrew安装好之后,依次安装三个辅助性编译工具: $ brew install libtool $ brew install autoconf $ brew install automake 第二步. 克隆TensorFlow Google以Apache 2.0开源协议将TensorFlow开源在GitHub上,我们可以直接使用TensorFlow源码。 在任意你想存放TensorFlow源码的地方(建议不要放在桌面。_),clone项目。 $ git clone [https://github.com/tensorflow/tensorflow](https://github.com/tensorflow/tensorflow) 第三步. 编译前准备 在TensorFlow的tensorflow/contrib/makefile/目录下,有很多可使用的编译脚本,其中build_all_ios.sh脚本专门用来一键编译TensorFlow iOS静态库。虽然可以直接使用此脚本进行一键编译,但是因为有墙,某些依赖需要提前做处理。 1、下载protobuf protobuf 是编译前唯一需要特殊处理的依赖库,[点击下载](https://github.com/google/protobuf/archive/master.zip),下载protobuf之后,解压,备用。 2、下载googlemock 虽然protobuf编译脚本autogen.sh中的googlemock链接地址https://googlemock.googlecode.com/files/gmock-1.7.0.zip无法直接下载到,但是细心的人会发现,在浏览器中输入 https://googlemock.googlecode.com/地址后,会跳转到https://github.com/google/googlemock地址,google在GiHub上的仓库地址。而GitHub上的仓库,我们可以直接的下载,克隆等。 我们直接在GitHub上下载googlemock(点击下载),下载完成后,修改压缩包名字为gmock-1.7.0.zip,修改后将此压缩包移至上一步protobuf文件夹目录下,备用。 3、修改下载依赖脚本,移除protobuf的下载 在tensorflow/contrib/makefile/目录下,download_ dependencies.sh 脚本用来下载相关依赖,打开此脚本文件,注释掉或者直接删掉git clone https://github.com/google/protobuf.git ${DOWNLOADS_DIR}/protobuf部分,目的是不让脚本去下载protobuf。 上面三步准备好后,接下来就进入静态库编译了。 第四步. 一键编译 前面已经知道在TensorFlow文件夹tensorflow/contrib/makefile/目录下的build_all_ios.sh脚本是用来编译iOS静态库的脚本,因此可以直接执行此脚本,开始静态库的编译工作了。 但是有一个问题大家可能会发现,由于编译TensorFlow需要用到protobuf,但是protobuf使我们自己手动下载的,该怎么让手动下载的protobuf能够直接让build_all_ios.sh脚本使用呢? 答案是复制、粘贴。可能有些low,但是有效。执行命令 build_all_ios.sh之后,立即把之前手动下载的protobuf文件夹拷贝进tensorflow/contrib/makefile/downloads目录。(放心,你拷贝的速度会很快,不会影响编译的执行的。_) $ build_all_ios.sh 一切准备就绪,接下来就是静静的等待编译完成了。在Mac编译的过程中,建议插上电源,最好不要让设备休眠断电,也最好不要去干别的东西,出去溜达一圈,回来后就看到战果了。 编译完成之后,会在tensorflow/contrib/makefile/gen/目录下看到编译的结果,关于这些静态库该如何使用,自己的项目如何应用,请参考 TensorFlow iOS Examples 。 三、遇到的问题 1、googlecode.com被墙了,需要翻墙!(目前测试挂了VPN也没用),这也是上面编译前准备为什么要那么做的原因。 curl: (7) Failed to connect to googlemock.googlecode.com port 443: Operation timed out 解决: 请参考 『第三步. 编译前准备』。 2、没有Xcode。 xcrun: error: SDK "iphoneos" cannot be located xcrun: error: SDK "iphoneos" cannot be located xcrun: error: unable to lookup item 'PlatformPath' in SDK 'iphoneos' + IPHONEOS_PLATFORM= 解决:安装Xcode,从上面报错的命令中可以看到,在编译静态库的过程中使用了xcrun,而此命令是xCode本身具有的能力。 3、你的Xcode版本不是7.3或以后,或者你有多个Xcode,而默认的安装路径版本不是7.3或以后。 error: Xcode 7.3.0 or later is required. exit 1 解决:更新Xcode至最新版本,并且保证默认路径下是最新/版本。 如果Xcode是7.3,并且没有条件更新Xcode,你可以修改tensorflow/contrib/makefile/compile_ios_tensorflow.sh 里的REQUIRED_XCODE_VERSION=7.3.0,为REQUIRED_XCODE_VERSION=7.3。(这样修改,目前还不确定会不会带来一些其他影响,最好是升级你的Xcode) 「深度学习福利」大神带你进阶工程师,立即查看>>> 大数据技术的发展与应用已经在深刻地改变和影响我们的日常生活与工作,可以预见的是在大数据提升为国家战略层面后,未来的几年里大数据技术将会被更多的行业应用。 相信很多人对于大数据技术的应用还是处于一个非常陌生的阶段,可能在很多地方听说过大数据,但具体应用在哪方面可能就并不清楚了。举个最简单的的例子,前段时间新闻报道说警方在某明星的演唱会上抓捕了一名在逃嫌犯,而这名嫌犯是在进入现场时被监控识别出来的。这种就是大数据技术的一种具体的应用表现。这个案例可能不是很贴切,但应该很好理解了吧! 企业对大数据技术的需求尤其是在移动互联网进入到井喷式发展阶段后变得尤为强烈。当然,我们这里探讨的仅是大型企业而非中小型企业。中小型企业当然也是可以应用大数据技术,但着实没有这样做的必要,因为中小企业基本不会产生大量的数据,换句话就是中小企业产生的这些数据不能用体现大数据技术在处理这些数据方面的优势。 企业大数据解决方案在市场上不能说是很多吧,毕竟大数据技术难度高度摆在这里,不是一般的企业就可以去做的。不同的解决方案会一些方面存在一定的差异,这里给大家介绍分析一下DKH大数据解决方案的的优势。 DKH大数据解决方案:以大数据云计算技术为核心的,统一数据管控解决方案 以大快的DKH为基础,增加数据可视化,异构数据全文搜索,跨平台数据整合,NLP以及人工只能等基础功能,面向大中型企业及政府机构,提供的基于大数据与云计算技术的新一代跨平台数据中心解决方案。(备注:资料来源于大快搜索) 以DKH(大快的发行版hadoop)为核心,增加数据可视化、数据权限管控,异构数据管理、全文搜索引擎、语义搜索和自然语言处理等技术,实现大数据的跨平台整合管控。 DKH大数据解决方案优势: 数据互联互通,支持多数据集实时同步; 支持数据资源管理,实现多源异构数据的整合管控; 提供完善的大数据分析基础运行环境,提供统一二次开发接口; 动态数据可视化,支持权限管理 集成基于人工智能的全文搜索引擎和语义搜索技术 提供容灾备份功能吗,原有数据可无缝全自动灾备还原; 全程管控,实现数据交换全流程跟踪及服务状态实时监控; 简捷极致的运维管理,有效降低运维难度和管理成本。 「深度学习福利」大神带你进阶工程师,立即查看>>> NumPy是在python中处理数据的最基本和最强大的包。 如果您打算从事数据分析或机器学习项目,那么对numpy的充分理解几乎是必须的。 其他用于数据分析的软件包(如pandas)是建立在numpy之上,用于构建机器学习应用的scikit-learn软件包也在numpy上运行。 但对于.NET开发人员来说,却没有这样的强大工具库。 虽然有像Deedle和Math.NET这样的开源库,但它们不是很容易使用,也不能借用很多现有的python代码。 NumSharp(Numerical .NET)可以说是C#中的线性代数库。 它是用C#编写的,符合.netstandard 2.0库标准。 它的目标是让.NET开发人员使用NumPy的语法编写机器学习代码,从而最大限度地借鉴现有大量在python代码的转译成本。 NumSharp使用最新的Span技术安全高效地访问内存,优化每个模拟API的性能,确保最底层的NDArray达到最佳性能状态。NumSharp对于在数组上执行数学和逻辑运算非常有用。 它为.NET中的n阵列和矩阵的操作提供了大量有用的功能。 让我们给出一个代码片段来说明如何使用NumSharp。 // 初始化一个NumSharp实例,类名故意叫NumPy var np = new NumPy(); // 产生一个数字0到9的向量 np.arange(10) // 产生一个3维张量 np.arange(12).reshape(2, 3, 2); // 产生10个0到9的随机数,并转换成5*5的矩阵 np.random.randint(low: 0, high: 10, size: new Shape(5, 5)); 上面的代码是不是看起来否非常接近python代码?简直就是如出一辙。NumSharp的目的就是让你可以轻松的复制粘贴Python代码。 如何安装: PM> Install-Package NumSharp 如果您觉得这个图书馆对您有帮助,请积极参与讨论。 欢迎在 Github 上为我点赞。 这里还有个 神经网络代码 ,是完全基于NumSharp编写的。 「深度学习福利」大神带你进阶工程师,立即查看>>> #导入 直接将文本load成numpy.ndarray,如果类型不是默认类型(dtype=float)会导致部分数据nan,skip_footer world_alcohol = numpy.genfromtxt("world.txt", delimiter=",", #以“,”为列的分隔符 skip_header=1, #跳过第一行 usecols=(0, -1), #只读取的列 dtype="U75", #设定类型 names="A, B, C", #设定列名 missing_values={0:"N/A", 'b':" ", 2:"???"}, #某列缺失值定义 filling_values={0:0, 'b':0, 2:-999} #某列缺失值替换 ) #初始化 vector = numpy.array([5, 10, 15, 20]) matrix = numpy.array([[5, 10, 15], [20, 25, 30], [35, 40, 45]]) np.zeros ((3,4)) np.ones( (2,3,4), dtype=np.int32 ) np.arange( 0, 2, 0.3 ) #0-2,以0.3为步长 np.random.random((2,3)) #2行3列的0-1 array from numpy import pi np.linspace( 0, 2*pi, 100 ) #设置100个点 z = np.linspace(0,10,11,endpoint=True,retstep=True) #生成0~10之间均匀分布的11个数,包括0和10 help(np.linspace) a=[1,2,3] np.diag(a) 是生成1,2,3 为对角线的方阵 #常用方法属性 查看维度:vector.shape 查看类型:vector.dtype 更改类型:vector = vector.astype(float) type(d) 和 d.dtype 一个返回的是d 的数据类型 nd.array 另一个返回的是数组中内容的数据类型 类型NumPy array必须所有数据是相同类型 a.ndim #查看维度坐标的数量,axes (dimensions)的数量 a.dtype.name a.size#总数 #索引 vector[1,4]第一行第四列的值,从0开始.vector[0:3]是0-2的数列 matrix[:,1],所有行的第2列,matrix[:,0:2],所有行的1,2列 matrix = numpy.array([ [5, 10, 15], [20, 25, 30], [35, 40, 45] ]) matrix[1:3,1:3] [[20 25] [35 40]] #比较 vector = numpy.array([5, 10, 15, 20]) vector == 10 -> array([False, True, False, False], dtype=bool) 比较每一个元素 通过比较的bool结果索引 vector = numpy.array([5, 10, 15, 20]) equal_to_ten = (vector == 10) print equal_to_ten -> [False True False False] print(vector[equal_to_ten]) -> [10] matrix = numpy.array([ [5, 10, 15], [20, 25, 30], [35, 40, 45] ]) second_column_25 = (matrix[:,1] == 25) print second_column_25 -> [False True False] print(matrix[second_column_25, :]) -> [[20 25 30]] equal_to_ten_and_five = (vector == 10) & (vector == 5) #进行与或非操作 vector = numpy.array([5, 10, 15, 20]) equal_to_ten_or_five = (vector == 10) | (vector == 5) vector[equal_to_ten_or_five] = 50 print(vector) -> [50 50 15 20] matrix = numpy.array([ [5, 10, 15], [20, 25, 30], [35, 40, 45] ]) second_column_25 = matrix[:,1] == 25 print second_column_25 -> [False True False] matrix[second_column_25, 1] = 10 print matrix -> 中间25->10 #运算 vector = numpy.array([5, 10, 15, 20]) 求和:vector.sum() 求平均:vector.mean() numpy.exp():返回e的幂次方 matrix.sum(axis=1) # 1是按行相加,0是按列相加 is_value_empty = numpy.isnan(world_alcohol[:,4]) #判断是不是nan,各个位置是bool值 z = np.zeros((5,5)) z += np.arange(5) print np.arange(5) -> [0 1 2 3 4] print z [[0. 1. 2. 3. 4.] [0. 1. 2. 3. 4.] [0. 1. 2. 3. 4.] [0. 1. 2. 3. 4.] [0. 1. 2. 3. 4.]] a1=mat([1,1]); a2=mat([2,2]); a3=multiply(a1,a2) np.array的+/-/平方**2/开方np.sqrt(A)都是对应元素操作,<>也是对应元素,返回对应的bool值 两种点乘操作:A.dot(B) np.dot(A, B) A.T #转置 np.floor()#各个元素向下取整 #变形 a = np.arange(15).reshape(3, 5)#更改形状 reshape:有返回值,所谓有返回值,即不对原始多维数组进行修改; resize:无返回值,所谓有返回值,即会对原始多维数组进行修改; 将多维数组降位一维: numpy.ravel() #返回的是视图(view,也颇有几分C/C++引用reference的意味),会影响原始矩阵 numpy.flatten() #返回一份拷贝,对拷贝所做的修改不会影响(reflects)原始矩阵 #拼接 np.hstack((a,b))#列相拼接,多了列,行数不变 np.vstack((a,b))#行拼接,多了行,列数不变 np.vsplit(a,3)#将a从行切出3个array b = a #是一个对象 相等 变化牵连 c = a.view() #创建一个新对象 不相等 变化不牵连 d = a.copy() #完全复制一个对象 不相等 变化不牵连 ind = data.argmax(axis=0) np.argmax(data,axis=0) #array每行上最大数的索引下标 (3,)#一维数组 (1,3)#二维 import numpy as np data = np.sin(np.arange(20)).reshape(5,4) print data [[ 0. 0.84147098 0.90929743 0.14112001] [-0.7568025 -0.95892427 -0.2794155 0.6569866 ] [ 0.98935825 0.41211849 -0.54402111 -0.99999021] [-0.53657292 0.42016704 0.99060736 0.65028784] [-0.28790332 -0.96139749 -0.75098725 0.14987721]] ind = data.argmax(axis=0) print ind - > [2 0 3 1] data_max = data[ind, xrange(data.shape[1])] print data_max ->[0.98935825 0.84147098 0.99060736 0.6569866 ] all(data_max == data.max(axis=0)) -> True #numpy.tile(A,reps) numpy.tile(A,reps) #tile共有2个参数,A指待输入数组,reps则决定A重复的次数。整个函数用于重复数组A来构建新的数组。 numpy.tile([1,2,3],2) -> array([1, 2, 3, 1, 2, 3]) numpy.tile([1,2,3],(1,2)) -> array([[1, 2, 3, 1, 2, 3]]) numpy.tile([1,2,3],(2,1)) ->array([[1, 2, 3],[1, 2, 3]]) 注意维度:一维数组shape为(3,),扩充至2维则shape值为(1,3),扩充至3维则shape值为(1,1,3) y = x.argsort() #argsort()函数是将x中的元素从小到大排列,提取其对应的index(索引),然后输出到y a = np.array([4, 3, 1, 2]) j = np.argsort(a) print j -> [2 3 1 0] print a -> [4 3 1 2] print a[j] -> [1 2 3 4] #sort() # 直接对对象进行排序,不会产生一个新数组,而是在原数组的基础上进行修改 # None : 如果待排序的对象是一个视图的话,则原始数据将会被修改 obj.sort() # 这种方式会为原数组创建一个已排序的副本,所以并不会对原数组进行修改 np.sort(obj) # 相同之处:两种排序都可以接受一个axis参数,用于对相应的行或者列进行排序 # Note : 两个排序方法都不可以被设置为降序,只能是升序, ndarray.sort(axis=-1, kind='quicksort', order=None) 或者:ndarray.sort(axis=-1, kind='quicksort', order=None) 参数 描述 axis 排序沿数组的(轴)方向,0表示按行,1表示按列,None表示展开来排序,默认值为-1,表示沿最后的轴排序 kind 排序的算法,提供了快排'quicksort'、混排'mergesort'、堆排'heapsort', 默认为‘quicksort' order 排序的字段名,可指定字段排序,默认为None #meshgrid() [X,Y]=meshgrid(x,y) [X,Y]=meshgrid(x)=[X,Y]=meshgrid(x,x) m, n = (5, 3) x = np.linspace(0, 1, m) y = np.linspace(0, 1, n) X, Y = np.meshgrid(x,y) X,Y:3行5列 #NumPy 用字符编码来表示数据类型 数据类型 字符编码 整数 i 无符号整数 u 单精度浮点数 f 双精度浮点数 d 布尔值 b 复数 D 字符串 S Unicode U Void V #其他操作: z[1::2,::2] = 1 z[::2,1::2] = 1 z = np.random.random((10,10)) zmin,zmax = z.min(),z.max() #归一化,将矩阵规格化到0~1,即最小的变成0,最大的变成1,最小与最大之间的等比缩放 z = 10*np.random.random((5,5)) print z zmin,zmax = z.min(),z.max() z = (z-zmin)/(zmax-zmin) print z 交换第0,1行:a[[0,1]] = a[[1,0]] #找出数组中与给定值最接近的数 z = np.array([[0,1,2,3],[4,5,6,7]]) a = 5.1 print np.abs(z-a).argmin() -> 5 #判断二维矩阵中有没有一整列数为0? z = np.random.randint(0,3,(2,10)) print z -> [[1 1 2 0 0 1 1 0 2 2],[0 0 2 1 0 2 1 0 1 0]] print z.any(axis=0) -> [ True True True True False True True False True True] 「深度学习福利」大神带你进阶工程师,立即查看>>> 摘要: 10月27日下午,2018中国计算机大会上举办了主题“存储软硬件之国产化挑战与机遇”的技术论坛,共同探讨存储软硬件栈上的关键系统与技术的国产化发展道路。论坛上,阿里数据库资深技术专家黄贵针对存储软硬件国产化进行了《存储新硬件给数据库自研带来的机会》的报告。 10月27日下午,2018中国计算机大会上举办了主题“存储软硬件之国产化挑战与机遇”的技术论坛,共同探讨存储软硬件栈上的关键系统与技术的国产化发展道路。论坛上,阿里数据库资深技术专家黄贵针对存储软硬件国产化进行了《存储新硬件给数据库自研带来的机会》的报告。 专家简介: 黄贵,阿里巴巴数据库事业部资深技术专家,近10年一直从事分布式存储、分布式数据库的设计与研发工作,经历过连续6年双11的数据库大考,见证了阿里从商业数据库到开源数据库再到自主研发分布式数据库的过程。目前的方向是打造全面兼容MySQL生态,新一代跨地域高可用,高可扩展,高性能低成本分布式数据库X-DB。 首先,黄贵介绍了阿里巴巴随着业务迅猛增长而实现的数据库的进化,一直发展到目前已被广泛应用到阿里各项业务的异地多活,云化,分布式数据库X-DB。 其次,黄贵详述了阿里巴巴数据库面临的特殊挑战,以及为了应对这些挑战而做的设计,具体思路就是利用现代存储的多层次结构,根据业务访问数据特点,设计出一套分层的存储架构,结合了内存数据库和磁盘数据库技术,同时达成高性能和低成本。
最后,黄贵详述了数据库存储引擎X-Engine的设计思想,包括存储方式、应对超大并发事务的流水线事务处理模式、元数据索引结构、数据布局、数据访问加速、数据压缩等特性,同时指出其利用NVM引入新的存储层次,将存储层次分为冷数据、暖数据及热数据三类,三个层次采用Flash/HDD、NVM、DRAM不同存储类型,以应对不同数据特性。X-Engine结合大数据访问热点集中的特点,采用了基于数据访问频率区分冷热数据,并基于数据的冷热进行封层存储的架构,并在此架构上进行充分的优化以满足不断增长的需求。 了解更多阿里云产品请戳链接: https://www.aliyun.com/product/list?utm_code=p_2018090501 阿里云双十一1折拼团活动:已满6人,都是最低折扣了 【满6人】1核2G云服务器99.5元一年298.5元三年 2核4G云服务器545元一年 1227元三年 【满6人】1核1G MySQL数据库 119.5元一年 【满6人】3000条国内短信包 60元每6月 参团地址: http://click.aliyun.com/m/1000020293/ 原文链接 「深度学习福利」大神带你进阶工程师,立即查看>>> 摘要: 10月27日下午,2018中国计算机大会上举办了主题“数据中心计算”的技术论坛,一起探讨解决数据中心所面临的挑战。论坛上,阿里云分布式存储团队高级技术专家田磊磊进行了《阿里云文件存储的高性能架构演进之路》的报告。 10月27日下午,2018中国计算机大会上举办了主题“数据中心计算”的技术论坛,一起探讨解决数据中心所面临的挑战。论坛上,阿里云分布式存储团队高级技术专家田磊磊进行了《阿里云文件存储的高性能架构演进之路》的报告。 专家简介 田磊磊,阿里云存储团队高级技术专家,主要从事分布式文件系统领域工作多年,具有丰富的分布式存储开发经验。 田磊磊从存储介质、网络的发展以及人工智能、高性能计算、基因等领域的兴起给高性能计算带来的机遇和挑战出发,介绍了新一代Cloud Native文件存储在应用中所需要的特性以及更高的要求,尤其是要求高吞吐、高iops、低延时。随后,他又详述了阿里云文件存储如何架构在飞天盘古之上,同时简述了阿里云文件存储的高效元数据、高效线程模型以及文件协议等典型特性。
最后,田磊磊介绍了阿里云在高性能计算领域的最新实践,包括数据迁移、多种数据接入、云监控、云上大规模渲染。
了解更多阿里云产品请戳链接: https://www.aliyun.com/product/list?utm_code=p_2018090501 原文链接 「深度学习福利」大神带你进阶工程师,立即查看>>> 摘要: 近日,为了提升用户网站访问体验,阿里云虚拟主机宣布推出流量型独享虚拟主机新规格,流量型独享虚拟主机新规格可以提供高速流量包,提高访问速度。在高速流量包用尽后,网站也不会关停,可自动降为低带宽模式,保证网站一直在线。 近日,为了提升用户网站访问体验,阿里云虚拟主机宣布推出流量型独享虚拟主机新规格,流量型独享虚拟主机新规格可以提供高速流量包,提高访问速度。在高速流量包用尽后,网站也不会关停,可自动降为低带宽模式,保证网站一直在线。 全球首发,独享虚拟主机和流量包会结合出什么火花? 与共享云虚拟主机相比,独享云虚拟主机最大的不同点是用户可以资源独享,享有整个服务器的软硬件资源,即每台轻云服务器的 CPU、内存、带宽、硬盘均为独享,因此是企业建站的首选。稳定性具备了,提升访问速度也是重中之重。 阿里云独享虚拟主机流量包新规格是全球第一个将独享虚拟主机和流量包结合的产品,既带有独享虚拟主机的稳定特性,又提升了网站访问速度,同时最低带宽能够保证用户网站一直在线。 用户购买主机后开始计算高速流量,如果当月高速流量耗尽,则主机网络速度降为保底带宽1Mbps。保底带宽下流量速度不限制。流量包每月1日重置,同时峰值带宽恢复。 相较于阿里云之前推出的独享虚拟主机带宽型,独享虚拟主机流量型的网络峰值访问速度有了明显提升,其中基础版和标准版均比之前的带宽规格提升了1Mbps,而高级版和豪华版则相对之前(2Mbps)提升了4Mbps和8Mbps,网络访问速度最高提升了400%。 此次阿里云流量型独享虚拟主机新规格在国内主要地区均有上线,了解更多阿里云流量型独享虚拟主机新规格详情,请戳链接: https://wanwang.aliyun.com/hosting?spm=a2c4e.11155435.1146454.867.450c3312naCJmF 原文链接 |