GanjinZero.github.io

  • 首页

  • 归档

科学麻将:从不放炮开始

发表于 2019-03-26 | 更新于 2019-03-28

项目地址

https://github.com/GanjinZero/Tenpai_prediction

项目背景

日本麻将是一种最强调防守的麻将,它比其他的麻将更注重不要点炮(也就是放铳)。雀魂最近比较流行,所以我又重新开始玩日麻(以前在MJ和天凤都打过一点)。我也比较菜,才打到雀士三。一个经常遇到的场景时,当有人立直(门清宣告听牌)的时候,当我选择弃胡时,我想知道应该打出什么样的牌才不会点炮。这就是在这个项目中研究的问题:当他家率先立直时,他家可能的听牌有哪些。这个问题可以看成是一个文本分类问题来考虑,将前面已经打过的牌当作文本,听牌考虑成文本最终的分类。当然这还是和文本分类问题不太一样的,因为对于某一个文本一般是固定一个分类(比如情感分类中的积极或者消极);而对于麻将而言首先一次听牌可以听好几种牌(纯正九莲宝灯!)、其次同样的舍牌可能听的牌完全不同。

在这里推荐一本书《科学するマジャン》,可以在苹果的图书商店下载到。这里有利用概率论计算的麻将打法和一些关于麻将的数值模拟结果。本项目也是在阅读该书中产生的想法。

听说你在做大牌

1
ロン!断幺九!30符1番,1000点!

数据准备

牌谱收集

最初是在《科学する麻雀》中看到了该书作者とつげき東北的个人主页,然后在这面找到他收集的一些在东风庄这个平台上的一些牌谱。

kagakul

一共收集有万份左右的牌谱。

一份牌谱的示例如下

1
2
3
4
5
6
7
8
9
10
東2局 0本場(リーチ0) YZKTR 3000 松戸の俊 -1500 菌太郎 -1000 シャモア -500 
30符 二飜ツモ リーチ 門前清模和
[1西]3p8p9p3s4s8s8s南西北白白発
[2北]1m5m6m7m4p6p1s5s7s東白白中
[3東]3m5m2p3p4p6p8p9p1s5s7s8s8s
[4南]1m4m4m9m1p5p5p7p9p4s4s北中
[表ドラ]西 [裏ドラ]北
* 3G9s 3D9s 4G中 4d9m 1G8m 1d北 2G4m 2d1s 3G6p 3D6p 4G1p 4d1m
* 1G6s 1d南 2G2s 2d1m 3G6s 3D6s 4G2s 4D2s 1C3s4s 1d8m 2C6m7m 2d2s
* 3G3s 3G3s 4G7p 4d9p 4R 1G3s 1d9p

这里记录了对局信息,胡牌的番型和各家起手牌、宝牌、每家每一轮的摸牌、切牌和鸣牌。这些牌谱的具体信息会在下文的牌谱准备中详细介绍。4R代表南家立直,那么对于东、西、北家都需要预测南家可能的听牌。因为各家的起手牌不同,摸到的牌也不同,所以对于南家的听牌有不同的估计(在德扑中叫做阻隔牌)。三家由于有不同的起手信息,所以可以生成三份训练数据。例如对于北家而言,可以只留下北家可以知道的信息作为训练用的x,而将南家的真实听牌作为训练用的y。

数据增强

只用这些牌谱数据看起来还有些不够,训练出的结果不是很理想。考虑可以这样生成一些假的牌谱。将中、发、白以某种顺序置换;将饼、万、索以某种顺序置换;将123456789变成987654321。这样的变换不能保证是完全合理的。一个原因是绿一色导致索和饼、万并不是完全等价的,但考虑到绿一色出现的概率如此的低就不管了。另一个原因是宝牌的问题,比如原来的宝牌指示牌是1m,宝牌是2m。如果进行了123456789变成987654321,宝牌就会变成8m;这时宝牌指示牌并不能变成9m,而变成了7m。这两个问题不能很好解决,但为了获得更多的牌谱,还是进行了这几种置换。中发白的置换共6种,饼万索的置换共6种,数字颠倒共2种(颠倒或者不颠倒),一共6*6*2=72种变换方式。对每一份牌谱,我们随机的选择k=7种变换作为增强的数据。(考虑到内存大小,k不要太大)

将牌谱编码

我们将每一次摸牌,鸣牌或者打牌都定义为一个action,然后将这个action嵌入到一个52维向量中。这个向量描述了这个动作是谁执行的(东西南北家),是进行了什么动作(摸牌、切牌、吃碰杠、立直),是和哪一张牌进行了交互,交互牌是否是自风、场风、宝牌这些信息。具体的编码方式可以看/src/haifu_parser.py中的action_to_vector(action, player, chanfon, jikaze, dora_list)函数。

模型训练

模型使用了双层LSTM网络连接34维的Softmax层进行预测(麻将一共34张不同的牌)。损失函数为交叉熵。在两块1080Ti的显卡下训练70个epoch得到了预训练的模型,大约需要训练2个小时。具体的模型可以参照/src/neural_network.py中的结构。

进行预测

预备工作

需要有可以编译Python3的环境。在终端中输入

1
$ git clone https://github.com/GanjinZero/Tenpai_prediction.git

下载该项目。在终端中输入

1
$ pip install -r requirements.txt

安装依赖。

牌谱准备

预训练好的模型保存在model/tenpai.model。我们需要将牌谱设置为data/test.txt中的格式,并保存到data/test.txt中:

1
2
3
4
5
6
7
8
9
10
東2局 0本場(リーチ0)
123
[1西]
[2北]1m5m6m7m4p6p1s5s7s東白白中
[3東]
[4南]
[表ドラ]西 [裏ドラ]北
* 3D9s 4d9m 1d北 2G4m 2d1s 3D6p 4d1m
* 1d南 2G2s 2d1m 3D6s 4D2s 1C3s4s 1d8m 2C6m7m 2d2s
* 3D3s 4d9p 4R 1G3s 1d9p

  • 第一行填写东x局(或者南x局),后面的本场、立直棒、点棒信息都不是必要的。
  • 第二行填写符数、翻数、番形,可以留空行,但不能把这行都删了。
  • 第三-六行填写四家起手牌,可以只填自家牌,其他留空。其中m代表万,p代表饼,s代表索;“東南西北中発白”请使用日语汉字。比如:

    1
    2
    3
    4
    [1西]
    [2北]1m5m6m7m4p6p1s5s7s東白白中
    [3東]
    [4南]
  • 第七行填写宝牌和里宝牌,里宝牌可以不填。注意是宝牌,不是宝牌指示牌!

  • 第八行起填写这局牌的行进过程。每一行以*开始,每一个行动和行动之间有一个空格。比如第一行的动作3D9s可以翻译为东家摸切9s,4d9m可以翻译为3家切掉9m。只需要记录自家的摸牌动作(在这里就是2G,因为其他家摸到的牌你是看不见的,就算输入了模型也会忽略其他家的摸牌数据)完整的动作对应表见下表:
字符 含义 用法示例
G 自摸(不是自摸和) 1G1m
d 切牌 1d2s
D 摸切 1D1m
N 碰 1N
C 吃 1C1s3s(1s3s是玩家1自己的牌)
K 杠 1K1s
R 立直 1R
A 胡牌 1A

data/test.txt中可以保存多个牌谱,请在牌谱和牌谱之间用空行分隔。

P.S. 如果可以直接获取到文字格式的天凤或者雀魂牌谱,可以编写一个牌谱的自动encoder,就不需要上述这么麻烦了。

开始预测

在src文件夹下,使用如下的命令进行预测

1
$ python predict.py

就可以看到类似如下的预测结果

1
2
3
4
5
6
7
8
9
10
Richi player tenpai: ['3m', '6m', '9m']
Player 1:
{'3m': 0.33759603, '6m': 0.33912653, '9m': 0.32323775}
Richi player tenpai: ['3m', '6m', '9m']
Player 2:
{'3m': 0.337948, '6m': 0.33527905, '9m': 0.31589714}
Richi player tenpai: ['3m', '6m', '9m']
Player 3:
{'3m': 0.33415237, '6m': 0.33977884, '9m': 0.32597464}
Richi player tenpai: ['6m']

其他

欢迎提供更多的牌谱和咖啡给作者!联系作者:

Github - https://github.com/GanjinZero/

Email - yuanz17@mails.tsinghua.edu.cn

Jyama

教程:使用Bert预训练模型文本分类

发表于 2019-02-28

Bert介绍

Bert模型是Google在2018年10月发布的语言表示模型,Bert在NLP领域横扫了11项任务的最优结果,可以说是现今最近NLP中最重要的突破。Bert模型的全称是Bidirectional Encoder Representations from Transformers,是通过训练Masked Language Model和预测下一句任务得到的模型。关于Bert具体训练的细节和更多的原理,有兴趣的读者可以去看在arXiv上的原文。本篇文章从实践入手,带领大家进行Bert的中文文本分类和作为句子向量进行使用的教程。

准备工作

1.下载bert

1
git clone https://github.com/google-research/bert.git

2.下载bert预训练模型

Google提供了多种预训练好的bert模型,有针对不同语言的和不同模型大小的。对于中文模型,我们使用Bert-Base, Chinese。为了下载该模型,可能需要使用梯子。如果需要下载其他的模型(英文以及其他语言),可以在Bert里的Pre-trained models找到下载链接。

3.(可选项)安装bert-as-service,这是一个可以利用bert模型将句子映射到固定长度向量的服务。

1
2
pip install bert-serving-server # server
pip install bert-serving-client # client, independent of 'bert-serving-server'

该服务要求tensorflow的最低版本为1.10。

准备数据

数据格式

作为中文文本分类问题,需要先将数据集整理成可用的形式。不同的格式对应了不同的DataProcessor类。可以将数据保存成如下格式:

1
2
game	APEX是个新出的吃鸡游戏。
technology Google将要推出tensorflow2.0。

一行代表一个文本,由标签加上一个tab加上正文组成。

将文本分割为三个文件,train.tsv(训练集),dev.tsv(验证集),test.tsv(测试集);然后放置在同一个data_dir文件夹下。

编写DataProcessor类

在run_classifier.py中的def main(_):函数中将processors的内容增加为

1
2
3
4
5
6
7
processors = {
"cola": ColaProcessor,
"mnli": MnliProcessor,
"mrpc": MrpcProcessor,
"xnli": XnliProcessor,
"mytask": MyTaskProcessor,
}

实现如下的MyTaskProcessor(DataProcessor)类,并将这一段代码放置在run_classifier.py和其他Processor并列的位置。

__init__(self)中的self.labels含有所有的分类label。

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
class MyTaskProcessor(DataProcessor):
"""Processor for the News data set (GLUE version)."""

def __init__(self):
self.labels = ['game', 'fashion', 'houseliving']

def get_train_examples(self, data_dir):
return self._create_examples(
self._read_tsv(os.path.join(data_dir, "train.tsv")), "train")

def get_dev_examples(self, data_dir):
return self._create_examples(
self._read_tsv(os.path.join(data_dir, "dev.tsv")), "dev")

def get_test_examples(self, data_dir):
return self._create_examples(
self._read_tsv(os.path.join(data_dir, "test.tsv")), "test")

def get_labels(self):
return self.labels

def _create_examples(self, lines, set_type):
"""Creates examples for the training and dev sets."""
examples = []
for (i, line) in enumerate(lines):
guid = "%s-%s" % (set_type, i)
text_a = tokenization.convert_to_unicode(line[1])
label = tokenization.convert_to_unicode(line[0])
examples.append(
InputExample(guid=guid, text_a=text_a, text_b=None, label=label))

return examples

如果数据格式并不是一个label,一个tab,一段文本;则需要更改_create_examples()的实现。

编写运行脚本

新建一个运行脚本文件名为run.sh,将文件内容编辑为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
export DATA_DIR=/media/ganjinzero/Code/bert/data/
export BERT_BASE_DIR=/media/ganjinzero/Code/bert/chinese_L-12_H-768_A-12

python run_classifier.py \
--task_name=mytask \
--do_train=true \
--do_eval=true \
--data_dir=$DATA_DIR/ \
--vocab_file=$BERT_BASE_DIR/vocab.txt \
--bert_config_file=$BERT_BASE_DIR/bert_config.json \
--init_checkpoint=$BERT_BASE_DIR/bert_model.ckpt \
--max_seq_length=128 \
--train_batch_size=32 \
--learning_rate=2e-5 \
--num_train_epochs=3.0 \
--output_dir=/mytask_output

其中DATA_DIR是你的要训练的文本的数据所在的文件夹,BERT_BASE_DIR是你的bert预训练模型存放的地址。task_name要求和你的DataProcessor类中的名称一致。下面的几个参数,do_train代表是否进行fine tune,do_eval代表是否进行evaluation,还有未出现的参数do_predict代表是否进行预测。max_seq_length代表了句子的最长长度,当显存不足时,可以适当降低max_seq_length。

进行预测

运行脚本

1
./run.sh

可以得到类似如下样式的结果

1
2
3
4
5
***** Eval results *****
eval_accuracy = 0.845588
eval_loss = 0.505248
global_step = 343
loss = 0.505248

如果出现了这样的输出,就是运行成功了。在run.sh里指定的output_dir文件夹下可以看到模型的evaluation结果和fine-tune之后的模型文件。

以句子向量的形式使用Bert

如果想要将bert模型的编码和其他模型一起使用,将bert模型作为句子向量使用很有意义。我们可以使用bert-as-service来完成这个目标。

安装完bert-as-service以后,就可以利用bert模型将句子映射到固定长度的向量上。在终端中用一下命令启动服务:

1
bert-serving-start -model_dir /media/ganjinzero/Code/bert/chinese_L-12_H-768_A-12 -num_worker=4

model_dir后面的参数是bert预训练模型所在的文件夹。num_worker的数量应该取决于你的CPU/GPU数量。

这时就可以在Python中调用如下的命令:

1
2
3
from bert_serving.client import BertClient
bc = BertClient()
bc.encode(['一二三四五六七八', '今天您吃了吗?'])

最好以列表的形式,而非单个字符串传给bc.encode()参数,这样程序运行的效率较高。

参考文档

Github:bert

arXiv:bert

Github:bert-as-service

用Keras构造日文的神经网络语言模型

发表于 2019-01-21

摘要

本文介绍了语言模型,并介绍如何用MeCab和Keras实现一个日文的神经网络语言模型。(为什么是日文呢?纯属作者兴趣)

基于神经网络的语言模型

依据Wikepedia,语言模型的定义是“句子们的概率分布”。给定一个长度为m的句子,则可以有概率

由条件概率公式有

n-gram模型假设,第i个词语的概率分布只和前面固定的n个词有关(Markov性),那么就有

所以估计

的任务变成了估计

用传统的统计方法面临着

  • 维度灾难(当n变大,存储空间不够)
  • n元组并不会在语料库中全部出现

所以这里使用神经网络近似函数

神经网络方法解决了如上两个困难

  • 当n变大,神经网络的参数以线性级别增长
  • n元组虽然没有全部出现,但词向量可以捕捉到不同的词可能代表的相似的含义

一个传统的基于神经网络的模型结构如下图所示:
traditional

用MeCab实现日语分词

MeCab(めかぶ)是一款日语分词工具。Linux用户可以用如下指令安装MeCab:

1
2
sudo apt-get install mecab mecab-ipadic-utf8 libmecab-dev swig
pip install mecab-python3

MeCab可以对一个句子进行分词,并分析各词的词性。对于句子“すもももももももものうち”有

1
2
3
4
5
6
7
8
9
すもももももももものうち
すもも 名詞,一般,*,*,*,*,すもも,スモモ,スモモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
も 助詞,係助詞,*,*,*,*,も,モ,モ
もも 名詞,一般,*,*,*,*,もも,モモ,モモ
の 助詞,連体化,*,*,*,*,の,ノ,ノ
うち 名詞,非自立,副詞可能,*,*,*,うち,ウチ,ウチ
EOS

为了将分析的结果转化为分词结果,可用如下的mecab_to_text函数,则会输出“すもも も もも も もも の うち”。

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
def mecab_to_text(sentence_list):
"""
:param sentence_list: A list of sentences or one single sentence.
:return: A list of segmented sentences.
:note: Use mecab to segment a list of sentences or one single sentence in Japanese.
"""
import MeCab
mecab = MeCab.Tagger("-Ochasen")

single_flag = False
if isinstance(sentence_list, str):
sentence_list = [sentence_list]
single_flag = True

ret_list = []
for sentence in sentence_list:
text_list = []
m = mecab.parseToNode(sentence)
while m:
text_list.append(m.surface)
m = m.next
seg_sentence = " ".join(text_list).strip()
ret_list.append(seg_sentence)

if single_flag:
return ret_list[0]
return ret_list

模型构建

我们需要先构建我们的训练样本,语料库来自日语小说。对语料库中的句子用MeCab进行分词之后,用给定的窗宽k分割出训练集。训练集中的词和词向量进行对应为300维的向量。这样训练集中的每一个x(特征)对应一个(k-1)×300维的矩阵,每一个y(结果)对应一个one-hot的向量。

语料库

语料库是来自于网络上的日语小说,因为版权因素这里不提供下载。用什么样的小说并不会太影响我们后续的过程。在这里实现了load_text,make_word_dictionary,clear_dictionary;分别用来读入语料库,从分好词的语料库中生成词典,清理词典中在词向量里没有出现的词。

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
57
58
59
60
61
62
63
64
65
66
67
68
69
def load_text(use_length=-1, min_len=10):
start = time.clock()
japanese_text_path = "H:\\Work\\JapaneseModel\\Japanese_book\\"
text_list = []

if use_length == -1:
for file in os.listdir(japanese_text_path):
with open(japanese_text_path + file, 'r', encoding='utf-8') as f:
for line in f.readlines():
line_use = line.strip()
if len(line_use) > min_len:
text_list.append(line_use)
else:
counter = 0
for file in os.listdir(japanese_text_path):
with open(japanese_text_path + file, 'r', encoding='utf-8') as f:
for line in f.readlines():
line_use = line.strip()
if len(line_use) > min_len:
text_list.append(line_use)
counter += 1
if counter == use_length:
print("Japanese text loaded %d lines."%use_length)
elapsed = time.clock() - start
print("Time used:", round(elapsed, 3))
return text_list

print("Japanese text loaded all lines.")
elapsed = time.clock() - start
print("Time used:", round(elapsed, 3))

return text_list

def make_word_dictionary(split_text_list, lower_bound=100):
start = time.clock()

word_dictionary = dict()
for sentence in split_text_list:
sentence_use = sentence.split(" ")
for word in sentence_use:
if not word in word_dictionary:
word_dictionary[word] = 1
else:
word_dictionary[word] += 1

print("Word dictionary established.")
elapsed = time.clock() - start
print("Time used:", round(elapsed, 3))

if lower_bound > 0:
pop_list = []
for word in word_dictionary:
if word_dictionary[word] < lower_bound:
pop_list.append(word)
for word in pop_list:
word_dictionary.pop(word)

word_list = []
for word in word_dictionary:
word_list.append(word)

return word_list

def clear_dictionary(dictionary, embedding_dictionary):
ret_list = []
for word in dictionary:
if word in embedding_dictionary:
ret_list.append(word)
return ret_list

实现了这几个函数以后,就可以用如下的方式读入语料库。

1
2
3
4
japanese_text = load_text(use_text_length)
split_japanese_text = mecab_to_text(japanese_text)
dictionary = make_word_dictionary(split_japanese_text, lower_bound=10)
dictionary = clear_dictionary(dictionary, embeddings_index)

词向量

我们使用facebook在fastText项目中预训练好的日语300维词向量,下载地址点击这里。因为该文件的第一行保存了词向量文件的信息,你应该手动删除该行,然后用load_embedding函数来读取词向量。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
def load_embedding():
start = time.clock()

"""
Total 2000000 words in this embedding file, 300-d. It is float16 type.
The first line is "2000000 300".
You should delete this line.
"""
EMBEDDING_FILE = 'H:\\Work\\cc.ja.300.vec'
def get_coefs(word, *arr): return word, np.asarray(arr, dtype='float16')
embeddings_index = dict(get_coefs(*o.strip().split(" ")) for o in open(EMBEDDING_FILE, 'r', encoding="utf-8"))

elapsed = time.clock() - start
print("Word vectors loaded.")
print("Time used:", round(elapsed, 3))

return embeddings_index

生成训练集

假设我们的窗宽为k,那么我们的训练集由k-1个词组成x_train,由之后连接的词组成y_train。如果k=3,我们语料库中的一个句子为“a bb ccc d”, 其中a、bb、ccc、d分别是4个词。那么我们将这个句子前面连接k-1=2个“space”,结尾连接一个“eol”,扩充为“space space a bb ccc d eof”。这样可以得到如下的训练样本:

x1 x2 y
space space a
space a bb
a bb ccc
bb ccc d
ccc d eol

generate_train函数实现了上述生成训练集的算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
def generate_train(window, end_index, text_seq):
prefix = [0] * (window - 1)
suffix = [end_index]
x_list = []
y_list = []
for seq in text_seq:
if len(seq) > 1:
seq_use = prefix + seq + suffix
# print(seq_use)
for i in range(len(seq_use) - window + 1):
x_list.append(seq_use[i: i + window - 1])
y_list.append(seq_use[i + window - 1])
# print(seq_use[i: i + window])
return x_list, y_list

构建神经网络模型

和传统的神经网络语言模型有所不同:先将x映射为词向量,连接双层BiLSTM作为隐藏层,再连接一个Softmax来预测下一个词是什么。在Keras中,实现BiLSTM非常容易。因为CuDNNLSTM的实现比LSTM要快很多,推荐安装cudnn来使用这个函数。加入了一些Dropout层来避免过拟合。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Model
inp = Input(shape=(window - 1,))
x = Embedding(nb_words, 300, trainable = True, weights=[embedding_matrix])(inp)
x = Bidirectional(CuDNNLSTM(128, return_sequences=True))(x)
x = Dropout(0.1)(x)
x = Bidirectional(CuDNNLSTM(128, return_sequences=False))(x)
x = Dropout(0.1)(x)
x = Dense(128, activation="relu")(x)
x = Dropout(0.1)(x)
x = Dense(nb_words, activation="softmax")(x)
model = Model(inputs=inp, outputs=x)
opt = keras.optimizers.Adam(lr=0.001, beta_1=0.9, beta_2=0.999,
epsilon=None, decay=0.0, amsgrad=False)
model.compile(loss='categorical_crossentropy',
optimizer=opt, metrics=['accuracy'])
history = LossHistory()

epoch_nb = 80 # 40 is enough
batch = 64

model.fit(x_train, y_train, batch_size=batch, epochs=epoch_nb, verbose=1,
validation_data=(x_test, y_test), callbacks=[history])

随机生成句子

用predict_random_sentence函数来生成随机句子,其中的reverse_index保存了从语料库生成的词典中的词和序号的一一对应。若将[0,0,0,0]更改为其他数字,即可生成给定开头的句子。

1
2
3
4
5
6
7
8
9
10
def predict_random_sentence(new=[0] * (window - 1)):
sentence = reverse_index[new[0]] + reverse_index[new[1]] + reverse_index[new[2]] + reverse_index[new[3]]
while new[-1] != end_index:
prob = model.predict(np.asarray([new]))[0]
new_predict = int(random.choices(word_ind, weights=prob)[0])
sentence += reverse_index[new_predict]
new = new[1:] + [new_predict]
return sentence

predict_random_sentence([0,0,0,0])

保存模型

保存模型到本地,以后就可以直接调用,避免重复训练。上文中提到的tokenizer和神经网络模型都需要保存。

1
2
3
with open("../result/tokenizer.pkl", "wb") as handle:
pickle.dump(tokenizer, handle, protocol=pickle.HIGHEST_PROTOCOL)
model.save('../model/language_model.model')

效果展示

我们训练了80个epoch,使用了20000句话进行训练,选择的窗宽为5。以下是从日文语言模型中随机生成的一些句子。

1
2
3
4
5
6
7
8
'「なんだろう。僕が仕事を休みになり、でもまあ……見てた」'
'アグライアはグラスをじっと見つめた。'
'それにしても、それを使って、ジークをから表情になって猫のように《さ》がを受けた。'
'森そうだ、そんなことか」'
'真剣で命をように、そのの人は、辻宮氏はだいたい邸にてあげた《と?》みをうとした。「そんな顔だって今?」'
'佳澄ちゃんが……俺とさっきに言わせて下さい。'
'沙耶「まあ、沙耶ねえ先に戻ることにになってきます?」'
'「最近はどうしてそういうつもりじゃないでしょうね」'

简单的翻译一下生成的句子(日语水平比较烂,可能翻译错了)

1
2
3
4
5
6
7
8
'怎么说呢。我虽然下班了,但还是……看到了'
'Agria凝视着玻璃杯'
'即使如此,使用它,Sieg看来像猫一样的表情接受了さ'
'像树林啊,是这样吗'
这句话实在不太通顺……
'佳澄酱,请给我说下刚才的事情'
'沙耶:“嘛,沙耶先回去了啊?”'
'最近为什么不打算这样做了呢'

总体来说,该语言模型可以生成出一些通顺的话语。以上都是从空句子开始生成的,也可以改变生成句子的开头。

项目地址及参考文献

完整的项目代码见GitHub
Language_model
MeCab
fastText

在PyPI上发布并更新自己的python package

发表于 2019-01-17 | 更新于 2019-03-11

将package整理成如下形式

1
2
3
4
5
6
/example_pkg
/example_pkg
__init__.py
setup.py
LICENSE
README.md

编辑setup.py

注意每次更新要更新版本号。

生成distribution archives

1
python setup.py sdist bdist_wheel

上传distribution archives

1
twine upload dist/*

或者

1
python -m twine upload dist/*

参考文档

Packaging Python Projects

利用pyserverchan推送程序输出

发表于 2019-01-15

背景介绍

在深度学习的过程中,训练时间一般很长,如果可以将训练结果自动推送到微信上,可以省去不少的麻烦。Server酱是一个向微信发送自定义信息的服务,我将该服务打包成了pyserverchan,可以让python用户简单的调用。

注册Server酱

进入Server酱官网,只需要两个步骤即可完成注册。

  • 在主页登陆GitHub账号,获得一个SCKEY
  • 点击微信推送,进行绑定

至此,你已经获得了一个SCKEY。在python中这样设置你的user_URL

1
user_URL = 'https://sc.ftqq.com/' + SCKEY + '.send'

使用pyserverchan

安装pyserverchan

1
pip install pyserverchan

在Python中发送文字,图片(png格式),Markdown格式文件。(至多64K)

1
2
3
4
5
from pyserverchan import pyserver
svc = pyserver.ServerChan(user_URL)
svc.output_to_weixin("ATestMessage.")
svc.output_to_weixin_picture("http://sc.ftqq.com/static/image/bottom_logo.png")
svc.output_to_weixin_markdown("J:/pyserverchan/README.md")

使用例子

当训练神经网络时,想将训练完的准确率发送至微信,加入如下代码

1
2
3
4
import os
train_result = 'Accuracy on train:' + str(round(acc_train, 4) * 100) + "%" + os.linesep + os.linesep
train_result += 'Accuracy on test:' + str(round(acc_test, 4) * 100) + "%"
svc.output_to_weixin('Train done.', train_result) # 第一个参数是发送的文章标题,第二个参数是发送的文章内容

微信端即可收到如下结果

项目地址

  • GitHub
  • PyPi

GanjinZero

5 日志
5 标签
GitHub E-Mail
© 2019 GanjinZero
由 Hexo 强力驱动 v3.8.0
|
主题 – NexT.Muse v6.7.0
|