中文分词入门之字标注法4

http://www.52nlp.cn/%E4%B8%AD%E6%96%87%E5%88%86%E8%AF%8D%E5%85%A5%E9%97%A8%E4%B9%8B%E5%AD%97%E6%A0%87%E6%B3%A8%E6%B3%954

上一节主要介绍的是利用最大熵工具包来做字标注中文分词,这一节我们直奔主题,借用条件随机场工具“CRF++: Yet Another CRF toolkit”来完成字标注中文分词的全过程。

关于条件随机场(CRF)的背景知识,推荐参考阅读一些经典的文献:《条件随机场文献阅读指南》,另外再额外推荐一个tutorial:《Classical Probabilistic Models and Conditional Random Fields》, 这份关于CRF的文档分别从概率模型(NB,HMM,ME, CRF)之间的关系以及概率图模型背景来介绍条件随机场,比较清晰:

While a Hidden Markov Model is a sequential extension to the Nave Bayes Model, Conditional Random Fields can be understood as a sequential extension to the Maximum Entropy Model.

如果这些还不够过瘾,推荐课程图谱上收录的Coursera创始人之一Daphne Koller的“概率图模型公开课”,相信拿下这门课之后,对于上述概率模型,会有一种“一览众山小”的感觉。

不过我们还是要从安装CRF++工具包说起,在Linux或者Mac OS系统下,下载C++源代码安装包(这里用的是 CRF++-0.58.tar.gz )之后,依然是 “configure & make & (sudo) make install”,安装完毕之后,可以cd python进入到其同样用SWIG生成的Python工具包下,安装python包:python setup.py build & (sudo) python setup.py install。安装完毕之后,可以在python解释器下测试,是否能成功import CRFPP,如果ok,则准备工作就绪。

上一节我们利用最大熵模型工具包里自带的词性标注工具进行的中文分词,稍微有些曲折,这一节我们依然利用CRF++ example里的样例进行测试,不过好处是,CRF++ example里有个seg目录,这个seg目录对应的是一个日文分词的样例,正好可以套用到我们的中文分词中来。在安装包目录下,cd example, cd seg目录后,有4个文件:

exec.sh(执行脚本)
template(特征模板)
test.data(测试集)
train.data(训练集)

有了这4个文件,我们可以做得事情就比较简单,只要按测试集,训练集的格式准备数据就可以了,特征模板和执行脚本可以套用,不过这里简单解读一下这几个CRF++文件。首先来看训练集:

1
2
3
4
5
6
7
8
9
10
毎 k   B
日 k   I
新 k   I
聞 k   I
社 k   I
特 k   B
別 k   I
顧 k   B
問 k   I                                                 
4 n   B

这里第一列是待分词的日文字,第二列暂且认为其是词性标记,第三列是字标注中的2-tag(B, I)标记,这个很重要,对于我们需要准备的训练集,主要是把这一列的标记做好,不过需要注意的是,其断句是靠空行来完成的。

再来看测试集的格式:

1
2
3
4
5
6
7
8
9
10
よ h   I
っ h   I
て h   I
私 k   B
た h   B
ち h   I
の h   B                                                     
世 k   B
代 k   I
が h   B

同样也有3列,第一列是日文字,第二列第三列与上面是相似的,不过在测试集里第三列主要是占位作用。事实上,CRF++对于训练集和测试集文件格式的要求是比较灵活的,首先需要多列,但不能不一致,既在一个文件里有的行是两列,有的行是三列;其次第一列代表的是需要标注的“字或词”,最后一列是输出位”标记tag”,如果有额外的特征,例如词性什么的,可以加到中间列里,所以训练集或者测试集的文件最少要有两列。

接下里我们再来详细的分析一下特征模板文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Unigram
U00:%x[-2,0]
U01:%x[-1,0]
U02:%x[0,0]
U03:%x[1,0]
U04:%x[2,0]
U05:%x[-2,0]/%x[-1,0]/%x[0,0]
U06:%x[-1,0]/%x[0,0]/%x[1,0]
U07:%x[0,0]/%x[1,0]/%x[2,0]
U08:%x[-1,0]/%x[0,0]                                          
U09:%x[0,0]/%x[1,0]

# Bigram
B

关于CRF++中特征模板的说明和举例,请大家参考官方文档上的“Preparing feature templates”这一节,而以下部分的说明拿上述日文分词数据举例。在特征模板文件中,每一行(如U00:%x[-2,0])代表一个特征,而宏“%x[行位置,列位置]”则代表了相对于当前指向的token的行偏移和列的绝对位置,以上述训练集为例,如果当前扫描到“新 k I”这一行,

1
2
3
4
5
6
7
8
9
10
毎 k   B
日 k   I
新 k   I   <== 扫描到这一行,代表当前位置
聞 k   I
社 k   I
特 k   B
別 k   I
顧 k   B
問 k   I
4 n   B

那么依据特征模板文件抽取的特征如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Unigram
U00:%x[-2,0] ==> 毎
U01:%x[-1,0] ==> 日
U02:%x[0,0]  ==> 新
U03:%x[1,0]  ==> 聞
U04:%x[2,0]  ==> 社
U05:%x[-2,0]/%x[-1,0]/%x[0,0] ==> 每/日/新
U06:%x[-1,0]/%x[0,0]/%x[1,0]  ==> 日/新/聞
U07:%x[0,0]/%x[1,0]/%x[2,0]   ==> 新/聞/社
U08:%x[-1,0]/%x[0,0]          ==> 日/新
U09:%x[0,0]/%x[1,0]           ==> 新/聞

# Bigram
B

CRF++里将特征分成两种类型,一种是Unigram的,“U”起头,另外一种是Bigram的,“B”起头。对于Unigram的特征,假如一个特征模板是”U01:%x[-1,0]”, CRF++会自动的生成一组特征函数(func1 … funcN) 集合:

1
2
3
4
5
func1 = if (output = B and feature="U01:日") return 1 else return 0
func2 = if (output = I and feature="U01:日") return 1 else return 0
....
funcXX = if (output = B and feature="U01:問") return 1  else return 0
funcXY = if (output = I and feature="U01:問") return 1  else return 0

生成的特征函数的数目 = (L * N),其中L是输出的类型的个数,这里是B,I这两个tag,N是通过模板扩展出来的所有单个字符串(特征)的个数,这里指的是在扫描所有训练集的过程中找到的日文字(特征)。

而Bigram特征主要是当前的token和前面一个位置token的自动组合生成的bigram特征集合。最后需要注意的是U01和U02这些标志位,与特征token组合到一起主要是区分“U01:問”和“U02:問”这类特征,虽然抽取的日文”字”特征是一样的,但是在CRF++中这是有区别的特征。

最后我们再来看一下执行脚本:

1
2
3
4
5
6
7
#!/bin/sh
../../crf_learn -f 3 -c 4.0 template train.data model
../../crf_test -m model test.data

../../crf_learn -a MIRA -f 3 template train.data model
../../crf_test -m model test.data
rm -f model

执行脚本告诉了我们如何训练一个CRF模型,以及如何利用这个模型来进行测试,执行这个脚本之后,对于输入的测试集,输出结果多了一列:

1
2
3
4
5
6
7
8
9
10
よ h   I   B
っ h   I   I
て h   I   B
私 k   B   B
た h   B   B
ち h   I   I
の h   B   B                                      
世 k   B   B
代 k   I   I
が h   B   B

而这一列才是模型预测的改字的标记tag,也正是我们所需要的结果。到此为止,关于日文分词样例的介绍已经完毕,读者应该可以猜测到接下来我们会如何做中文分词吧?

和上一节利用最大熵模型进行中文分词相似,第一步仍然是将backoff2005里的训练数据转化为CRF++所需的训练数据格式,还是以微软亚洲研究院提供的中文分词语料为例,依然采用4-tag(B(Begin,词首), E(End,词尾), M(Middle,词中), S(Single,单字词))标记集,只处理utf-8编码文本。原始训练集./icwb2-data/training/msr_training.utf8的形式是人工分好词的中文句子形式,如:

1
2
3
4
5
6
7
8
9
10
“  人们  常  说  生活  是  一  部  教科书  ,  而  血  与  火  的  战争  >      更  是  不可多得  的  教科书  ,  她  确实  是  名副其实  的  ‘  我  的  >      大学  ’  。
“  心  静  渐  知  春  似  海  ,  花  深  每  觉  影  生  香  。
“  吃  屎  的  东西  ,  连  一  捆  麦  也  铡  不  动  呀  ?
他  “  严格要求  自己  ,  从  一个  科举  出身  的  进士  成为  一个  伟>      大  的  民主主义  者  ,  进而  成为  一  位  杰出  的  党外  共产主义  战 士  ,  献身  于  崇高  的  共产主义  事业  。
“  征  而  未  用  的  耕地  和  有  收益  的  土地  ,  不准  荒芜  。
“  这  首先  是  个  民族  问题  ,  民族  的  感情  问题  。
’  我  扔  了  两颗  手榴弹  ,  他  一下子  出  溜  下去  。
“  废除  先前  存在  的  所有制  关系  ,  并不是  共产主义  所  独具  的        特征  。
“  这个  案子  从  始  至今  我们  都  没有  跟  法官  接触  过  ,  也  >      没有  跟  原告  、  被告  接触  过  。
“  你  只有  把  事情  做好  ,  大伙  才  服  你  。

这里同样提供一个脚本 make_crf_train_data.py,将这个训练语料转换为CRF++训练用的语料格式(2列,4-tag):

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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: 52nlpcn@gmail.com
# Copyright 2014 @ YuZhen Technology
#
# 4 tags for character tagging: B(Begin), E(End), M(Middle), S(Single)

import codecs
import sys

def character_tagging(input_file, output_file):
    input_data = codecs.open(input_file, 'r', 'utf-8')
    output_data = codecs.open(output_file, 'w', 'utf-8')
    for line in input_data.readlines():
        word_list = line.strip().split()
        for word in word_list:
            if len(word) == 1:
                output_data.write(word + "\tS\n")
            else:
                output_data.write(word[0] + "\tB\n")
                for w in word[1:len(word)-1]:
                    output_data.write(w + "\tM\n")
                output_data.write(word[len(word)-1] + "\tE\n")
        output_data.write("\n")
    input_data.close()
    output_data.close()

if __name__ == '__main__':
    if len(sys.argv) != 3:
        print "pls use: python make_crf_train_data.py input output"
        sys.exit()
    input_file = sys.argv[1]
    output_file = sys.argv[2]
    character_tagging(input_file, output_file)

只需要执行“python make_crf_train_data.py ./icwb2-data/training/msr_training.utf8 msr_training.tagging4crf.utf8” 即可得到CRF++要求的格式的训练文件msr_training.tagging4crf.utf8,样例如下:

1
2
3
4
5
6
7
8
9
10
11
“ S
人 B
们 E
常 S
说 S
生 B
活 E
是 S                                      
一 S
部 S
...

有了这份训练语料,就可以利用crf的训练工具crf_learn来训练模型了,执行如下命令即可:

crf_learn -f 3 -c 4.0 template msr_training.tagging4crf.utf8 crf_model

这次训练的时间稍微有些长,在我的4G内存的mac pro上跑了将近700轮,大约2个小时,最终训练的crf_model约51M。有了模型,现在我们需要做得还是准备一份CRF++用的测试语料,然后利用CRF++的测试工具crf_test进行字标注。原始的测试语料是icwb2-data/testing/msr_test.utf8 ,样例如下:

1
2
3
4
5
6
7
8
9
10
扬帆远东做与中国合作的先行
希腊的经济结构较特殊。
海运业雄踞全球之首,按吨位计占世界总数的17%。
另外旅游、侨汇也是经济收入的重要组成部分,制造业规模相对较小。
多年来,中希贸易始终处于较低的水平,希腊几乎没有在中国投资。
十几年来,改革开放的中国经济高速发展,远东在崛起。
瓦西里斯的船只中有40%驶向远东,每个月几乎都有两三条船停靠中国港口。
他感受到了中国经济发展的大潮。
他要与中国人合作。
他来到中国,成为第一个访华的大船主。

这里我们同样提供一个python脚本 make_crf_test_data.py 对测试语料进行处理,将其转换为CRF++要求的格式(2列,B作为最后一列的占位符)

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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: 52nlpcn@gmail.com
# Copyright 2014 @ YuZhen Technology
#
# 4 tags for character tagging: B(Begin), E(End), M(Middle), S(Single)

import codecs
import sys

def character_split(input_file, output_file):
    input_data = codecs.open(input_file, 'r', 'utf-8')
    output_data = codecs.open(output_file, 'w', 'utf-8')
    for line in input_data.readlines():
        for word in line.strip():
            word = word.strip()
            if word:
                output_data.write(word + "\tB\n")
        output_data.write("\n")
    input_data.close()
    output_data.close()

if __name__ == '__main__':
    if len(sys.argv) != 3:
        print "pls use: python make_crf_test_data.py input output"
        sys.exit()
    input_file = sys.argv[1]
    output_file = sys.argv[2]
    character_split(input_file, output_file)

执行“python make_crf_test_data.py ./icwb2-data/testing/msr_test.utf8 msr_test4crf.utf8”即可得到可用于CRF++测试的测试语料msr_test4crf.utf8,样例如下:

1
2
3
4
5
6
7
8
9
10
11
扬 B
帆 B
远 B
东 B
做 B
与 B
中 B
国 B
合 B
作 B                                                    
...

现在执行crf_test即可得到字标注结果:

crf_test -m crf_model msr_test4crf.utf8 > msr_test4crf.tag.utf8

msr_test4crf.tag.utf8即是标注结果,样例如下:

1
2
3
4
5
6
7
8
9
10
11
扬 B   B
帆 B   E
远 B   B
东 B   E
做 B   S
与 B   S
中 B   B
国 B   E
合 B   B
作 B   E                                       
...

最后我们还需要一个脚本,按标注的词位信息讲这份结果再转化为分词结果,这里我们仍然提供一个转换脚本 crf_data_2_word.py :

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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: 52nlpcn@gmail.com
# Copyright 2014 @ YuZhen Technology
#
# 4 tags for character tagging: B(Begin), E(End), M(Middle), S(Single)

import codecs
import sys

def character_2_word(input_file, output_file):
    input_data = codecs.open(input_file, 'r', 'utf-8')
    output_data = codecs.open(output_file, 'w', 'utf-8')
    for line in input_data.readlines():
        if line == "\n":
            output_data.write("\n")
        else:
            char_tag_pair = line.strip().split('\t')
            char = char_tag_pair[0]
            tag = char_tag_pair[2]
            if tag == 'B':
                output_data.write(' ' + char)
            elif tag == 'M':
                output_data.write(char)
            elif tag == 'E':
                output_data.write(char + ' ')
            else: # tag == 'S'
                output_data.write(' ' + char + ' ')
    input_data.close()
    output_data.close()

if __name__ == '__main__':
    if len(sys.argv) != 3:
        print "pls use: python crf_data_2_word.py input output"
        sys.exit()
    input_file = sys.argv[1]
    output_file = sys.argv[2]
    character_2_word(input_file, output_file)

只需执行“python crf_data_2_word.py msr_test4crf.tag.utf8 msr_test4crf.tag2word.utf8” 即可得到合并后的分词结果文件 msr_test4crf.tag2word.utf8,样例如下:

1
2
3
4
5
6
7
8
9
10
11
扬帆  远东  做  与  中国  合作  的  先行 
 希腊  的  经济  结构  较  特殊  。 
 海运  业  雄踞  全球  之  首  ,  按  吨  位  计  占  世界  总数  的  17%  。 
 另外  旅游  、  侨汇  也是  经济  收入  的  重要  组成部分  ,  制造业  规模  相对  较小  。 
 多年来  ,  中  希  贸易  始终  处于  较低  的  水平  ,  希腊  几乎  没有  在  中国  投资  。 
 十几年  来  ,  改革开放  的  中国  经济  高速  发展  ,  远东  在  崛起  。 
 瓦西里斯  的  船只  中  有  40%  驶  向  远东  ,  每个  月  几乎  都  有  两三条  船  停靠  中国  港口  。 
 他  感受  到  了  中国  经济  发展  的  大潮  。 
 他  要  与  中国人  合作  。 
 他  来到  中国  ,  成为  第一个  访  华  的  大船  主  。
 ...

有了这个CRF字标注分词结果,我们就可以利用backoff2005的测试脚本来测一下这次分词的效果了:

./icwb2-data/scripts/score ./icwb2-data/gold/msr_training_words.utf8 ./icwb2-data/gold/msr_test_gold.utf8 msr_test4crf.tag2word.utf8 > msr_crf_segment.score

结果如下:

=== SUMMARY:
=== TOTAL INSERTIONS: 1412
=== TOTAL DELETIONS: 1305
=== TOTAL SUBSTITUTIONS: 2449
=== TOTAL NCHANGE: 5166
=== TOTAL TRUE WORD COUNT: 106873
=== TOTAL TEST WORD COUNT: 106980
=== TOTAL TRUE WORDS RECALL: 0.965
=== TOTAL TEST WORDS PRECISION: 0.964
=== F MEASURE: 0.964
=== OOV Rate: 0.026
=== OOV Recall Rate: 0.647
=== IV Recall Rate: 0.974
### msr_test4crf.tag2word.utf8 1412 1305 2449 5166 106873 106980 0.965 0.964 0.964 0.026 0.647 0.974

这次我们获得了一个准确率,召回率以及F值都在96%以上的结果,相对于前面几节的测试结果,这个CRF字标注分词结果还相对不错。不过是不是感觉上面的步骤有些繁琐,有没有一次到位的CRF分词器,这里我们同样提供一个CRF分词脚本 crf_segmenter.py ,利用CRF++的python工具包,做到一次输入,一次输出:

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
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# Author: 52nlpcn@gmail.com
# Copyright 2014 @ YuZhen Technology
#
# CRF Segmenter based character tagging:
#     4 tags for character tagging: B(Begin), E(End), M(Middle), S(Single)

import codecs
import sys

import CRFPP

def crf_segmenter(input_file, output_file, tagger):
    input_data = codecs.open(input_file, 'r', 'utf-8')
    output_data = codecs.open(output_file, 'w', 'utf-8')
    for line in input_data.readlines():
        tagger.clear()
        for word in line.strip():
            word = word.strip()
            if word:
                tagger.add((word + "\to\tB").encode('utf-8'))
        tagger.parse()
        size = tagger.size()
        xsize = tagger.xsize()
        for i in range(0, size):
            for j in range(0, xsize):
                char = tagger.x(i, j).decode('utf-8')
                tag = tagger.y2(i)
                if tag == 'B':
                    output_data.write(' ' + char)
                elif tag == 'M':
                    output_data.write(char)
                elif tag == 'E':
                    output_data.write(char + ' ')
                else: # tag == 'S'
                    output_data.write(' ' + char + ' ')
        output_data.write('\n')
    input_data.close()
    output_data.close()

if __name__ == '__main__':
    if len(sys.argv) != 4:
        print "pls use: python crf_segmenter.py model input output"
        sys.exit()
    crf_model = sys.argv[1]
    input_file = sys.argv[2]
    output_file = sys.argv[3]
    tagger = CRFPP.Tagger("-m " + crf_model)
    crf_segmenter(input_file, output_file, tagger)

只需执行“python crf_segmenter.py crf_model ./icwb2-data/testing/msr_test.utf8 msr_test.seg.utf8”即可得到与前面几步得到的分词结果完全一致的CRF分词结果:msr_test.seg.utf8 。

好了,到此为止,关于字标注中文分词的系列终于可以画上句号了,这个系列中所举的例子以及所提供的脚本都是toy级别的中文分词工具,距离一个真正实用的中文分词器还有很多路要走,不过既然路已经打开,欢迎大家和我们一起继续探索中文分词的奥秘。

注:原创文章,转载请注明出处“我爱自然语言处理”:www.52nlp.cn

本文链接地址:http://www.52nlp.cn/中文分词入门之字标注法4

转载于:https://www.cnblogs.com/DjangoBlog/p/4201527.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/276962.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

后台设置 datakeynames

FormView2.DataKeyNames new String[] { "ShoppingRemarkID" }; 转载于:https://www.cnblogs.com/Fernando/archive/2008/01/16/1041717.html

4K 海思 联咏 芯片_老电视也有春天,换装海美迪4K电视盒子H7 Plus

写在前面YALL&#xff0c;大家好&#xff0c;我是老炮儿许老板。疫情进入六月逐渐好转&#xff0c;各级各类学校相继开学&#xff0c;年前给儿子报的托班也终于迎来了开学&#xff0c;平日里帮忙照看儿子的爷爷奶奶也终于得到了解放。现在白天有大把大把的时间来追剧看电视&…

知识付费不热了,得到们接下来故事怎么讲?

如今&#xff0c;知识付费风口已过&#xff0c;红利期随之在逐渐消失&#xff0c;很多知识付费的创业者也在感叹生意难做&#xff0c;甚至有人已经开始离场。比如&#xff0c;百度音频知识付费产品只生存了6个月&#xff0c;最后的更新时间则停在7月13日。再如&#xff0c;在分…

I'm genius,用游戏柄控制鼠标

昨天不小心把鼠标放在店里没有带回来&#xff0c;今天电脑就没有鼠标了&#xff0c;用了很久的键盘&#xff0c;实在不爽&#xff0c;就突然发现自己有一个游戏柄&#xff0c;后来到网上查了一下怎么用游戏柄控制鼠标&#xff0c;呵呵&#xff0c;发现了一个&#xff0c;下载用…

WCF从理论到实践(4):路在何方

本文的出发点 通过阅读本文&#xff0c;您能了解以下知识&#xff1a; Address是什么&#xff1f; Address的组成&#xff1f; 如何在配置文件中指定Address? 如何通过编程方式设置Address? Address有什么特殊应用&#xff1f; 本文适合的读者 适合WCF初学者&#xff…

office 2007图标_微软Office 365桌面版新图标开始测试

IT之家3月1日消息 此前&#xff0c;微软公布了全新的Office图标&#xff0c;微软Office 365在线网页版在2月15日开始已经全面更新新版图标&#xff0c;而桌面版Office 365现在也陆续开始测试新版图标。目前微软Office Dogfood通道上推送的开发者预览版本已经在2月27日开始测试O…

【动态规划BFS】相遇

这是我第一次模拟题测试点全部AC。。。 同机房的DALAO都用的BFS 然而我用的DP&#xff08;其实不会BFS&#xff09; 话不多说&#xff0c;上题&#xff01; &#xff08;灰常详细&#xff09;DP解法&#xff1a; 重点还是状态转移方程式的推导 1个点i要么是后面的位置i-1往前走…

Ruby on Rails 通过代理远程安装

在网上查了一些资料&#xff0c;都不详细&#xff0c;现在列出标准命令&#xff1a; 1。如果代理服务器需要认证 gem install rails --include-dependencies --http-proxy http://username:passwordproxy:port 2。如果代理服务器不需要认证 gem install rails --include-depend…

五个思路,教你如何建立金融业的数据分析管理模型

说起银行、保险、股票投资这样的金融行业&#xff0c;很多人都认为它们是依靠数据驱动的企业&#xff0c;毕竟大数据的诞生本来就是为了金融信息流通而服务的&#xff0c;但在我身边很多搞证券、投资的朋友看来&#xff0c;事实却并非如此。 真正在金融行业做数据分析的人&…

【SSH网上商城项目实战19】订单信息的级联入库以及页面的缓存问题

购物车这一块还剩最后两个问题&#xff0c;就是订单信息的级联入库和页面缓存&#xff0c;这里的信息是指购物车和购物项&#xff0c;即我们将购物车的信息存入数据库的同时&#xff0c;也存入每个购物项的信息&#xff0c;而且外键都关联好&#xff0c;这涉及到了Hibernate中的…

exfat分配单元大小选多少_安防监控摄像机视角大小和镜头毫米数的基础知识!...

关于选择监控镜头毫米数的问题&#xff0c;虽然只有新手才有此困惑&#xff0c;但是我们还是要认真地说一说。监控视角&#xff0c;就是指监控照射的镜头所能覆盖到的范围&#xff0c;就是监控画面所能看到的角度统称叫监控视角。我们正常选购监控的时候&#xff0c;除了可以选…

彩信编辑器之预览功能

html代码 <table width"200"height"250"border"0"cellpadding"0"cellspacing"0"bgcolor"#666666"><tr><td align"center"valign"middle"><marquee id"MMScreen&qu…

java 几个实用的小工具

1、除法运算 编程的人都知道&#xff0c;java中的“/”、“%”运算&#xff0c;其中前者为取整&#xff0c;后者取余数。那么有没有快捷的运算方法取正常的运算结果呢&#xff1f; 查了资料&#xff0c;发现很简单。代码如下&#xff1a; public static String txfloat(int a,i…

处理模板页菜单高亮

//处理模板页菜单高亮var urlstatus false;$("#indexMenu a").each(function () {if ((location.href /).indexOf($(this).attr(href)) > -1 && $(this).attr(href) ! ) {$(this).parent().addClass(active);urlstatus true;} else {$(this).parent().…

动画演示 Delphi 2007 IDE 功能[3] - 修改属性

动画剧本:添加控件后用 F11 激活 Object Inspector 窗口;可用 ↑ ↓ 选择属性;用 Tab 切换属性名和属性值;用 Tab 切换到属性名后, 键入属性名的部分字母, 可迅速定位;用 Tab 切换到属性值后, 也可以键入字母选择, 而后回车确认.Ctrl↓ 可以选择其他控件;整个过程可以做到无鼠标…

kali怎么成为管理员_网站死链是什么、是怎么引起的以及死链对SEO优化的影响?...

网站死链是我们在做SEO时必不可少的一个错误&#xff0c;对于从事SEO行业的人员来说&#xff0c;网站死链最熟悉不过了&#xff0c;但是对于那些刚入SEO行业的新手来说&#xff0c;还是不太熟悉。今天我们就给大家讲一下什么是网站死链&#xff1f;网站死链是怎么引起的&#x…

Map-Reduce入门

1、Map-Reduce的逻辑过程 假设我们需要处理一批有关天气的数据&#xff0c;其格式如下&#xff1a; 按照ASCII码存储&#xff0c;每行一条记录每一行字符从0开始计数&#xff0c;第15个到第18个字符为年第25个到第29个字符为温度&#xff0c;其中第25位是符号/-006701199099999…

Java之泛型T T与T的用法

<T> T表示返回值是一个泛型&#xff0c;传递啥&#xff0c;就返回啥类型的数据&#xff0c;而单独的T就是表示限制你传递的参数类型&#xff0c;这个案例中&#xff0c;通过一个泛型的返回方式&#xff0c;获取每一个集合中的第一个数据&#xff0c; 通过返回值<T>…

UrlReWriter 使用经验小结

UrlRewriter 是微软封装好了的一个URL重写组件。使用它可以让我节约很多自已开发的时间。 好了&#xff0c;开始讲述我的应用经验&#xff0c;这只是很菜鸟的经验&#xff0c;高手就不用看了。 第一步&#xff0c;请从此下载此组件。解压&#xff0c;把UrlRewriter.dll copy到你…

clickhouse大数据分析技术与实战_从销售到经营——大客户销售策略与实战技术...

对于首席客户代表而言&#xff0c;要走出困局&#xff0c;所需要大客户销售策略性的训练&#xff0c;而不是像基层客户经理的销售技巧训练一样&#xff1b;新业务的学习固然重要&#xff0c;但更重要的是转化成实战绩效。从组织变革角度&#xff0c;每次成功的业务转型背后都意…