环境:
Centos 7
Capistrano v3
ruby 2.4.1
rails 5.2.3

Installation

install as Ruby Gem

gem install capistrano

Usage in a Rails project

1
2
3
4
group :development do
gem "capistrano", "~> 3.10", require: false
gem "capistrano-rails", "~> 1.3", require: false
end

bundle install

capistrano-rails

  • Asset Pipeline Support
    cap deploy:migrate
  • Database Migration Support
    cap deploy:compile_assets

    Usage

bundle exec cap install

会生成如下结构。

Capfile
config/deploy.rb
config/deploy/production.rb
config/deploy/staging.rb
lib/capistrano/tasks

Capfile 实际上是ruby文件
主要作用:require ruby module,install_plugin, and

1
2
# Load custom tasks from `lib/capistrano/tasks` if you have any defined
Dir.glob("lib/capistrano/tasks/*.rake").each { |r| import r }

config/deploy.rb
配置capistrano task的变量,定义任务,hooks。

config/deploy/*.rb
定义各部署环境的serverroles,即定义各服务器承担了什么角色或者各角色的服务器。
config/deploy/production.rb 执行的时候需要
cap production deploy

lib/capistrano/tasks
rake文件 定义capistrano的tasks。

添加Rails master key

Capistrano::Rails 写在README里,但基本是必须步骤。
如本地尚未生成master key 执行rails secret or rake secret

编辑Capfile文件

1
2
3
4
5
6
7
8
9
10
11
12
13
append :linked_files, "config/master.key"

namespace :deploy do
namespace :check do
before :linked_files, :set_master_key do
on roles(:app), in: :sequence, wait: 10 do
unless test("[ -f #{shared_path}/config/master.key ]")
upload! 'config/master.key', "#{shared_path}/config/master.key"
end
end
end
end
end

migration

Capistrano::Rails Recommendations 提到

1
2
set :migration_role, :app
# Defaults to :db role

这样当你的server 承担app role的时候,cap deploy:migrate 会起作用。
或者在config/deploy/your_env.rb roles 里添加db 角色。

其他一些总结的任务

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
52
53
54
55
56

def package_add(*pkgs)
pkgs.each do |pkg|
unless test "rpm -qa #{pkg}"
execute("yum -y install #{pkg}")
end
end
end

namespace :rbenv do
before :update_ruby_build,:dep do
on roles(:app) do
execute("yum install -y openssl-devel readline-devel zlib-devel")
end
end
end

namespace :puma do
before :nginx_config,:install do
on roles(:app) do
package_add "nginx"

unless test "[ -d /etc/nginx/sites-available ]"
execute("mkdir -p /etc/nginx/sites-available")
end
unless test "[ -d /etc/nginx/sites-enabled ]"
execute("mkdir -p /etc/nginx/sites-enabled")
end

end
end
end

namespace :bundler do
before :install,:dep do
on roles(:app) do
package_add "epel-release","yum-utils"
package_add "postgresql-devel"
unless test "rpm -qa postgresql12-server"
execute("yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm")
execute("yum-config-manager --enable pgdg12")
execute("yum -y install postgresql12-server postgresql12")
execute("/usr/pgsql-12/bin/postgresql-12-setup initdb")
execute("systemctl enable --now postgresql-12")
execute("systemctl status postgresql-12")
execute("firewall-cmd --add-service=postgresql --permanent")
execute("firewall-cmd --reload")
# execute("sudo su - postgres;psql -c 'alter user postgres with password \'\'' ")
end
package_add "sqlite-devel"

# execute("yum -y install nodejs")

end
end
end

由于采用了active storage log的东西太多,收集一些log 过滤方法

1, 过滤http请求参数

initializers/filter_parameter_logging.rb

1
2
3
4
5
6
7
Rails.application.config.filter_parameters += [
:password,
# Filter ActiveStorage blob keys so that the logs aren't full of as much stuff.
:encoded_key,
:signed_blob_id,
:variation_key
]

或者在environments/ 的环境配置文件里设置

2, 针对controller过滤
由于我采用了lograge ,这里针对lograge说明

config/initializers/lograge.rb

1
2
3
4
5
6
7
8
9
Rails.application.configure do
config.lograge.enabled = true
config.lograge.base_controller_class = 'ActionController::Base'
config.lograge.ignore_actions = [
'ActiveStorage::DiskController#show',
'ActiveStorage::RepresentationsController#show',
'ActiveStorage::BlobsController#show'
]
end

3, overwrite LogSubscriber

前面两种针对了http params和controller过滤,但是ActiveStorage::LogSubscriber
在debug信息里面还有ActiveStorage::Variant的log信息,判断Variant文件是否存在,需不需要生成。
由于我上传的文件名都是经过hash的一大串字符,实在干扰查看log,这里重写过滤了。

1
2
3
4
5
6
7
8
config.after_initialize do
module ActiveStorage
class LogSubscriber
def debug(*args, &block)
end
end
end
end

最近,经常出现页面阻止和社交网络帐户注册到外国号码的情况。让我们看看如何避免这种情况。

首先,最受欢迎的网站可以通过 IP地址读取您的位置。您所在国家/地区与注册号码国家的分歧可能会导致网站更加怀疑并进一步阻止。在这种情况下,解决方案可能是使用 VPN 和 PROXY,这样就不会与您的位置编号发生冲突。当然,付费 VPN 和 PROXY 会更有效率,但如果您没有能力或欲购买它们,那么您可以使用免费版本的选项。

其次,所有浏览器都存储用于存储设置的 cookie。因此,这些文件可以被一个站点读取,该站点将了解您之前从另一个区域访问过此站点,这也会对使用外来号码产生不利影响。因此,建议使用干净的浏览器进行注册(在浏览器设置中,清除 cookie)或在浏览器中进行隐身模式。它也可能适合浏览器 Top。

第三, 在注册期间使用正确的名称。正确的名称表示名称的拼写语言及其语法正确性。例如,要将页面注册到中文编号,最好使用中文名称。由于我们大多数人不知道它,您可以使用生成名称的服务。

第四,填写页面上的联系信息。最好立即放置一个头像并填写一些信息,以最大限度地提高自己的怀疑。也不建议立即从页面进行活动操作,例如,主动发布消息,进入大量组,垃圾邮件。有时在注册账户后,有必要给“在床上休息”留出时间 - 连续几天不进入。

这就是全部,我们希望这个小清单可以帮助您避免阻止您创建的页面!

摘自:https://github.com/brightmart/text_classification

Performance

(mulit-label label prediction task,ask to prediction top5, 3 million training data,full score:0.5)

Model fastText TextCNN TextRNN RCNN HierAtteNet Seq2seqAttn EntityNet DynamicMemory Transformer
Score 0.362 0.405 0.358 0.395 0.398 0.322 0.400 0.392 0.322
Training 10m 2h 10h 2h 2h 3h 3h 5h 7h

Bert model achieves 0.368 after first 9 epoch from validation set.

Ensemble of TextCNN,EntityNet,DynamicMemory: 0.411

Ensemble EntityNet,DynamicMemory: 0.403

转自:https://github.com/cjymz886/sentence-similarity

sentence-similarity

对四种句子/文本相似度计算方法进行实验与比较;

四种方法为:cosine,cosine+idf,bm25,jaccard;

本实验仍然利用之前抓取的医疗语料库;

1 环境
=
python3

gensim

jieba

scipy

numpy

2 算法原理
=
image

image

image

image

3 运行步骤
=
setp1:先利用word2vec对./data/file_corpus进行词向量训练(python train_word2vec.py),生成voc.txt词向量文件

setp2:对训练出来的词,计算其在语料库中idf词(python compute_idf.py),生成idf.txt文件

setp3:统计语料库中存在的句子(python get_sentence.py),生成file_sentece.txt文件;考虑计算量问题,本实验只取了出现频率最高的前10000个句子

setp4:运行python test.py,可对设定好的5个句子,按照不同的算法得出最相似的结果

备注说明:./data/medfw.txt文件是我上个项目find-Chinese-medcial-words在同样语料库找出的词文件,本次作为用户词库参与jieba分词;similarity.py文件为四种算法实现的程序,可以调用,不同的环境下只需重新训练词向量和词的idf矩阵;./data/test_result.txt文件是本实验测试结果。

4 测试结果
=
下面表格是对5个相同的句子进行测试的结果,结果可以看出,cosine+idf方法计算复杂度最大,但效果就我个人来看,此方法相对其他方法结果更精确些;bm25算法对有些句子匹配显得有点偏离,我觉得可能跟调节因子k1,b有关;jaccard方法最为简单,计算也是最快,计算结果带不上语义效果;cosine方法算是最常用方法,它的结果非常依赖Word2vec训练的结果。

image

转自:https://github.com/ysc/cws_evaluation

使用说明:

如何建立开发环境?

如果是使用Netbeans、IDEA,则直接打开项目
如果是使用Eclipse、MyEclipse,则要执行导入操作
推荐使用IDEA

评估采用的测试文本位于data目录下,253 3709行,共2837 4490个字符

test-test.txt为未分词的文件,一行一个句子或短语,格式如下:

迈向充满希望的新世纪
一九九八年新年讲话
附图片1张
中共中央总书记
国家主席江泽民
一九九七年十二月三十一日
12月31日
总书记
国家主席江泽民发表1998年新年讲话
新华社记者兰红光摄

standard-text.txt为人工分好词的文件,用于判断参与评估的分词器的分词结果是否正确,词和词之间以空格分隔,格式如下:

迈向 充满 希望 的 新 世纪
一九九八年 新年 讲话
附 图片 1 张
中共中央 总书记
国家 主席 江泽民
一九九七年 十二月 三十一日
12月 31日
总书记
国家 主席 江泽民 发表 1998年 新年 讲话
新华社 记者 兰红光 摄

speed-test-text.txt用于纯粹的速度对比

注意:由于每个分词器的词典格式不一致,除了词典之外使用的其他模型的格式也不一致,所以我们评估对比时没有让所有分词器使用统一的词典和模型,测试的是各个分词器的默认行为

运行org.apdplat.evaluation.Evaluator类可获得评估结果

运行org.apdplat.evaluation.WordSegmenter类可对比不同分词器结果

windows:

./contrast.bat
./evaluation.bat

linux:

chmod +x contrast.sh & ./contrast.sh
chmod +x evaluation.sh & ./evaluation.sh

最终评估结果文件位于report目录下:分词效果评估报告.txt

注意:stanford分词器是吃内存的怪兽,运行的时候需要增加虚拟机参数 -Xms3000m -Xmx3000m

评估报告:

1、word分词 最大Ngram分值算法:
分词速度:370.9714 字符/毫秒
行数完美率:66.55%  行数错误率:33.44%  总的行数:2533709  完美行数:1686210  错误行数:847499
字数完美率:60.94% 字数错误率:39.05% 总的字数:28374490 完美字数:17293964 错误字数:11080526

2、word分词 最少词数算法:
分词速度:330.1586 字符/毫秒
行数完美率:65.67%  行数错误率:34.32%  总的行数:2533709  完美行数:1663958  错误行数:869751
字数完美率:60.12% 字数错误率:39.87% 总的字数:28374490 完美字数:17059641 错误字数:11314849

3、HanLP分词器 标准分词:
分词速度:935.7724 字符/毫秒
行数完美率:58.31%  行数错误率:41.68%  总的行数:2533709  完美行数:1477422  错误行数:1056287
字数完美率:50.43% 字数错误率:49.56% 总的字数:28374490 完美字数:14311008 错误字数:14063482

4、word分词 全切分算法:
分词速度:62.960262 字符/毫秒
行数完美率:57.2%  行数错误率:42.79%  总的行数:2533709  完美行数:1449288  错误行数:1084421
字数完美率:47.95% 字数错误率:52.04% 总的字数:28374490 完美字数:13605742 错误字数:14768748

5、Ansj BaseAnalysis 基本分词:
分词速度:1295.5205 字符/毫秒
行数完美率:55.36%  行数错误率:44.63%  总的行数:2533709  完美行数:1402905  错误行数:1130804
字数完美率:48.18% 字数错误率:51.81% 总的字数:28374490 完美字数:13672441 错误字数:14702049

6、smartcn:
分词速度:611.1504 字符/毫秒
行数完美率:55.29%  行数错误率:44.7%  总的行数:2533690  完美行数:1401069  错误行数:1132621
字数完美率:48.03% 字数错误率:51.96% 总的字数:28374433 完美字数:13628910 错误字数:14745523

7、Ansj ToAnalysis 精准分词:
分词速度:759.40717 字符/毫秒
行数完美率:54.72%  行数错误率:45.27%  总的行数:2533709  完美行数:1386683  错误行数:1147026
字数完美率:44.99% 字数错误率:55.0% 总的字数:28374490 完美字数:12768426 错误字数:15606064

8、HanLP分词器 极速词典分词:
分词速度:6015.3677 字符/毫秒
行数完美率:54.25%  行数错误率:45.74%  总的行数:2533709  完美行数:1374736  错误行数:1158973
字数完美率:46.12% 字数错误率:53.87% 总的字数:28374490 完美字数:13088320 错误字数:15286170

9、word分词 双向最大最小匹配算法:
分词速度:462.87158 字符/毫秒
行数完美率:53.06%  行数错误率:46.93%  总的行数:2533709  完美行数:1344624  错误行数:1189085
字数完美率:43.07% 字数错误率:56.92% 总的字数:28374490 完美字数:12221610 错误字数:16152880

10、HanLP分词器 N-最短路径分词:
分词速度:77.89775 字符/毫秒
行数完美率:53.01%  行数错误率:46.98%  总的行数:2533709  完美行数:1343252  错误行数:1190457
字数完美率:44.42% 字数错误率:55.57% 总的字数:28374490 完美字数:12604878 错误字数:15769612

11、HanLP分词器 最短路径分词:
分词速度:384.70233 字符/毫秒
行数完美率:52.94%  行数错误率:47.05%  总的行数:2533709  完美行数:1341450  错误行数:1192259
字数完美率:43.76% 字数错误率:56.23% 总的字数:28374490 完美字数:12417741 错误字数:15956749

12、Ansj NlpAnalysis NLP分词:
分词速度:172.19516 字符/毫秒
行数完美率:52.66%  行数错误率:47.33%  总的行数:2533709  完美行数:1334314  错误行数:1199395
字数完美率:42.66% 字数错误率:57.33% 总的字数:28374490 完美字数:12105808 错误字数:16268682

13、HanLP分词器 NLP分词:
分词速度:408.2249 字符/毫秒
行数完美率:52.18%  行数错误率:47.81%  总的行数:2533709  完美行数:1322216  错误行数:1211493
字数完美率:43.03% 字数错误率:56.96% 总的字数:28374490 完美字数:12211399 错误字数:16163091

14、FudanNLP:
分词速度:123.456985 字符/毫秒
行数完美率:51.48%  行数错误率:48.51%  总的行数:2533709  完美行数:1304371  错误行数:1229338
字数完美率:43.22% 字数错误率:56.77% 总的字数:28374490 完美字数:12265742 错误字数:16108748

15、Jieba SEARCH:
分词速度:993.435 字符/毫秒
行数完美率:50.84%  行数错误率:49.15%  总的行数:2533709  完美行数:1288237  错误行数:1245472
字数完美率:41.54% 字数错误率:58.45% 总的字数:28374490 完美字数:11789036 错误字数:16585454

16、Jcseg 复杂模式:
分词速度:561.55975 字符/毫秒
行数完美率:47.96%  行数错误率:52.03%  总的行数:2533709  完美行数:1215171  错误行数:1318538
字数完美率:38.84% 字数错误率:61.15% 总的字数:28374490 完美字数:11021588 错误字数:17352902

17、word分词 双向最小匹配算法:
分词速度:967.68604 字符/毫秒
行数完美率:46.34%  行数错误率:53.65%  总的行数:2533709  完美行数:1174276  错误行数:1359433
字数完美率:36.07% 字数错误率:63.92% 总的字数:28374490 完美字数:10236574 错误字数:18137916

18、word分词 双向最大匹配算法:
分词速度:661.148 字符/毫秒
行数完美率:46.18%  行数错误率:53.81%  总的行数:2533709  完美行数:1170075  错误行数:1363634
字数完美率:35.65% 字数错误率:64.34% 总的字数:28374490 完美字数:10117122 错误字数:18257368

19、HanLP分词器 索引分词:
分词速度:942.4862 字符/毫秒
行数完美率:45.44%  行数错误率:54.55%  总的行数:2533709  完美行数:1151473  错误行数:1382236
字数完美率:35.48% 字数错误率:64.51% 总的字数:28374490 完美字数:10068062 错误字数:18306428

20、Jcseg 简易模式:
分词速度:1193.3085 字符/毫秒
行数完美率:44.59%  行数错误率:55.4%  总的行数:2533709  完美行数:1130000  错误行数:1403709
字数完美率:35.78% 字数错误率:64.21% 总的字数:28374490 完美字数:10155059 错误字数:18219431

21、word分词 正向最大匹配算法:
分词速度:1567.1318 字符/毫秒
行数完美率:41.88%  行数错误率:58.11%  总的行数:2533709  完美行数:1061189  错误行数:1472520
字数完美率:31.35% 字数错误率:68.64% 总的字数:28374490 完美字数:8896173 错误字数:19478317

22、word分词 逆向最大匹配算法:
分词速度:1232.6017 字符/毫秒
行数完美率:41.69%  行数错误率:58.3%  总的行数:2533709  完美行数:1056515  错误行数:1477194
字数完美率:30.98% 字数错误率:69.01% 总的字数:28374490 完美字数:8792532 错误字数:19581958

23、word分词 逆向最小匹配算法:
分词速度:1936.9575 字符/毫秒
行数完美率:41.42%  行数错误率:58.57%  总的行数:2533709  完美行数:1049673  错误行数:1484036
字数完美率:31.34% 字数错误率:68.65% 总的字数:28374490 完美字数:8893622 错误字数:19480868

24、Ansj IndexAnalysis 面向索引的分词:
分词速度:677.1308 字符/毫秒
行数完美率:40.66%  行数错误率:59.33%  总的行数:2533709  完美行数:1030336  错误行数:1503373
字数完美率:29.81% 字数错误率:70.18% 总的字数:28374490 完美字数:8459997 错误字数:19914493

25、MMSeg4j ComplexSeg:
分词速度:1699.5801 字符/毫秒
行数完美率:38.81%  行数错误率:61.18%  总的行数:2533688  完美行数:983517  错误行数:1550171
字数完美率:29.6% 字数错误率:70.39% 总的字数:28374428 完美字数:8400089 错误字数:19974339

26、MMSeg4j SimpleSeg:
分词速度:2355.5115 字符/毫秒
行数完美率:37.57%  行数错误率:62.42%  总的行数:2533688  完美行数:951909  错误行数:1581779
字数完美率:28.45% 字数错误率:71.54% 总的字数:28374428 完美字数:8074021 错误字数:20300407

27、IKAnalyzer 智能切分:
分词速度:319.28085 字符/毫秒
行数完美率:37.55%  行数错误率:62.44%  总的行数:2533686  完美行数:951638  错误行数:1582048
字数完美率:27.97% 字数错误率:72.02% 总的字数:28374416 完美字数:7938726 错误字数:20435690

28、word分词 正向最小匹配算法:
分词速度:2228.9465 字符/毫秒
行数完美率:36.7%  行数错误率:63.29%  总的行数:2533709  完美行数:930069  错误行数:1603640
字数完美率:26.72% 字数错误率:73.27% 总的字数:28374490 完美字数:7583741 错误字数:20790749

29、Jieba INDEX:
分词速度:861.55615 字符/毫秒
行数完美率:36.02%  行数错误率:63.97%  总的行数:2533709  完美行数:912771  错误行数:1620938
字数完美率:25.9% 字数错误率:74.09% 总的字数:28374490 完美字数:7351689 错误字数:21022801

30、MMSeg4j MaxWordSeg:
分词速度:1737.2491 字符/毫秒
行数完美率:34.27%  行数错误率:65.72%  总的行数:2533688  完美行数:868440  错误行数:1665248
字数完美率:25.2% 字数错误率:74.79% 总的字数:28374428 完美字数:7152898 错误字数:21221530

31、IKAnalyzer 细粒度切分:
分词速度:323.76926 字符/毫秒
行数完美率:18.87%  行数错误率:81.12%  总的行数:2533686  完美行数:478176  错误行数:2055510
字数完美率:10.93% 字数错误率:89.06% 总的字数:28374416 完美字数:3103178 错误字数:25271238

评估耗时:41分钟,42秒,725毫秒

重点说明:
        关于分词速度,这个不是绝对的,每次测试都会有些差距,而完美率是固定的,所以按行数完美率排名
        上面的评估报告中没有包括Stanford分词器和Paoding分词器
        当前代码已经移除了Paoding分词器,因为Paoding分词器已经7年没有维护了
        当前代码升级Stanford分词器到3.5.2,速度慢的无法等待评估完成,仅用于交互式效果对比
        下面是之前代码对 Paoding分词器2.0.4-beta 和 Stanford分词器 3.3.1 的评估数据

Stanford Beijing University segmentation:
分词速度:14.4612055 字符/毫秒
行数完美率:58.29%  行数错误率:41.7%  总的行数:2533709  完美行数:1477034  错误行数:1056675
字数完美率:51.36% 字数错误率:48.63% 总的字数:28374490 完美字数:14574120 错误字数:13800370

Stanford Chinese Treebank segmentation:
分词速度:13.723294 字符/毫秒
行数完美率:55.45%  行数错误率:44.54%  总的行数:2533709  完美行数:1404968  错误行数:1128741
字数完美率:47.27% 字数错误率:52.72% 总的字数:28374490 完美字数:13414926 错误字数:14959564

Paoding MAX_WORD_LENGTH_MODE:
分词速度:1343.1075 字符/毫秒
行数完美率:14.19%  行数错误率:85.8%  总的行数:2533158  完美行数:359637  错误行数:2173521
字数完美率:7.72% 字数错误率:92.27% 总的字数:28373102 完美字数:2191349 错误字数:26181753

Paoding MOST_WORDS_MODE:
分词速度:1338.9246 字符/毫秒
行数完美率:11.6%  行数错误率:88.39%  总的行数:2533158  完美行数:294011  错误行数:2239147
字数完美率:5.92% 字数错误率:94.07% 总的字数:28373102 完美字数:1680261 错误字数:26692841

效果对比:

1、以 我爱楚离陌 为例子:

word分词器 的分词结果:
    1 、【全切分算法】    我 爱 楚离陌 
    2 、【双向最大最小匹配算法】    我 爱 楚离陌 
    3 、【最大Ngram分值算法】    我 爱 楚离陌 
    4 、【正向最大匹配算法】    我 爱 楚离陌 
    5 、【双向最大匹配算法】    我 爱 楚离陌 
    6 、【最少词数算法】    我 爱 楚离陌 
    7 、【逆向最大匹配算法】    我 爱 楚离陌 
    8 、【正向最小匹配算法】    我 爱 楚离陌 
    9 、【双向最小匹配算法】    我 爱 楚离陌 
    10 、【逆向最小匹配算法】    我 爱 楚离陌 
Stanford分词器 的分词结果:
    1 、【Stanford Chinese Treebank segmentation】    我 爱 楚离陌 
    2 、【Stanford Beijing University segmentation】    我 爱 楚 离陌 
Ansj分词器 的分词结果:
    1 、【BaseAnalysis】    我 爱 楚 离 陌 
    2 、【IndexAnalysis】    我 爱 楚 离 陌 
    3 、【ToAnalysis】    我 爱 楚 离 陌 
    4 、【NlpAnalysis】    我 爱 楚离 陌 
HanLP分词器 的分词结果:
    1 、【NLP分词】 我 爱 楚 离 陌 
    2 、【标准分词】  我 爱 楚 离 陌 
    3 、【N-最短路径分词】  我 爱 楚 离 陌 
    4 、【索引分词】  我 爱 楚 离 陌 
    5 、【最短路径分词】    我 爱 楚 离 陌 
    6 、【极速词典分词】    我 爱 楚 离 陌 
smartcn分词器 的分词结果:
    1 、【smartcn】    我 爱 楚 离 陌 
FudanNLP分词器 的分词结果:
    1 、【FudanNLP】    我 爱楚离陌
Jieba分词器 的分词结果:
    1 、【SEARCH】    我爱楚 离 陌 
    2 、【INDEX】    我爱楚 离 陌 
Jcseg分词器 的分词结果:
    1 、【简易模式】    我 爱 楚 离 陌 
    2 、【复杂模式】    我 爱 楚 离 陌 
MMSeg4j分词器 的分词结果:
    1 、【SimpleSeg】    我爱 楚 离 陌 
    2 、【ComplexSeg】    我爱 楚 离 陌 
    3 、【MaxWordSeg】    我爱 楚 离 陌 
IKAnalyzer分词器 的分词结果:
    1 、【智能切分】    我 爱 楚 离 陌 
    2 、【细粒度切分】    我 爱 楚 离 陌 

2、以 结合成分子 为例子:

word分词器 的分词结果:
    1 、【全切分算法】    结合 成 分子 
    2 、【双向最大最小匹配算法】    结 合成 分子 
    3 、【最大Ngram分值算法】    结合 成 分子 
    4 、【正向最大匹配算法】    结合 成分 子 
    5 、【双向最大匹配算法】    结 合成 分子 
    6 、【最少词数算法】    结合 成 分子 
    7 、【逆向最大匹配算法】    结 合成 分子 
    8 、【正向最小匹配算法】    结合 成分 子 
    9 、【双向最小匹配算法】    结 合成 分子 
    10 、【逆向最小匹配算法】    结 合成 分子 
Stanford分词器 的分词结果:
    1 、【Stanford Chinese Treebank segmentation】    结合 成 分子 
    2 、【Stanford Beijing University segmentation】    结合 成 分子 
Ansj分词器 的分词结果:
    1 、【BaseAnalysis】    结合 成 分子 
    2 、【IndexAnalysis】    结合 成 分子 
    3 、【ToAnalysis】    结合 成 分子 
    4 、【NlpAnalysis】    结合 成 分子 
HanLP分词器 的分词结果:
    1 、【NLP分词】    结合 成 分子 
    2 、【标准分词】    结合 成 分子 
    3 、【N-最短路径分词】    结合 成 分子 
    4 、【索引分词】    结合 成 分子 
    5 、【最短路径分词】    结合 成 分子 
    6 、【极速词典分词】    结合 成分 子 
smartcn分词器 的分词结果:
    1 、【smartcn】    结合 成 分子 
FudanNLP分词器 的分词结果:
    1 、【FudanNLP】    结合 成 分子
Jieba分词器 的分词结果:
    1 、【SEARCH】    结合 成 分子 
    2 、【INDEX】    结合 成 分子 
Jcseg分词器 的分词结果:
    1 、【简易模式】    结合 成分 子 
    2 、【复杂模式】    结合 成 分子 
MMSeg4j分词器 的分词结果:
    1 、【SimpleSeg】    结合 成分 子 
    2 、【ComplexSeg】    结合 成分 子 
    3 、【MaxWordSeg】    结合 成分 子 
IKAnalyzer分词器 的分词结果:
    1 、【智能切分】    结合 成 分子 
    2 、【细粒度切分】    结合 合成 成分 分子

速度对比:

1、HanLP分词器 极速词典分词:
分词速度:5030.1978 字符/毫秒

2、MMSeg4j MaxWordSeg:
分词速度:2454.494 字符/毫秒

3、MMSeg4j SimpleSeg:
分词速度:2184.697 字符/毫秒

4、word分词 逆向最小匹配算法:
分词速度:1407.4127 字符/毫秒

5、word分词 正向最小匹配算法:
分词速度:1234.6848 字符/毫秒

6、MMSeg4j ComplexSeg:
分词速度:1184.436 字符/毫秒

7、Jcseg 简易模式:
分词速度:1023.73364 字符/毫秒

8、Ansj BaseAnalysis 基本分词:
分词速度:906.4427 字符/毫秒

9、word分词 双向最小匹配算法:
分词速度:833.2229 字符/毫秒

10、Jieba SEARCH:
分词速度:831.52246 字符/毫秒

11、word分词 逆向最大匹配算法:
分词速度:808.4246 字符/毫秒

12、IKAnalyzer 细粒度切分:
分词速度:735.4621 字符/毫秒

13、HanLP分词器 索引分词:
分词速度:664.67535 字符/毫秒

14、word分词 正向最大匹配算法:
分词速度:573.46375 字符/毫秒

15、word分词 双向最大匹配算法:
分词速度:539.6636 字符/毫秒

16、Jieba INDEX:
分词速度:507.40472 字符/毫秒

17、word分词 双向最大最小匹配算法:
分词速度:505.20273 字符/毫秒

18、IKAnalyzer 智能切分:
分词速度:483.90262 字符/毫秒

19、HanLP分词器 标准分词:
分词速度:461.43375 字符/毫秒

20、Ansj IndexAnalysis 面向索引的分词:
分词速度:446.76096 字符/毫秒

21、word分词 最少词数算法:
分词速度:444.56738 字符/毫秒

22、Ansj ToAnalysis 精准分词:
分词速度:440.2442 字符/毫秒

23、word分词 最大Ngram分值算法:
分词速度:419.61484 字符/毫秒

24、smartcn:
分词速度:419.39886 字符/毫秒

25、Jcseg 复杂模式:
分词速度:391.21075 字符/毫秒

26、HanLP分词器 最短路径分词:
分词速度:288.55948 字符/毫秒

27、HanLP分词器 NLP分词:
分词速度:251.66522 字符/毫秒

28、Ansj NlpAnalysis NLP分词:
分词速度:174.01068 字符/毫秒

29、word分词 全切分算法:
分词速度:146.16898 字符/毫秒

30、FudanNLP:
分词速度:111.7975 字符/毫秒

31、HanLP分词器 N-最短路径分词:
分词速度:67.67644 字符/毫秒

支持的分词器有:

1、word分词器

2、ansj分词器

3、mmseg4j分词器

4、ik-analyzer分词器

5、jcseg分词器

6、fudannlp分词器

7、smartcn分词器

8、jieba分词器

9、stanford分词器

10、hanlp分词器

https://travis-ci.org/ysc/cws_evaluation

转自:https://github.com/liuhuanyong/WordSegment

1、MaxMatch:
dict.txt: 分词用词典位置
max_forward_cut:正向最大匹配分词
max_backward_cut:逆向最大匹配分词
max_biward_cut:双向最大匹配分词
result:
输入:我们在野生动物园玩
输出:
forward_cutlist: [‘我们’, ‘在野’, ‘生动’, ‘物’, ‘园’, ‘玩’]
backward_cutlist: [‘我们’, ‘在’, ‘野生’, ‘动物园’, ‘玩’]
biward_seglit: [‘我们’, ‘在’, ‘野生’, ‘动物园’, ‘玩’]

2、HMM:
hmm_train.py:基于人民日报语料29W句子,训练初始状态概率,发射概率,转移概率
data:训练语料,放在 ./data/train.txt
model: 保存训练的概率模型,训练完成后可直接调用
trans_path = ‘./model/prob_trans.model’
emit_path = ‘./model/prob_emit.model’
start_path = ‘./model/prob_start.model’

hmm_cut.py:基于训练得到的model,结合viterbi算法进行分词
输入:我们在野生动物园玩
输出:[‘我们’, ‘在’, ‘野’, ‘生动’, ‘物园’, ‘玩’]

3、N-gram
train_ngram.py:基于人民日报语料29W句子,训练词语出现概率,2-gram条件概率
data: 训练语料,放在 ./data/train.txt
model: 保存概率模型,训练完成后可直接调用
word_path = ‘./model/word_dict.model’ (词语出现概率)
trans_path = ‘./model/trans_dict.model’(2-gram条件概率)
max_ngram.py: 最大化概率2-gram分词算法
biward_ngram.py: 基于ngram的前向后向最大匹配算法

4、算法比较
1、评测语料:微软评测语料,共3985个句子
2、性能比较

Algorithm Precision Recall F1-score Cost-Time
HMM 0.65 0.75 0.70 4.87
MaxForward 0.76 0.87 0.81 244.14
MaxBackward 0.76 0.87 0.81 280.61
MaxBiWard 0.76 0.87 0.81 443.23
MaxProbNgram 0.76 0.87 0.81 8.99
MaxBiwardNgram 0.74 0.86 0.80 3.96

DOCTYPE

时过境迁,我们已无需在复制粘贴冗长的DOCTYPE代码,我们可以直接使用HTML5的文档类型<!DOCTYPE html>而无需担心兼容性问题,但在此之前的版本XHTML标准仍有参考意义。

  1. XHTML 元素必须被正确地嵌套。
  2. XHTML 元素必须被关闭。
  3. 标签名必须用小写字母。
  4. XHTML 文档必须拥有根元素。

在此我针对以上几点补充说明:

  1. 其实无论哪种版本对于开发者而言都应该做到正确的嵌套元素。为了节省篇幅我将使用ZenCode语法作示例。
    正确的嵌套如下:

    html>head+body
    ul>li>a

  2. 此时所说的元素必须被关闭包括成对标签如<p></p>或者单独标签<hr/><br/>,单独标签在HTML5文档类型中不应被关闭。

  3. 实际上浏览器会无视html的大小写,但我们也没必要多按住 Shift 或者 Capslock

  4. 即使你没有写DOCTYPE、html、body 浏览器也会在外面包裹上,但为什么不写html元素呢?

<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <meta charset="UTF-8" /> 如何选择?

你可以放心的使用<meta charset="UTF-8" />在所有的浏览器。参见:Obsolete practices to avoid 另外需要强调meta charset设置请放置在<head>之后使之成为第一个meta声明,依照W3C规范

“ META declarations should appear as early as possible in the HEAD element”。

X-UA-Compatible

建议如此设置<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />,IE=edge告诉IE使用最新的引擎渲染网页,chrome=1则可以激活Chrome Frame(使安装了Chrome Frame的IE浏览器和某些极速浏览器使用WebKit 引擎处理网页,另外也支持IE所没有的HTML5等其他open web技术。)。

如上所述X-UA-Compatible则跟在meta charset之后,如果因为某些原因IE采用兼容试图之后才出现这个meta设置那就无意义了,所以还是尽量靠前吧,这里的某些原因暂时没找到相关文献。

属性值的包裹是用单引号、双引号还是不写引号?

HTML规范并没有指明属性的值是否应该被引号包裹,是用单引号还是双引号,浏览器为了页面能较好的呈现也会兼容这三种方式。然而为了较好的阅读性以及我们可能在属性的值写上JSON数据或者其他HTML片段(此时HTML片段里的属性值可用单引号包裹或者使用双引号HTML实体&quot;)还是使用双引号更为合理。

根据The link element `rel=”stylesheet”`在<link>标签上是必须的,type并不是必须的无论是在<link>标签上还是<style>标签上。
参见:

text/javascript

在 HTML 4.01 和 XHTML 1.0标准上是必须的,参见SCRIPT,HTML5并不是必须的,而不写text/javascript在所有浏览器上都不会产生错误。

从WordPress迁移到hexo,为什么呢?因为我发现自己业余项目购置的两台阿里云主机,可申请的发票面额超过了1万,上面一共运行了两个网站一个Wordpress,都是基于兴趣而创建的,然而在长期的充值下,花费已经超出了预期,首先考虑把博客迁移出去,因为作为日志来说显得过于笨重,需要维护PHP,MySQL虽说上面有几个自定义的Page还有一个PHP在线小工具,但就这样吧,谁会记得呢?后面再考虑关闭一个目前只有演示作用的网址,直接减少一台云主机的费用。

下面记录迁移过程:

hexo init mine-blog

npm install hexo-migrator-wordpress --save

hexo migrate wordpress suntory.wordpress.2018-08-15.xml 

hexo server

hexo migrate wordpress 没有处理文章中的图片,我把生成的source目录删除了,寻找别的方法,这里作下记录。

尝试启动server时报错:

Package hexo-renderer-sass is not installed.

安装依赖:

npm i hexo-renderer-sass --save

安装过程中报错

fatal error: 'sass/context.h' file not found

brew install libsass

采用hexo-migrator-wordpressimg来migrate
npm install hexo-migrator-wordpressimg --save
hexo migrate wordpressimg suntory.wordpress.2018-08-15.xml www.bungos.me
hexo-migrator-wordpressimg 会下载文章里的图片并把markdown里的地址替换成本地相对路径。
这里有三个问题:

  • 匹配图片的正则有点简单,我文章里的包含中文的图片路径无法匹配到
  • 下载图片的时候url没有encode导致无法下载包含中文路径的图片
  • 对于Page路径包含/时替换后的路径仍是相对source目录的

所以最后我用了我修改后的版本解决了前两个问题
https://github.com/bung87/hexo-migrator-wordpressimg

然而这还没有完,有的图片没有下载完整,最后我不得不直接把服务器上WordPress的wp-content/uploads直接下载了下来。

查看最终的效果:
发现图片有[caption]的替换后的markdown成了\[caption\],手动处理了几篇。

codeblock由于原来我在WP采用的是自动识别的方案,而生成的并没有语法高亮,我不得不手动修改成markdown的codeblock的语法。

而个别的codeblock语法高亮还是有问题,语法虽然识别了,但整个块并未包裹highlight的class,导致没有颜色而class为number的数字异常的大,我不得不使用

{% codeblock %}

Prerequisites

nodejs ruby

node package dev Dependencies

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
"devDependencies": {
"bower": "^1.8.0",
"browser-sync": "^2.18.8",
"gulp": "^3.9.1",
"gulp-copy": "^1.0.0",
"gulp-cssmin": "^0.1.7",
"gulp-group-files": "^2.0.0",
"gulp-ignore": "^2.0.2",
"gulp-rename": "^1.2.2",
"gulp-ruby-sass": "^2.1.1",
"gulp-sourcemaps": "^2.6.0",
"gulp-uglify": "^2.1.2",
"iniparser": "^1.0.5",
"main-bower-files": "^2.13.1",
"ncp": "^2.0.0",
"pdf.js": "bung87/pdf.js#master"
}

pdf.js 只为演示build项目依赖包,下面说明gulpfile.js

1
2
3
4
5
6
7
8
9
var gulp = require('gulp');
// var sass = require('gulp-sass');
var sass = require('gulp-ruby-sass');
var group = require('gulp-group-files');

var bower = require('main-bower-files');
var sourcemaps = require('gulp-sourcemaps');
var browserSync = require('browser-sync').create();
var fs = require('fs');

此处注释gulp-sass而采用gulp-ruby-sass是因为gulp-sass依赖node-sass而node-sass依赖node-gyp,鉴于我有很多次node-gyp安装失败的经历而且本身sass最初的compiler就是ruby实现的我就采用了更为稳妥的做法。 precompile sass files

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var sassFiles = {
"style" : {
src: "./static/scss/style.scss",
dest: "./build/css"
}
};

gulp.task('sass:compile',function (){
return group(sassFiles,function (key,fileset){
// group(sassFiles,function (key,fileset){
// return gulp.src(fileset.src)
// .pipe(sass().on('error', sass.logError))
console.log(fileset.src)
return sass(fileset.src)
.pipe(sourcemaps.init())
.pipe(sourcemaps.write('maps', {
includeContent: true,
sourceRoot: 'source'
}))
.on('error', sass.logError)
.pipe(gulp.dest(fileset.dest)).pipe(browserSync.stream());
})();
});

pipe到browserSync.stream()是实现precompile后浏览器自动刷新的关键,下面不再赘述。 copy前端ui框架的字体到build目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
gulp.task('copy',function (){
var dest = './build/fonts';
if (!fs.existsSync(dest)) {
var sassFiles = {
"fonts" : {
src: ['bower_components/foundation-icons/foundation_icons_general/fonts/*' ],
dest: "./build/fonts"
}
};
return group(sassFiles,function (key,fileset){
return gulp.src(fileset.src)
.pipe(gulp.dest(fileset.dest)).pipe(browserSync.stream());
})();
}
});

使用main-bower-files将bower依赖包 bower.json main 属性里静态资源copy到build目录

1
2
3
4
gulp.task('bower', function() {
//.pipe(gulpIgnore.exclude("pdf.js/"))
return gulp.src(bower()).pipe(gulp.dest('build/js')).pipe(browserSync.stream());
});

watch bower sass的变化

1
2
3
4
5
6
7
8
9
gulp.task('bower:watch',function (){
// gulp.watch('static/**/*.scss',['sass:compile']);
gulp.watch('bower.json',['copy','bower']);
});

gulp.task('sass:watch',function (){
gulp.watch('static/**/*.scss',['sass:compile']);
// gulp.watch('bower.json',['build']);
});

将由collectstatic 和build后输出到assets目录的js和css都minify 并加.min.js .min.css后缀

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var cssmin = require('gulp-cssmin');
var rename = require('gulp-rename');
var uglify = require('gulp-uglify');
var gulpIgnore = require('gulp-ignore');

gulp.task('css:min', ["collectstatic"],function () {
return gulp.src('assets/**/*.css')
.pipe(gulpIgnore.exclude("*.min.css"))
.pipe(cssmin())
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest('assets'));
});

gulp.task('js:min', ["collectstatic"],function () {
return gulp.src('assets/**/*.js')
.pipe(gulpIgnore.exclude("*.min.js"))
.pipe(gulpIgnore.exclude("**/grappelli/js/*.js"))
.pipe(uglify())
.pipe(rename({suffix: '.min'}))
.pipe(gulp.dest('assets'));
});

gulp.task('min', ['css:min','js:min']);

根据virtualenv 环境变量或者uwsgi.ini获取python执行环境后调用./manage.py collectstatic。 –no-post-process 是因为后面还有其他gulp task,需要确定同步执行完毕。 –noinput >/dev/null 是因为collectstatic输出内容太多。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var iniparser = require('iniparser');
var execSync = require('child_process').execSync;
var exec = require('child_process').exec;
gulp.task('collectstatic', function (cb) {
iniparser.parse('./uwsgi.ini', function(err,data){
var uwsgi = data.uwsgi,home = "";
if(process.env.VIRTUAL_ENV){
home = process.env.VIRTUAL_ENV
}else{
home = uwsgi.home;
}
var python = home +"/bin/python";
execSync(python + ' ./manage.py collectstatic --no-post-process --noinput >/dev/null ');
cb();
});
});

单独build pdf.js

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
gulp.task("pdfbuild",function(){
var path = 'build/js/pdf.js/';
var process = require('process');
if (!fs.existsSync(path)) {
process.chdir('./node_modules/pdf.js');
execSync("yarn install",function(err, stdout, stderr){
console.log(err, stdout, stderr);
process.chdir(__dirname);
});
}
});

var ncp = require('ncp').ncp;
gulp.task("pdf",function(){
var process = require('process');
var path = 'build/js/pdf.js/'
// process.chdir('./node_modules/pdf.js');

if (!fs.existsSync(path)) {
// Do something

execSync("gulp minified --gulpfile ./node_modules/pdf.js/gulpfile.js",function(err, stdout, stderr){
console.log(err, stdout, stderr);
ncp('./node_modules/pdf.js/build/',path);
});
}
});

启动本地server,我是mac环境所以这里启动mysql server 是”mysql.server start”。 这里依赖django-pserver requirements.txt 增加 git+https://github.com/bung87/django-pserver django-pserver 是因为bower sync proxy socket而修改python代码后django默认不会重用同一个socket,而是新开一个socket这时候bower sync监听的已经关闭,新开的又未知。而django-pserver是复用同一个socket所以不存在这个问题。 spawn 这里设置了选项stdio,经过尝试发现django console log都是走stderr所以配置后browser sync的std outputs会和django的混在一起,之前使用execSync导致django的log只有到process终止才输出,而且每次到超出默认的buffer限制。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const { spawn } = require('child_process');
gulp.task('build',['sass:compile',"copy","bower","pdf"]);
gulp.task('develop',['sass:watch',"bower:watch"]);
gulp.task('server',function(cb){
execSync("mysql.server start");

if(process.env.VIRTUAL_ENV){
home = process.env.VIRTUAL_ENV;
const path = require('path');
var python = home +"/bin/python";
var manage = './manage.py'
const server = spawn(python , [`${manage}`,"runserverp","--nostatic"], {
cwd:path.resolve('./'),
stdio: ['ignore', 'ignore', process.stderr]
});

server.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});

cb();
}
});

urls.py 里serve media文件 并阻止static file cache因为没有文件名hash浏览器会缓存。

1
2
3
4
5
6
7
8
9
10
11
12
13
from django.contrib.staticfiles.views import serve as serve_static
from django.views.decorators.cache import never_cache
from django.conf.urls.static import static

if settings.DEBUG:

urlpatterns = (tuple) (static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)) +urlpatterns

if settings.DEBUG:
urlpatterns += (
url(r'^static/(?P.*)$', never_cache(serve_static)),

)

最后最主要的gulp task proxyReq.setHeader(‘X-BrowserSync-External-Url’, externalUrl);此处设置brower sync的externalUrl到http header以供后端调试之用。 watch pyc pyo $py.class 此三类python的缓存文件,python code编辑后生成缓存文件有一段间隔所以这里并不直接watch .py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
gulp.task("dev",['server'],function(){

browserSync.init({
// logLevel: "debug",
logConnections: true,
proxy: {
target:"localhost:8000",
proxyReq: [
function(proxyReq) {
externalUrl = browserSync.getOption('urls').get('external');
proxyReq.setHeader('X-BrowserSync-External-Url', externalUrl);
}
]
},
});
gulp.watch('bower.json',['copy','bower']);
gulp.watch('static/**/*.scss',['sass:compile']);
gulp.watch("**/*.html").on('change', browserSync.reload);
gulp.watch("**/*.pyc").on('change', browserSync.reload);
gulp.watch("**/*.pyo").on('change', browserSync.reload);
gulp.watch("**/*$py.class").on('change', browserSync.reload);
gulp.watch("**/*.mo").on('change', browserSync.reload);
});

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×