用JavaScript处理自然语言-音节和词

一切可以结构化的数据都可以编程。

自然语言作为人类智慧的结晶,也是可以结构化的(非结构化数据都是噪音),在进行结构化之前,需要了解其语法。本系列文章主要介绍中文自然语言的处理。

首先我们需要一边学习中文语法,一边设计数据结构。

如果要寻找计算机中还吸引我的地方,那么非自然语言处理莫属了。

单音节语素

如:土、人、水、风、子、民、大、海。

设计的数据结构(本文的数据结构将随业务逻辑的改变做出调整):

this.MonosyllabicMorphemes = [{
	id: 0,
	word: '土'
}, {
	id: 1,
	word: '人'
}, {
	id: 2,
	word: '水'
}, {
	id: 3,
	word: '风'
}];

双音节语素

双音节语素分为 双声、叠韵、 非双声叠韵联绵字、外来词、专用名词。

设计的数据结构:

this.DisyllabicMorphemes = [{
	type: 'alliteration',//双声
	words: [{
		id: 0,
		word: '乒乓'
	}, {
		id: 1,
		word: '澎湃'
	}, {
		id: 2,
		word: '踌躇'
	}, {
		id: 3,
		word: '犹豫'
	}]
}, {
	type: 'vowel rhyme',//叠韵
	words: [{
		id: 0,
		word: '从容'
	}, {
		id: 1,
		word: '葫芦'
	}, {
		id: 2,
		word: '糊涂'
	}, {
		id: 3,
		word: '蜿蜒'
	}]
}, {
	type: 'compound word',//联绵词
	words: [{
		id: 0,
		word: '蜈蚣'
	}, {
		id: 1,
		word: '珊瑚'
	}, {
		id: 2,
		word: '奚落'
	}, {
		id: 3,
		word: '蚂螂'
	}]
}, {
	type: 'loanword',//外来词
	words: [{
		id: 0,
		word: '干部'
	}, {
		id: 1,
		word: '涤纶'
	}, {
		id: 2,
		word: '吉普'
	}, {
		id: 3,
		word: '芭蕾'
	}]
}, {
	type: 'terminology',//专用名词
	words: [{
		id: 0,
		word: '纽约'
	}, {
		id: 1,
		word: '巴黎'
	}, {
		id: 2,
		word: '北京'
	}, {
		id: 3,
		word: '苏轼'
	}]
}];

多音节语素

多音节音素包括 拟声词、专用名词和音译外来词。

设计的数据结构:

this.PolysyllabicMorphemes = [{
	type: 'onomatopoetic-word',//拟声词
	words: [{
		id: 0,
		word: '噼里啪啦'
	}, {
		id: 1,
		word: '淅淅沥沥'
	}]
}, {
	type: 'terminology',//专用名词
	words: [{
		id: 0,
		word: '中华人民共和国'
	}]
}, {
	type: 'loanword',//外来词
	words: [{
		id: 0,
		word: '安迪斯'
	}, {
		id: 1,
		word: '喜马拉雅'
	}, {
		id: 2,
		word: '法兰克福'
	}, {
		id: 3,
		word: '奥林匹克'
	}]
}];

实词

实词指有实际意义的词,包括:名词、动词、形容词、数词、量词、代词。

this.notionalWord = ['noun', 'verb', 'adj', 'numeral', 'classifier', 'pronoun'];

名词

名词包括人物、事物、时间、方位等。

动词

动词是表示动作行为及发展变化的词,包括行为动词、发展动词、心理动词、存现动词、使现动词、使令动词、能愿动词、趋向动词、判断动词等。

形容词

形容词是表示事物性质、状貌特征的词,包括形状、性质、状态等。

数词

数词是表示事物数目的词,包括确数、概数、序数。

量词

量词是表示事物或动作的单位,包括有名量词和有动量词。

代词

代词是能代替事物名称的词,包括人称代词、疑问代词和指示代词。

this.notionalWordList = {
	noun: [{
		type: 'people',
		words: [{
			id: 0,
			word: '学生'
		}, {
			id: 1,
			word: '群众'
		}, {
			id: 2,
			word: '老头'
		}, {
			id: 3,
			word: '妇女'
		}, {
			id: 4,
			word: '同志'
		}]
	}, {
		type: 'stuff',
		words: [{
			id: 0,
			word: '杉木'
		}, {
			id: 1,
			word: '笔'
		}, {
			id: 2,
			word: '蜗牛'
		}, {
			id: 3,
			word: '猎豹'
		}, {
			id: 4,
			word: '战斗机'
		}]
	}],

	verb: [{
		type: 'behavior',
		words: [{
			id: 0,
			word: '跑'
		}, {
			id: 1,
			word: '唱'
		}, {
			id: 2,
			word: '喝'
		}, {
			id: 3,
			word: '敲'
		}, {
			id: 4,
			word: '盯'
		}]
	}, {
		type: 'develop',//发展动词
		words: [{
			id: 0,
			word: '生长'
		}, {
			id: 1,
			word: '枯萎'
		}, {
			id: 2,
			word: '发芽'
		}, {
			id: 3,
			word: '结果'
		}, {
			id: 4,
			word: '产卵'
		}]
	}],

	adj: [{
		type: 'shape',
		words: [{
			id: 0,
			word: '大'
		}, {
			id: 1,
			word: '高'
		}, {
			id: 2,
			word: '胖'
		}, {
			id: 3,
			word: '细'
		}, {
			id: 4,
			word: '壮'
		}]
	}, {
		type: 'nature',
		words: [{
			id: 0,
			word: '甜'
		}, {
			id: 1,
			word: '好'
		}, {
			id: 2,
			word: '香'
		}, {
			id: 3,
			word: '漂亮'
		}, {
			id: 4,
			word: '机智'
		}]
	}, {
		type: 'state',
		words: [{
			id: 0,
			word: '快'
		}, {
			id: 1,
			word: '浓'
		}, {
			id: 2,
			word: '满'
		}, {
			id: 3,
			word: '多'
		}, {
			id: 4,
			word: '迅速'
		}]
	}],

	numeral: [{
		type: 'exact quantity',//确数
		words: [{
			id: 0,
			word: '1'
		}, {
			id: 1,
			word: '2'
		}, {
			id: 2,
			word: '3'
		}, {
			id: 3,
			word: '一'
		}, {
			id: 4,
			word: '二'
		}]
	}, {
		type: 'approximate number',//概数
		words: [{
			id: 0,
			word: '几'
		}, {
			id: 1,
			word: '一些'
		}, {
			id: 2,
			word: '左右'
		}, {
			id: 3,
			word: '以下'
		}, {
			id: 4,
			word: '余'
		}]
	}, {
		type: 'ordinal',//序数
		words: [{
			id: 0,
			word: '第一'
		}, {
			id: 1,
			word: '第二'
		}, {
			id: 2,
			word: '老大'
		}, {
			id: 3,
			word: '老二'
		}, {
			id: 4,
			word: '初一'
		}]
	}],

	classifier: [{    //量词
		type: 'famous quantifier',
		words: [{
			id: 0,
			word: '尺'
		}, {
			id: 1,
			word: '寸'
		}, {
			id: 2,
			word: '里'
		}, {
			id: 3,
			word: '斤'
		}, {
			id: 4,
			word: '元'
		}]
	}, {
		type: 'momentum word',
		words: [{
			id: 0,
			word: '把'
		}, {
			id: 1,
			word: '次'
		}, {
			id: 2,
			word: '回'
		}, {
			id: 3,
			word: '声'
		}, {
			id: 4,
			word: '幢'
		}]
	}],

	pronoun: [{      //代词
		type: 'personal pronoun',
		words: [{
			id: 0,
			word: '我'
		}, {
			id: 1,
			word: '你'
		}, {
			id: 2,
			word: '他'
		}, {
			id: 3,
			word: '她'
		}, {
			id: 4,
			word: '他们'
		}]
	}, {
		type: 'interrogative pronoun', //疑问代词dem pro
		words: [{
			id: 0,
			word: '谁'
		}, {
			id: 1,
			word: '什么'
		}, {
			id: 2,
			word: '怎么'
		}, {
			id: 3,
			word: '哪里'
		}, {
			id: 4,
			word: '为什么'
		}]
	}, {
		type: 'dem pro', //指示代词
		words: [{
			id: 0,
			word: '这'
		}, {
			id: 1,
			word: '那'
		}, {
			id: 2,
			word: '那里'
		}, {
			id: 3,
			word: '那边'
		}, {
			id: 4,
			word: '哪边'
		}]
	}]
};

虚词

虚词指没有实在意义的词,包括副词、介词、连词、助词、叹词、拟声词。

this.conj = ['adverb', 'preposition', 'conjunction', 'auxiliary word', 'interjection', 'onomatopoetic word'];//虚词

副词

副词指没有实在意义的词,包括有程度副词、有时间副词、有范围副词、有情态副词、有语气副词、有重复副词。

介词

介词用在名词、代词或名词性词组前边,合起来表示方向、对象等的词。

连词

连词指连接词、短语或句子的词。

助词

助词指附着在别的词后面、独立性差、无实义的一种特殊的虚词,包括结构助词、时态助词和语气助词。

叹词

叹词指表示感叹或者呼唤答应的词。

拟声词

拟声词指模拟事物的声音的词。

this.conjList = {
	adverb: [{
		type: 'degree adverb', //程度副词
		words: [{
			id: 0,
			word: '很'
		}, {
			id: 1,
			word: '极'
		}, {
			id: 2,
			word: '非常'
		}, {
			id: 3,
			word: '太'
		}, {
			id: 4,
			word: '过分'
		}]
	}, {
		type: 'time adverb', //时间副词
		words: [{
			id: 0,
			word: '已'
		}, {
			id: 1,
			word: '刚'
		}, {
			id: 2,
			word: '才'
		}, {
			id: 3,
			word: '将'
		}, {
			id: 4,
			word: '要'
		}]
	}, {
		type: 'scope adverb', //范围副词
		words: [{
			id: 0,
			word: '都'
		}, {
			id: 1,
			word: '全'
		}, {
			id: 2,
			word: '总'
		}, {
			id: 3,
			word: '只'
		}, {
			id: 4,
			word: '仅'
		}]
	}, {
		type: 'manner adverb', //情态副词
		words: [{
			id: 0,
			word: '正好'
		}, {
			id: 1,
			word: '果然'
		}, {
			id: 2,
			word: '刚好'
		}, {
			id: 3,
			word: '依然'
		}, {
			id: 4,
			word: '全然'
		}]
	}, {
		type: 'modal adverb', //语气副词
		words: [{
			id: 0,
			word: '准保'
		}, {
			id: 1,
			word: '确实'
		}, {
			id: 2,
			word: '不'
		}, {
			id: 3,
			word: '没有'
		}, {
			id: 4,
			word: '难道'
		}]
	}, {
		type: 'repeated adverb', //重复副词
		words: [{
			id: 0,
			word: '又'
		}, {
			id: 1,
			word: '再'
		}, {
			id: 2,
			word: '还'
		}, {
			id: 3,
			word: '仍'
		}]
	}],//副词

	preposition: [{
		type: 'preposition',
		words: [{
			id: 0,
			word: '从'
		}, {
			id: 1,
			word: '往'
		}, {
			id: 2,
			word: '在'
		}, {
			id: 3,
			word: '当'
		}, {
			id: 4,
			word: '把'
		}]
	}],//介词

	conjunction: [{
		type: 'conjunction',
		words: [{
			id: 0,
			word: '和'
		}, {
			id: 1,
			word: '同'
		}, {
			id: 2,
			word: '跟'
		}, {
			id: 3,
			word: '不但'
		}, {
			id: 4,
			word: '只要'
		}]
	}],//连词

	auxiliaryWord: [{
		type: 'interrogative pronoun',
		words: [{
			id: 0,
			word: '谁'
		}, {
			id: 1,
			word: '什么'
		}, {
			id: 2,
			word: '怎么'
		}, {
			id: 3,
			word: '哪里'
		}, {
			id: 4,
			word: '为什么'
		}]
	}, {
		type: 'dem pro', //指示代词
		words: [{
			id: 0,
			word: '这'
		}, {
			id: 1,
			word: '那'
		}, {
			id: 2,
			word: '那里'
		}, {
			id: 3,
			word: '那边'
		}, {
			id: 4,
			word: '哪边'
		}]
	}],//助词

	interjection: [{
		type: 'interjection',
		words: [{
			id: 0,
			word: '啊'
		}, {
			id: 1,
			word: '哎'
		}, {
			id: 2,
			word: '噢'
		}, {
			id: 3,
			word: '哼'
		}, {
			id: 4,
			word: '呸'
		}]
	}],//叹词

	onomatopoeticWord: [{
		type: 'onomatopoeticWord',
		words: [{
			id: 0,
			word: '哗哗'
		}, {
			id: 1,
			word: '轰隆隆'
		}, {
			id: 2,
			word: '淅淅沥沥'
		}, {
			id: 3,
			word: '咚咚'
		}, {
			id: 4,
			word: '噼里啪啦'
		}]
	}]//拟声词
}

数据结构整理好了,现在我们的需求是这样的:

输入一个短语(只能是数据结构中存在的 单字词语 ),然后将其分割,并返回其词性。

按照这个需求,我们梳理出了以下算法(由于是单子词语,出奇意料的简单):

1. 遍历用户输入的字符串;

2. 遍历语料库,并与当前字符串进行对比;

3.如果当前字符串与当前语料库中的数据相同,则已经找到了对应的词语。

全部代码:

chineseLanguageProcessing.prototype = {

	wordStack: [],

	handleSingleWord: function(word) {
		this.word = word;

		var resultList = [
			this.handleMonosyllabicMorphemes(),
			this.handleDisyllabicMorphemes(),
			this.handlePolysyllabicMorphemes(),
			this.handleNotionalWordList(),
			this.handleConjList()
		];

		for (var i = 0; i < resultList.length; i++) {
			var result = resultList[i];
			if(typeof result != 'string') {
				return result;
			}
		};

		return this.word;
	},

	handleWordStack: function() {
		return this.handleSingleWord(this.wordStack.join(''));
	},

	packWordsList: function(result, word) {
		this.wordsList.push(result);
	},

	process: function() {

		var self = this, result;

		for (var i = 0; i < this.sentence.length; i++) {
			var word = this.sentence[i];
			result = self.handleSingleWord(word);

			if(typeof result == 'string') {
				//判断下一个字符是否在数据结构内
				self.wordStack.push(word);

				if(i == this.sentence.length - 1) {
					continue;
				}

				result = self.handleSingleWord(this.sentence[i + 1]);

				//如果下一个字符也不存在就连着上一个字符进行查找
				if(typeof result == 'string') {
					// console.log('process 3', self.wordStack, word);
					result = self.handleWordStack();
					console.log('process result 3==========', result);
					if(typeof result == 'string') {
						//没找到,继续找
						console.log('not found', self.word);
					}else {
						//如果找到了 就清空
						self.wordStack = [];
						self.packWordsList(result, word);
					}
				}else {
					self.packWordsList(result, word);
				}
			}else {
				self.packWordsList(result, word);
			}
		};

		return self.wordsList;
	},

	handleMonosyllabicMorphemes: function() {

		var self = this;

		for (var i = 0; i < self.MonosyllabicMorphemes.length; i++) {
			var mm = self.MonosyllabicMorphemes[i];
			if(mm.word == self.word) {
				return {
					type: {
						en: 'MonosyllabicMorphemes',
						cn: '单音节语素'
					},
					word: mm
				};
			}
		};

		return self.word;
	},

	handleWordType: function(type, wordType) {
		var self = this;

		for (var i = 0; i < type.length; i++) {
			var dm = type[i],
				dmWords = dm.words;

			for (var j = 0; j < dmWords.length; j++) {
				var dmWord = dmWords[j];
				if(dmWord.word == self.word) {
					return {
						type: {
							en: wordType,
							cn: self.wordTypeTable[wordType]
						},
						word: dmWord,
						wordType: dm.type
					}
				}
			};
		};

		return self.word;
	},

	handleMultiWordType: function(type) {
		for(var key in this[type]) {
			var result = this.handleWordType(this[type][key], type);
			if(typeof result != 'string') {
				return result;
			}
		}
		return this.word;				
	},

	handleDisyllabicMorphemes: function() {
		return this.handleWordType(this['DisyllabicMorphemes'], 'DisyllabicMorphemes');
	},

	handlePolysyllabicMorphemes: function() {
		return this.handleWordType(this['PolysyllabicMorphemes'], 'PolysyllabicMorphemes');
	},

	handleNotionalWordList: function() {
		return this.handleMultiWordType('notionalWordList');
	},

	handleConjList: function() {
		return this.handleMultiWordType('conjList');
	}

}

var clp = new chineseLanguageProcessing('土人生水跑高太'),
	word = clp.process();

console.log(word);

输入’土人生水跑高太‘后将输出:

[{"type":{"en":"MonosyllabicMorphemes","cn":"单音节语素"},"word":{"id":0,"word":"土"}},{"type":{"en":"MonosyllabicMorphemes","cn":"单音节语素"},"word":{"id":1,"word":"人"}},"生",{"type":{"en":"MonosyllabicMorphemes","cn":"单音节语素"},"word":{"id":2,"word":"水"}},{"type":{"en":"notionalWordList","cn":"实词"},"word":{"id":0,"word":"跑"},"wordType":"behavior"},{"type":{"en":"notionalWordList","cn":"实词"},"word":{"id":1,"word":"高"},"wordType":"shape"},{"type":{"en":"conjList","cn":"虚词"},"word":{"id":3,"word":"太"},"wordType":"degree adverb"}]

这段代码还只能处理单字词语,并且会有重复分析词语的情况,比如从容,会分成“从”和“从容”两个词语,在下一个章节中,将根据语法生成更加可靠的分析数据,并且支持多字词语,这需要用到DFA算法。

项目在github上: leinue/javascript

稿源:黑白互联网 (源链) | 关于 | 阅读提示

本站遵循[CC BY-NC-SA 4.0]。如您有版权、意见投诉等问题,请通过eMail联系我们处理。
酷辣虫 » 创业投资 » 用JavaScript处理自然语言-音节和词

喜欢 (0)or分享给?

专业 x 专注 x 聚合 x 分享 CC BY-NC-SA 4.0

使用声明 | 英豪名录