【shell精巧】一个20行shell写的马尔科夫链

马尔科夫链

  • 最近看了一篇文章,用二十行shell写的一个马尔科夫链
  • 正好自己比较喜欢shell,现在摘录下来

代码

  • mrkfeed.awk: 这个用来成一个模型文件。./mrkfeed.awk < chatlog.txt >> model.mrkdb
#!/usr/bin/awk -f
{
	for(i=1; i<NF; i++) {
		print $i, $(i+1)
	}
	print $i
}
  • ./mrkwords.sh:生成一段文字的过程
#!/bin/sh
file="${1:-~/.mrkdb}"    # 选择参数当中第一个以.mrkdb结尾的文件
n="${2:-1}"              # 要生成的词的最大数量
key="$3"                 # 起始单词

[ ! -z "$key" ] && echo "$key"
[ "$n" -le 0 ] && exit

if [ -z "$key" ]; then
    word=$(shuf -n 1 < "$file" | cut -d' ' -f1)
else
    word=$(grep -Fw "$key" < "$file" | awk -v key="$key" '$1 == key {print $0}' | shuf -n 1 | awk '{print $2}') || exit
    [ -z "$word" ] && exit
fi

# 单词个数-1, 重复执行
exec "$0" "$file" "$(( n - 1 ))" "$word"

执行过程

# 清洗聊天文件,使用语料生成一个模型文件
corpus=/usr/share/fortunes/goedel    # 英文语料
sed -e '/^%$/d' < $corpus >> goedel.txt
./mrkfeed.awk < goedel.txt >> model.mrkdb

# 使用模型文件生成一段对话
./mrkwords.sh model.mrkdb 50 | tr '\n' ' '

思考

这里的模型文件实际上是一个一个的词对,比如说(is, me)这个词对在语料当中出现了100次,那么在模型文件当中就会有100行(is, me),每次抽取的时候实际上是根据当前词对的概率最大来进行的,所以非常的短小和精妙

同时我也想起了word2vec算法在实现负采样的时候,实际上也是生成一个非常巨大的词表,按照词的概率填充词表,负采样的时候,就随机从这个巨大的词表当中抽取负样本,这样就是按照概率来抽取负样本

文章来源

  • https://0x0f0f0f.github.io/posts/2019/11/really-fast-markov-chains-in-~20-lines-of-sh-grep-cut-and-awk/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值