tonglin0325的个人主页

Python自然语言处理学习——jieba分词

jieba——“结巴”中文分词sunjunyi开发的一款Python中文分词组件,可以在Github上查看jieba项目

要使用jieba中文分词,首先需要安装jieba中文分词,作者给出了如下的安装方法

1.全自动安装:easy_install jieba 或者 pip install jieba / pip3 install jieba

2.半自动安装:先下载 http://pypi.python.org/pypi/jieba/ ,解压后运行 python setup.py install

3.手动安装:将 jieba 目录放置于当前目录或者 site-packages 目录

 

作者介绍其采用的算法

1.基于前缀词典实现高效的词图扫描,生成句子中汉字所有可能成词情况所构成的有向无环图 (DAG)

2.采用了动态规划查找最大概率路径, 找出基于词频的最大切分组合

3.对于未登录词,采用了基于汉字成词能力的 HMM 模型,使用了 Viterbi 算法

 

主要功能

1.分词

  分词功能主要有两个方法 **jieba.cut **和 jieba.cut_for_search

其中 jieba.cut方法 接受三个输入参数:

全文 >>

机器学习——利用PCA来简化数据

降维技术好处

  1.使得数据集更易使用

  2.降低很多算法的计算开销

  3.取出噪声

  4.使得结果易懂

 

已标注和未标注的数据上都有降维技术降维的方法

  1.主成分分析(Principal Component Analysis,PCA)。在PCA中,数据从原来的坐标系转换到新的坐标系,新坐标系的选择是由数据本身决定的。第一个新坐标轴选择的是原始数据中方差最大的方向,第二个新坐标轴的选择和第一个坐标轴正交且具有最大方差的方向。该过程中一直重复,重复次数为原始数据中特征的数目。我们会发现,大部分方差都包含在最前面的几个新坐标轴中。因此,我们就可以忽略余下的坐标轴,即对数据进行了降维处理。

  2.因子分析(Factor Analysis)。在因子分析中,我们假设在观察数据的生成中有一些观察不到的隐变量(latent variable)。假设观察数据是这些隐变量和某些噪声的线性组合。那么隐变量的数据可能比观察数据的数目少,也就是说通过找到隐变量就可以实现数据的降维

  3.独立成分分析(Independent Component Analysis,ICA)。ICA假设数据是从N个数据源生成的,这一点和因子分析有些类似。假设数据为多个数据源的混合观察结果,这些数据源之间在统计上相互独立的,而在PCA中只假设数据是不相关的。同因子分析一样,如果数据源的数目少于观察数据的数目,则可以实现降维过程

 

全文 >>

特征预处理——异常值处理

pandas是python特征预处理常用的框架

1.查看数据

加载数据

1
2
3
4
5
6
#-*- coding: utf-8 -*-
import pandas as pd

train_data = pd.read_csv("./data/train.csv")
print(train_data)

pandas显示DataFrame数据的所有列,set_option其他参数参考:Pandas函数set_option()学习笔记

1
2
3
4
5
6
7
8
pd.set_option('expand_frame_repr', False) # 不换行
#pd.set_option('display.width', 200) # 列最多显示多少字符后换行

pd.set_option('display.min_rows', 20) # 至少显示20行数据
pd.set_option('display.max_columns', None) # 显示所有列

print(train_data)

2.查看空值

在pandas中的空值为NaN,isna()等同于isnull()

1
2
print(train_data.isna()) # 判断所有值是否是na,转换成boolean值

对于csv字符串NA,用pandas读取的时候,会转换成NaN,对于字符串None,则不是NaN

全文 >>

机器学习——使用Apriori算法进行关联分析

从大规模的数据集中寻找隐含关系被称作为关联分析(association analysis)或者关联规则学习(association rule learning)

 

Apriori算法

优点:易编码实现

缺点:在大数据集上可能较慢

使用数据类型:数值型或者标称型数据

 

关联分析寻找的是隐含关系,这些关系可以有两种形式:频繁项集或者关联规则

频繁项集(frequent item sets)是经常出现在一起的集合

关联规则(association rule)暗示两种物品之间可能存在很强的关系

 

项集支持度可信度(置信度)

 

Apriori算法的原理是如果某个项集是频繁的,那么它的所有子集也是频繁的如果一个项集是非频繁的,那么它的所有超集也是非频繁的

 

ubuntu安装mongo数据库

安装mongo数据库,在shell下输入

1
2
sudo apt-get install mongodb

如果需要在Python中使用mongo数据库,还需要额外安装Python封装库

1
2
pip install pymongo

 检测安装是否成功,可以使用下面命令在本地启动MongoDB

1
2
mongod -dbpath .

 

在shell中输入mongo,就可以进入mongo数据库

查询数据库语句

1
2
3
4
> show databases;
cache 0.0625GB
local 0.03125GB

使用数据库语句 

1
2
3
> use cache;
switched to db cache

全文 >>

Python爬虫——使用Cookie登录新浪微博

1.首先在浏览器中进入WAP版微博的网址,因为手机版微博的内容较为简洁,方便后续使用正则表达式或者beautifulSoup等工具对所需要内容进行过滤

1
2
https://login.weibo.cn/login/

 

2.人工输入账号、密码、验证字符,最后最重要的是勾选(记住登录状态)

 3.使用Wireshark工具或者火狐的HttpFox插件对GET请求进行分析,需要是取得GET请求中的Cookie信息

未登录新浪微博的情况下,是可以通过网址查看一个用户的首页的,但是不能进一步查看该用户的关注和粉丝等信息,如果点击关注和粉丝,就会重定向回到登录页面

比如使用下面函数对某个用户 http://weibo.cn/XXXXXX/fans粉丝信息进行访问,会重定向回登录页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#获取网页函数
def getHtml(url,user_agent="wswp",num_retries=2): #下载网页,如果下载失败重新下载两次
print '开始下载网页:',url
# headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; rv:24.0) Gecko/20100101 Firefox/24.0'}
headers = {"User-agent":user_agent}
request = urllib2.Request(url,headers=headers) #request请求包
try:
html = urllib2.urlopen(request).read() #GET请求
except urllib2.URLError as e:
print "下载失败:",e.reason
html = None
if num_retries > 0:
if hasattr(e,'code') and 500 <= e.code < 600:
return getHtml(url,num_retries-1)
return html

所以需要在请求的包中的headers中加入Cookie信息,

在勾选了记住登录状态之后,点击关注或者粉丝按钮,发出GET请求,并使用wireshark对这个GET请求进行抓包

可以抓到这个GET请求

全文 >>

Python爬虫——光学字符识别

用homebrew 在电脑上安装tesseract库 

1
brew install tesseract

用pip安装支持python的tesseract 接口

1
2
pip install pytesseract

  

使用pytesseract库图片文件(jpg、png、bmp等)进行识别,把图片转换成字符串输出。

1
2
3
4
5
6
import pytesseract
from PIL import Image

img = Image.open('1.gif')
print(pytesseract.image_to_string(img))

 实际测试效果:

输入图片,输出,结果:成功

输入图片,输出:为空,结果:失败

输入图片,输出:为空,结果:失败

输入图片,输出:,结果:错误

全文 >>

go学习笔记——pprof性能分析工具

可以使用pprof来分析golang程序的CPU性能,内存占用,block死锁,Goroutine性能等,pprof一般是在需要分析代码性能的时候才加入

1.分析Gin web服务的性能

可以使用 gin-contrib/pprof 这个工具,参考:Gin框架中使用pprof

添加依赖

1
2
go get github.com/gin-contrib/pprof@v1.4.0

在gin的路由上添加 pprof.Register(app)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
package main

import (
"net/http"

"github.com/gin-contrib/pprof"
"github.com/gin-gonic/gin"
)

func main() {
app := gin.Default()

// 性能分析
pprof.Register(app)

app.GET("/test", func(c *gin.Context) {
c.String(http.StatusOK, "test")
})
app.Run(":3000")
}

启动web应用后访问如下path

1
2
http://localhost:3000/debug/pprof/

可以看到如下页面

全文 >>

Java多线程——Semaphore信号灯

Semaphore [ˈseməfɔːr] 可以维护当前访问自身的线程个数,并提供了同步机制。使用Semaphore可以控制同时访问资源的线程个数(即允许n个任务同时访问这个资源),例如,实现一个文件允许的并发访问数。

 

Semaphore实现的功能就类似厕所有5个坑,假如有十个人要上厕所,那么同时能有多少个人去上厕所呢?同时只能有5个人能够占用,当5个人中的任何一个人让开后,其中在等待的另外5个人中又有一个可以占用了。

另外等待的5个人中可以是随机获得优先机会,也可以是按照先来后到的顺序获得机会,这取决于构造Semaphore对象时传入的参数选项。

 

单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁”,再由另一个线程释放“锁”,这可应用于死锁恢复的一些场合。

通过acquire()获取访问许可,使用release()释放访问许可,Semaphore可以初始化是0,然后通过release来变成1

sp.availablePermits()可以获取当前可访问的许可的数量

sp.drainPermits()可以把所有许可全部清零

参考:并发编程之Semaphore原理与应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package java_thread;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;

public class SemaphoreTest {
public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final Semaphore sp = new Semaphore(3);
for(int i=0;i<10;i++){
Runnable runnable = new Runnable(){
public void run(){
try {
sp.acquire();
} catch (InterruptedException e1) {
e1.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() +
"进入,当前已有" + (3-sp.availablePermits()) + "个并发");
try {
Thread.sleep((long)(Math.random()*10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("线程" + Thread.currentThread().getName() +
"即将离开");
sp.release();
//下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元
System.out.println("线程" + Thread.currentThread().getName() +
"已离开,当前已有" + (3-sp.availablePermits()) + "个并发");
}
};
service.execute(runnable);
}
}

}

全文 >>

Java多线程——其他工具类CyclicBarrier、CountDownLatch和Exchange

CyclicBarrier

适用于:创建一组任务,它们并行地执行任务,然后在进行下一个步骤之前等待,直至所有任务完成。它使得所有的并行任务都将在栅栏处列队,因此可以一致地向前移动。

表示大家彼此等待,大家集合好后才开始出发,分散活动后又在指定地点集合碰面,这就好比整个公司的人员利用周末时间集体郊游一样,先各自从家出发到公司集合后,再同时出发到公园游玩,在指定地点集合后再同时开始就餐…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package java_thread;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CyclicBarrierTest {

public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final CyclicBarrier cb = new CyclicBarrier(3);
for(int i=0;i<3;i++){
Runnable runnable = new Runnable(){
public void run(){
try {
Thread.sleep((long)(Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() +
"即将到达集合地点1,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));
cb.await();

Thread.sleep((long)(Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() +
"即将到达集合地点2,当前已有" + (cb.getNumberWaiting()+1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));
cb.await();
Thread.sleep((long)(Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() +
"即将到达集合地点3,当前已有" + (cb.getNumberWaiting() + 1) + "个已经到达," + (cb.getNumberWaiting()==2?"都到齐了,继续走啊":"正在等候"));
cb.await();
} catch (Exception e) {
e.printStackTrace();
}
}
};
service.execute(runnable);
}
service.shutdown();
}
}

 

倒计时器CountDownLatch

犹如倒计时计数器,调用CountDownLatch对象的countDown方法就将计数器减1,当计数到达0时,则所有等待者或单个等待者开始执行。这直接通过代码来说明CountDownLatch的作用,这样学员的理解效果更直接。 可以实现一个人(也可以是多个人)等待其他所有人都来通知他,这犹如一个计划需要多个领导都签字后才能继续向下实施。还可以实现一个人通知多个人的效果,类似裁判一声口令,运动员同时开始奔跑。用这个功能做百米赛跑的游戏程序不错哦!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package java_thread;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountdownLatchTest {

public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final CountDownLatch cdOrder = new CountDownLatch(1);
final CountDownLatch cdAnswer = new CountDownLatch(3);
for(int i=0;i<3;i++){
Runnable runnable = new Runnable(){
public void run(){
try {
System.out.println("线程" + Thread.currentThread().getName() +
"正准备接受命令");
cdOrder.await(); //等待计数器归零
System.out.println("线程" + Thread.currentThread().getName() +
"已接受命令");
Thread.sleep((long)(Math.random()*10000));
System.out.println("线程" + Thread.currentThread().getName() +
"回应命令处理结果");
cdAnswer.countDown(); //减小主线程计数值
} catch (Exception e) {
e.printStackTrace();
}
}
};
service.execute(runnable);
}
try { //主线程
Thread.sleep((long)(Math.random()*10000));

System.out.println("线程" + Thread.currentThread().getName() +
"即将发布命令");
cdOrder.countDown(); //减小计数值
System.out.println("线程" + Thread.currentThread().getName() +
"已发送命令,正在等待结果");
cdAnswer.await(); //等待计数器归零
System.out.println("线程" + Thread.currentThread().getName() +
"已收到所有响应结果");
} catch (Exception e) {
e.printStackTrace();
}
service.shutdown();

}
}

 

 

Exchanger

用于实现两个人之间的数据交换,每个人在完成一定的事务后想与对方交换数据,第一个先拿出数据的人将一直等待第二个人拿着数据到来时,才能彼此交换数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package java_thread;
import java.util.concurrent.Exchanger;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExchangerTest {

public static void main(String[] args) {
ExecutorService service = Executors.newCachedThreadPool();
final Exchanger exchanger = new Exchanger();
service.execute(new Runnable(){
public void run() {
try {

String data1 = "zxx";
System.out.println("线程" + Thread.currentThread().getName() +
"正在把数据" + data1 +"换出去");
Thread.sleep((long)(Math.random()*10000));
String data2 = (String)exchanger.exchange(data1);
System.out.println("线程" + Thread.currentThread().getName() +
"换回的数据为" + data2);
}catch(Exception e){

}
}
});
service.execute(new Runnable(){
public void run() {
try {

String data1 = "lhm";
System.out.println("线程" + Thread.currentThread().getName() +
"正在把数据" + data1 +"换出去");
Thread.sleep((long)(Math.random()*10000));
String data2 = (String)exchanger.exchange(data1);
System.out.println("线程" + Thread.currentThread().getName() +
"换回的数据为" + data2);
}catch(Exception e){

}
}
});
}
}

全文 >>