年に一度のプリンタ稼働日

年末タスク

 

年末に実家に帰ると年賀状印刷というタスクが待っているわけですが、去年のこの時期にプリンタのノズルが目詰まりして、字がかすれてしか印刷できず、最後通告をしたつもりが、

 

父「今年もよろしく」

 

と何事もなかったように頼まれる訳で。とは言え、去年の時点で何度ノズルクリーニングを施してもダメだったので、これを試してみることに。

 

 

EPSON用プリンタヘッドクリーニング液 顔料 染料 両対応 PP-HC-E01

EPSON用プリンタヘッドクリーニング液 顔料 染料 両対応 PP-HC-E01

 

 近所の家電量販店にはさすがに置いてなかったので、アマゾン様におすがりすることに。

 

試してみよう

翌日の大晦日の午前中に品物が届き、何はともあれ試すことに。

 

f:id:deutschina:20161231091955j:image

開封すると中身はこんな感じ

f:id:deutschina:20161231092019j:image

説明書によると、注射器に2ml薬液を入れて、注射器の先に取り付けられたチューブをプリンタ側のカートリッジ接続部に繋げて、薬液をゆっくり出したり入れたりするとのこと。

 

f:id:deutschina:20161231092349j:image

プリンタをカートリッジ交換モードにして、言われた通りにやってみる。

f:id:deutschina:20161231092434j:image

薬液を出して、それを吸い取ると…という目論見だったけど、出した薬液が戻って来ない。

f:id:deutschina:20161231092444j:image

どこからか漏れているのかも。とは言え、あまり大量に薬液を注入するわけにも行かないので、とりあえず2回分の4mlを注入して待つこと30分。

 

結果的にはダメ。ノズルチェックをしてもやる前と全く同じ。とは言えここで諦めるのはもったいないので、今度は4mlを2回分注入してこれでダメなら諦めることに。

 

なるかミラクル

 さらに待つこと30分。今度は上手く行くかと思ったら、何と黒以外の5色のインクの残量がなくなり試せず…w

 

純正インクカートリッジ交換だと約6,000円。しかも、インクノズルの目詰まりが直らなかった場合は完全に無駄に。一方で事前に調べておいた新品プリンタの価格が約10,000円。

 

判断は両親に委ねました。ま、性格知り尽くしているので、どっちに転がるかは分かってましたけどね。

 

数時間後

 家電量販店に並ぶ格安モデルをゲットしてきました。

 プリンタはもう完全に髭剃りモデルに突入ですな。本体価格が1万円を割り込んで、インクカートリッジで儲けるモデルに。それも、ネットプリントの波に押されてあと何年続くんでしょうかね。

 

ということで、大晦日の午後2時。年賀状の作成に取り掛かろうとしております。 

 

 

 

Windows10での環境構築

サボりの原因は

気がつけば9ヶ月も放置してました。2015年年末から入門Python 3の写経シリーズをやって、3月頃にはグラフデータベースの話なんかも扱ってました。その後パッタリ更新が止まっていた理由を考えると、ズバリ本業が忙しかったからですね。春先は東京の北にある海のない県だとか、夏からは、西の方の本州じゃない島に長期出張する生活を繰り返しておりました。

とりあえずPythonまわりの環境を再び整える

ぶっちゃけ、あまり家にいなかったので、MBPを連れ出すこともなく、いろいろゴニョゴニョするための機会がなかったのですが、つい先日出先にも持ち出しているWindows PCをThinkPad X230からX1 Yogaへリプレイスしました。

レノボ・ジャパン 20FR0033JP ThinkPad X1 Yoga

レノボ・ジャパン 20FR0033JP ThinkPad X1 Yoga

これを契機に、またゴニョゴニョするための環境構築を始めました。だいたい自分のゴニョゴニョはPythonが絡んでいるので、まずは、Python3.5.2をインストール。ただし、今回はいきなりAnacondaを入れることにします。

Download Anaconda Now! | Continuum

これで、Pythonのインストールも併せて完了。最近のインストローラはPATHの設定まで自動でやってくれるんですね。これの頃とは隔世の感です。

deutschina.hatenablog.com

こんな感じで起動。Windows10にはPowershellというのが新たに入ったのね。。。これも浦島太郎状態w

f:id:deutschina:20161228112001p:plain

あとは、Jupyter Notebookを使えるようにしようと。

Installing Jupyter Notebook — Jupyter Documentation 4.1.1 alpha documentation

これを見る限りは、Anacondaを入れれば、Jupyter notebookまで入ると思っていたのですが、なぜかコマンドから起動しないので、改めてpipからインストールしてみました。

$ pip install jupyter

あらためてコマンドから起動してみます。

$ jupyter notebook

f:id:deutschina:20161228112434p:plain

これで大丈夫そうですね。さて、これから何をやるかですが、視界の隅にこの本が・・・。年明けからの某所に持って行くかどうか検討中です。

中国語学習×グラフデータベース(13) - 細々気づいたこと

一通りデータは登録してみたので、細々したことをいくつか。

重複ノードの削除

データを登録する際に、いろいろ間違えてしまい不要なノードを削除したいなという時があった。通常のリレーショナルDB(以下RDB)では、テーブル定義の時にキーの重複を許さないように設定しておけば良いが、Neo4jを触った限りでは、単一項目での重複を許さないという設定は出来るものの、例えば単語(Word)のように、keywordとpinyinの組み合わせでの重複を許さないというような設定は出来ない(ように見える)。

今回の取り組みの中でも、自分の作ったコードの考慮が足りなかったために、同じ単語のノードが重複したときの削除に少しハマった。

で、どうしたらいいかをいろいろググると、StackoverflowではSKIPを使う方法が紹介されていたが、直感的にイマイチだと思ったので、ここに注目してみた。

f:id:deutschina:20160307151715p:plain

わかりにくいと思うが、どのNodeにもという属性が振られていた。これもCypherで拾えるだろと思っていたら、id()という表現を使えば良いらしいことが分かったので、こんなCypherクエリを実行してみた。

match (w1:Word {autoadd:True}), (w2:Word {autoadd:True}) where w1.keyword=w2.keyword and id(w1)<id(w2) return w2.keyword, id(w1), id(w2)

これは算数の問題だが、普通にやると単語の組み合わせが無数にある(5800の2乗で3000万通り以上)ため、処理に恐ろしく時間がかかるのだが、自分の場合、この手の重複はautoadd=Trueで登録した単語に限られることが分かっていたので、そこで絞り込むことができた。

2つの単語のidを比較して、単語(keyword)は同じだがidが異なる(どちらか一方を消せば良いので、<でさらに絞っている)を出力してくれと実行すると、消すべきidが4つほどに絞り込まれたので、今度はこんなcypherクエリを実行した。

match (w:Word)-[r:is_similar_to]-(w2:Word) where id(w) in [6458, 6461, 6469, 6497] delete w, r

Neo4jでは、Nodeの消去を行うには、Relationshipに紐付いていない事という条件があるため、Relationshipも同時に削除しなくてはならないので、こんな書き方をしている。実行結果は、こんな感じ。

Deleted 4 nodes, deleted 14 relationships, statement executed in 98 ms.

Node 4つに加えて、Relationshipが14個も削除されたことが分かる。上の2つは、Webインターフェイスから直接Cypherクエリを実行したが、もちろんgraph.cypher.execute()でpython側から実行しても結果は同じだ。

すべてが嫌になったときは

前も書いたが、これですべて消せる。

graph.delete_all()

消すなんてもったいないと思うかもしれないが、Jupyter Notebookでログを残しながらやっていれば、同じコードを再実行するのは簡単なので、結構あっさりと復元できるはずだ。

一通り、今回触ってきた内容については、ブログ上で整理したつもり。また何か進捗があれば、ここに書いていく予定。

(つづくかも)


グラフ型データベース入門 - Neo4jを使う

グラフ型データベース入門 - Neo4jを使う

グラフデータベース ―Neo4jによるグラフデータモデルとグラフデータベース入門

グラフデータベース ―Neo4jによるグラフデータモデルとグラフデータベース入門

A Programmatic Introduction to Neo4j

A Programmatic Introduction to Neo4j

中国語学習×グラフデータベース(12) - 類義語間のリンク

前回、登録されていないキーワードを拾い集めたので、それをいったん単語として登録するところから再会。

新しい単語の自動新規登録

今回は、ある種機械的に拾い集めたものなので、単語の詳細は後回しにしつつ、自動登録だよという意味で、autoaddという属性をつけて登録してみた。

for word in unknown_words:
    new_word = Node("Word", keyword=word, autoadd=True)
    graph.create(new_word)

もしautoadd=Trueという属性を持っていたら、その単語は自動的に登録されたものだよということが明確になるのが狙い。

類義語の組み合わせには方向性はない(はず)

続いて、類義語同士を:is_similar_toというrelationshipでつないでみるのだが、少なくとも今回使用した資料には、類義語間の方向性はない。例えば、Aから見てBは類義語だが、Bから見てAは類義語ではないというようなケースは考えない。Neo4jのRelationshipはすべて有方向性にする必要があるが、この場合は2つのアプローチがあると思う。

  • お互いに類義語として、両方向(つまり2本)のRelationshipを設定する。
  • 便宜上片方向となるが1本だけRelationshipを設定する。

今回は、後者のアプローチで行く事にした。理由はクエリを実行する際に方向は無視すれば良いだけで、わざわざ2本を引っ張るとグラフが煩雑になりそうだからという単純な理由。あとは、類語間どうしの「組み合わせ」を見つけて、その間でRelationshipを引けば良いはず。組み合わせを作るのは、itertools.combinationsでOK。

from itertools import combinations as cmb
for words in combinations:
    combination_set = list(cmb(words, 2))
    for element in combination_set:
        graph.cypher.execute("MATCH (w1:Word {{keyword:'{0}'}}), (w2:Word {{keyword:'{1}'}}) CREATE UNIQUE (w1)-[:is_similar_to]->(w2) RETURN w1, w2".format(element[0], element[1]))

comibinationsというリストを作った事を後悔したのはここ。itertools.combinationsの方はcmbという名称で呼び出すことにした。ロジックとしては、単語2つの組み合わせのリストをcombination_setというものを作り、その単語間で:is_similar_toというRelationshipを登録している。

ここまでの出来映え

これでRelationshipが登録されたので、Neo4j側で、こんなクエリを実行してみた。

MATCH (s:Sentence)-[:uses]->(w:Word)-[r:is_similar_to]->(w2:Word)<-[:uses]-(s2:Sentence) RETURN s, s2, w, w2, r

出てきたグラフはこんな感じ。
f:id:deutschina:20160225174522p:plain
緑色の単語同士がつながり、その外側に青色の例文がつながっている様子が分かる。良い感じ。

ということで、一通りの流れを追ってきたが、これまで取り上げられてなかった細々した話を次回で整理したい。

(つづく)

グラフ型データベース入門 - Neo4jを使う

グラフ型データベース入門 - Neo4jを使う

グラフデータベース ―Neo4jによるグラフデータモデルとグラフデータベース入門

グラフデータベース ―Neo4jによるグラフデータモデルとグラフデータベース入門

中国語学習×グラフデータベース(11) - 類語を結びつける

ひとまず、単語(キーワード)の一部と短文をつなげるところまで来たので、今回は類義語どうしをつないでみる。

ネタ元はこれ

CD付 どう違う?例文で覚える中国語類義語1000

CD付 どう違う?例文で覚える中国語類義語1000

  • 作者: 于鵬,平山邦彦,川田直樹
  • 出版社/メーカー: アスク出版
  • 発売日: 2010/04/28
  • メディア: 単行本(ソフトカバー)
  • クリック: 1回
  • この商品を含むブログを見る

正確には、これの中国語版(当時58元)。ただし、日本で手に入れるのであれば、2800円払って日本語版の方が良いと思う。例文のCDが付いているので、この方がお買い得なはず。日本語タイトルからは分かりづらいけど、中国語を学ぶ留学生が躓きそうな500組の単語の使い分けについて例文付きで解説している。ちなみに北京語言大学出版から、辞典形式で1700組取り上げた本もあるし、日本で出版されたこんな本もある。

中国語類義語辞典

中国語類義語辞典

今のところお試しの意味合いもあるので、500組程度で十分かなと思い、500組の単語をタブ区切りファイルで作ってみた。同じ行にある単語は類義語の組み合わせというイメージだ。カンマ区切りのCSVではなくタブ区切りになったのは、デフォルトでSHIFT-JISにしてしまうEXCELのせいだと声高に言っておくw。

タブ区切りファイルを読み込む

取り込み用のコードをPythonで書くとこんな感じになった。本当は500組一気に取り込むつもりだったが、とりあえず先頭の259組を取り込んでみた。

combinations = []
with open('aton_sample.csv', encoding='utf-8') as f:
    for row in f.readlines():
        newset = [word for word in row[:-1].split('\t') if word]
        combinations.append(newset)
print(len(combinations))
259

今考えると、combinationsというListの名称は別の名前にするべきだったかなと思うが、Python的なポイントはそこではなく、for文の次にあるnewsetをリスト内包表記で取得している部分になる。

row[:-1]は行末の改行コードを取り除き、split('\t')は、行データをタブで分割している。ただし、行によって含まれる単語数が違う関係で、空っぽのデータが取得された場合はそれを無視してListを作るというイメージだ。そのListをさらにcombinationsというListにappend()しているという流れだ。

Keywordはすでに存在しているかのチェック

単語については、HSKの綱領に載っているもの、類義語の組み合わせについては別の本から持ってきているので、当然のことながら単語として登録されていない類義語が登場してくる可能性があるので、念のためチェックしてみた。

unknown_words = []
known_words = []
for wordset in combinations:
    ws = graph.cypher.execute("MATCH (w:Word) WHERE w.keyword in {0} RETURN w.keyword".format(str(wordset)))
    found_words = []
    for record in ws:
        found_words.append(record['w.keyword'])
        known_words.append(record['w.keyword'])
    for word in wordset:
        if word not in found_words:
            unknown_words.append(word)
known_words = set(known_words)   # To be a SET
unknown_words = set(unknown_words) # To be a SET
print("Found {0} known words".format(len(known_words)))
print("Found {0} unknown words".format(len(unknown_words)))||<
>||
Found 521 known words
Found 89 unknown words

これは、1回失敗したのを踏まえてロジックを調整したものになる。具体的には、今回登録した類義語の組み合わせの中に、単語として登録されていないキーワードが複数回登場した場合を考慮するために、生成されたunknown_wordsの中身をsetとして読み込み直して重複を排除している。後で取り上げるつもりだが、誤って重複して登録してしまった場合のNodeの削除が結構面倒くさい。

次回は、未登録単語の登録から類義語間のRelationshipを設定するところまで行こうと思う。


(つづく)

最初の本は、Cypherのリファレンス的にも使えたりして、日本語では一番充実していると思ってる。

グラフ型データベース入門 - Neo4jを使う

グラフ型データベース入門 - Neo4jを使う

グラフデータベース ―Neo4jによるグラフデータモデルとグラフデータベース入門

グラフデータベース ―Neo4jによるグラフデータモデルとグラフデータベース入門

A Programmatic Introduction to Neo4j

A Programmatic Introduction to Neo4j