如何使用jieba 結巴中文分詞程式 - I am Fukuball
文章推薦指數: 80 %
jieba 中文斷詞所使用的演算法是基於Trie Tree 結構去生成句子中中文字所有可能成詞的情況,然後使用動態規劃(Dynamic programming)算法來找出最大機率 ...
Fukuball
我是林志傑,網路上常用的名字是Fukuball。
我使用PHP及Python,對機器學習及區塊鏈技術感到興趣。
https://www.fukuball.com
About
Home
Facebook
GitHub
Blog
如何使用jieba結巴中文分詞程式
August6,2014
前言
自然語言處理的其中一個重要環節就是中文斷詞的處理,比起英文斷詞,中文斷詞在先天上就比較難處理,比如電腦要怎麼知道「全台大停電」要斷詞成「全台/大/停電」呢?如果是英文「PoweroutagealloverTaiwan」,就可以直接用空白斷成「Power/outage/all/over/Taiwan」,可見中文斷詞真的是一個大問題啊~
這樣的問題其實已經有很多解法,比如中研院也有提供「中文斷詞系統」,但就是很難用,不僅APICall的次數有限制,還很難串,Server也常常掛掉,真不曉得為何中研院不將核心開源出來,讓大家可以一起來改善這種現象,總之我要棄中研院的斷詞系統而去了。
近來玩了一下jieba結巴這個PythonBased的開源中文斷詞程式,感覺大好,順手發了一些pullrequest,今天早上就成為contributor了!感覺真爽!每次發pullrequest總是有種莫名的爽感,既期待被merge又怕被reject,就跟告白的感覺類似啊~
這麼好用的開源中文斷詞系統,當然要介紹給大家用啊!
背後演算法
jieba中文斷詞所使用的演算法是基於TrieTree結構去生成句子中中文字所有可能成詞的情況,然後使用動態規劃(Dynamicprogramming)算法來找出最大機率的路徑,這個路徑就是基於詞頻的最大斷詞結果。
對於辨識新詞(字典詞庫中不存在的詞)則使用了HMM模型(HiddenMarkovModel)及Viterbi算法來辨識出來。
基本上這樣就可以完成具有斷詞功能的程式了,或許我之後可以找個時間寫幾篇部落格來介紹這幾個演算法。
如何安裝
推薦用pip安裝jieba套件,或者使用Virtualenv安裝(未來可能會介紹如何使用Virtualevn,這樣就可以同時在一台機器上跑不同的Python環境):
pipinstalljieba
基本斷詞用法,使用預設詞庫
SampleCode:
jieba-default-mode.py
#encoding=utf-8
importjieba
sentence="獨立音樂需要大家一起來推廣,歡迎加入我們的行列!"
print"Input:",sentence
words=jieba.cut(sentence,cut_all=False)
print"Output精確模式FullMode:"
forwordinwords:
printword
sentence="独立音乐需要大家一起来推广,欢迎加入我们的行列!"
print"Input:",sentence
words=jieba.cut(sentence,cut_all=False)
print"Output精確模式FullMode:"
forwordinwords:
printword
得到的斷詞結果會是:
獨立/音樂/需要/大家/一起/來/推廣/,/歡迎/加入/我們/的/行列
独立/音乐/需要/大家/一/起来/推广/,/欢迎/加入/我们/的/行列
據原作者的說法,使用預設詞庫的話,繁體中文的斷詞結果應該會比較差,畢竟原來的詞庫是簡體中文,但在這個例子中,我感覺是繁體中文的斷詞結果比較好,這應該只是特例,我們接下來試試看中文歌詞的斷詞結果如何。
中文歌詞斷詞,使用預設詞庫
現在我們使用回聲樂團-座右銘的歌詞作為中文斷詞測試範例,歌詞我們先做成一個純文字檔,內容如下:
lyric.txt
我沒有心
我沒有真實的自我
我只有消瘦的臉孔
所謂軟弱
所謂的順從一向是我
的座右銘
而我
沒有那海洋的寬闊
我只要熱情的撫摸
所謂空洞
所謂不安全感是我
的墓誌銘
而你
是否和我一般怯懦
是否和我一般矯作
和我一般囉唆
而你
是否和我一般退縮
是否和我一般肌迫
一般地困惑
我沒有力
我沒有滿腔的熱火
我只有滿肚的如果
所謂勇氣
所謂的認同感是我
隨便說說
而你
是否和我一般怯懦
是否和我一般矯作
是否對你來說
只是一場遊戲
雖然沒有把握
而你
是否和我一般退縮
是否和我一般肌迫
是否對你來說
只是逼不得已
雖然沒有藉口
SampleCode:
jieba_cut_lyric.py
#encoding=utf-8
importjieba
content=open('lyric.txt','rb').read()
print"Input:",content
words=jieba.cut(content,cut_all=False)
print"Output精確模式FullMode:"
forwordinwords:
printword
得到的斷詞結果會是:
我/沒/有心/我/沒/有/真實/的/自我/我/只有/消瘦/的/臉孔/所謂/軟弱/所謂/的/順/從/一向/是/我/的/座/右銘/而/我/沒有/那/海洋/的/寬闊/我/只要/熱情/的/撫/摸/所謂/空洞//所謂/不安全感/是/我/的/墓誌/銘/而/你/是否/和/我/一般/怯懦/是否/和/我/一般/矯作/和/我/一般/囉/唆/而/你/是否/和/我/一般/退縮/是否/和/我/一般/肌迫/一般/地/困惑/我/沒/有力/我/沒/有/滿腔/的/熱火/我/只有/滿肚/的/如果/所謂/勇氣/所謂/的/認/同感/是/我/隨便/說/說/而/你/是否/和/我/一般/怯懦/是否/和/我/一般/矯作/是否/對/你/來/說/只是/一場/遊戲/雖然/沒/有把握/而/你/是否/和/我/一般/退縮/是否/和/我/一般/肌迫/是否/對/你/來/說/只是/逼不得已/雖然/沒有/藉口
我們可以從結果看出斷詞已經開始出了一些問題,比如「座右銘」被斷成了「座/右銘」,「墓誌銘」被斷成了「墓誌/銘」,這應該就是因為預設詞庫是簡體中文所造成,因此繁體中文的斷詞結果會比較差,還好jieba也提供了可以切換詞庫的功能,並提供了一個繁體中文詞庫,所以我們可以使用切換詞庫的功能來改善斷詞結果。
中文歌詞斷詞,使用繁體詞庫
SampleCode:
jieba_cut_lyric_zh.py
#encoding=utf-8
importjieba
jieba.set_dictionary('dict.txt.big')
content=open('lyric.txt','rb').read()
print"Input:",content
words=jieba.cut(content,cut_all=False)
print"Output精確模式FullMode:"
forwordinwords:
printword
我們在程式中多加一行jieba.set_dictionary(‘dict.txt.big’),這樣就可以將斷詞詞庫切換到dic.txt.big這個檔案。
得到的斷詞結果會是:
我/沒有/心/我/沒有/真實/的/自我/我/只有/消瘦/的/臉孔/所謂/軟弱/所謂/的/順從/一向/是/我/的/座右銘/而/我/沒有/那/海洋/的/寬闊/我/只要/熱情/的/撫摸/所謂/空洞/所謂/不安全感/是/我/的/墓誌銘/而/你/是否/和/我/一般/怯懦/是否/和/我/一般/矯作/和/我/一般/囉唆/而/你/是否/和/我/一般/退縮/是否/和/我/一般/肌迫/一般/地/困惑/我/沒有/力/我/沒有/滿腔/的/熱火/我/只有/滿肚/的/如果/所謂/勇氣/所謂/的/認同感/是/我/隨便說說/而/你/是否/和/我/一般/怯懦/是否/和/我/一般/矯作/是否/對/你/來說/只是/一場/遊戲/雖然/沒有/把握/而/你/是否/和/我/一般/退縮/是否/和/我/一般/肌迫/是否/對/你/來說/只是/逼不得已/雖然/沒有/藉口
我們可以看到「座右銘」成功斷成「座右銘」了!「墓誌銘」也成功斷成「墓誌銘」了!果然切換成繁體中文詞庫還是有用的!
台語歌詞斷詞,使用繁體詞庫
既然中文歌詞斷詞能夠得到不錯的斷詞結果了,那我們來試試看台語歌詞斷詞會是如何?在這邊我們使用滅火器-島嶼天光的歌詞作為台語斷詞測試範例,歌詞我們先做成一個純文字檔,內容如下:
lyric_tw.txt
親愛的媽媽
請你毋通煩惱我
原諒我
行袂開跤
我欲去對抗袂當原諒的人
歹勢啦
愛人啊
袂當陪你去看電影
原諒我
行袂開跤
我欲去對抗欺負咱的人
天色漸漸光
遮有一陣人
為了守護咱的夢
成做更加勇敢的人
天色漸漸光
已經不再驚惶
現在就是彼一工
換阮做守護恁的人
已經袂記
是第幾工
請毋通煩惱我
因為阮知道
無行過寒冬
袂有花開的一工
天色漸漸光
天色漸漸光
已經是更加勇敢的人
天色漸漸光
咱就大聲來唱著歌
一直到希望的光線
照光島嶼每一個人
天色漸漸光
咱就大聲來唱著歌
日頭一爬上山
就會使轉去啦
現在是彼一工
勇敢的台灣人
SampleCode:
jieba_cut_lyric_zh_tw.py
#encoding=utf-8
importjieba
jieba.set_dictionary('dict.txt.big')
content=open('lyric_tw.txt','rb').read()
print"Input:",content
words=jieba.cut(content,cut_all=False)
print"Output精確模式FullMode:"
forwordinwords:
printword
得到的斷詞結果會是:
親愛/的/媽媽/請/你/毋通/煩惱/我/原諒/我/行袂/開跤/我/欲/去/對抗/袂/當/原諒/的/人/歹勢/啦/愛人/啊/袂/當/陪你去/看/電影/原諒/我/行袂/開跤/我/欲/去/對抗/欺負/咱/的/人/天色/漸漸/光/遮有/一陣/人/為/了/守護/咱/的/夢/成/做/更加/勇敢的人/天色/漸漸/光/已經/不再/驚惶/現在/就是/彼一工/換阮/做/守護/恁/的/人/已經/袂/記/是/第幾/工/請/毋通/煩惱/我/因為/阮/知道/無行過/寒冬/袂/有/花開/的/一工/天色/漸漸/光/天色/漸漸/光/已經/是/更加/勇敢的人/天色/漸漸/光/咱/就/大聲/來/唱/著歌/一直/到/希望/的/光線/照光/島嶼/每/一個/人/天色/漸漸/光/咱/就/大聲/來/唱/著歌/日頭/一爬/上山/就/會/使/轉去/啦/現在/是/彼/一工/勇敢/的/台灣/人
原本猜想結果應該會蠻差的,畢竟詞庫中沒有台語的用詞,但是因為HMM的關係猜出了一些新詞,讓我們還是得到不錯的結果,「袂當」斷成了「袂」「當」,「袂記」斷成了「袂」「記」,「袂有」斷成了「袂」「有」等等,我們要如何改善這些結果呢?
jieba提供了一個功能讓使用者可以增加自定義詞庫,這種無法用HMM判斷出來的新詞就可以得到改善,我們就來試試看吧!
台語歌詞斷詞,使用繁體詞庫加自定義詞庫
首先我們新增一個純文字檔建立自定義詞庫,格式如下:
userdict.txt
行袂開跤2v
袂當4d
袂記4v
袂有4d
唱著4v
每一個4m
會使70d
其中每一行代表一筆語料資料,首先填上自定義詞如:「袂當」、「袂記」,然後填上權重,權重值可以依照斷詞結果做自己想做的調整,最後填上詞性,但詞性非必要填寫,詞性列表可以參考词性对照说明.中科院版本。
SampleCode:
jieba_cut_lyric_zh_tw_custom.py
#encoding=utf-8
importjieba
jieba.set_dictionary('dict.txt.big')
jieba.load_userdict("userdict.txt")
content=open('lyric_tw.txt','rb').read()
print"Input:",content
words=jieba.cut(content,cut_all=False)
print"Output精確模式FullMode:"
forwordinwords:
printword
我們在程式中多加一行jieba.load_userdict(“userdict.txt”),這樣就可以將自定義詞庫加進來了,超級簡單的。
得到的斷詞結果會是:
親愛/的/媽媽/請/你/毋通/煩惱/我/原諒/我/行袂開跤/我/欲/去/對抗/袂當/原諒/的/人/歹勢/啦/愛人/啊/袂當/陪你去/看/電影/原諒/我/行袂開跤/我/欲/去/對抗/欺負/咱/的/人/天色/漸漸/光/遮有/一陣/人/為/了/守護/咱/的/夢/成/做/更加/勇敢的人/天色/漸漸/光/已經/不再/驚惶/現在/就是/彼一工/換阮/做/守護/恁/的/人/已經/袂記/是/第幾/工/請/毋通/煩惱/我/因為/阮/知道/無行過/寒冬/袂有/花開/的/一工/天色/漸漸/光/天色/漸漸/光/已經/是/更加/勇敢的人/天色/漸漸/光/咱/就/大聲/來/唱著/歌/一直/到/希望/的/光線/照光/島嶼/每/一個/人/天色/漸漸/光/咱/就/大聲/來/唱著/歌/日頭/一爬/上山/就/會使/轉去/啦/現在/是/彼/一工/勇敢/的/台灣/人
完美!
取出斷詞詞性
大部份的斷詞系統都可以列出斷詞的詞性,jieba也有這個功能,但結果可能不是那麼好,這其實是跟所使用的語料庫有關係,不過既然是OpenSource,希望未來能有語言學家可以加入,讓jieba可以得到更好的效果。
SampleCode:
jieba_cut_lyric_zh_flag.py
#encoding=utf-8
importjieba
importjieba.possegaspseg
jieba.set_dictionary('dict.txt.big')
content=open('lyric.txt','rb').read()
print"Input:",content
words=pseg.cut(content)
print"Output精確模式FullMode:"
forwordinwords:
printword.word,word.flag
得到的結果會是:
我r
沒有x
心n
我r
沒有x
真實x
的uj
自我r
...
取出斷詞位置
有時我們會需要得到斷詞在文章中的位置:
SampleCode:
jieba_cut_lyric_zh_tokenize.py
#encoding=utf-8
importjieba
jieba.set_dictionary('dict.txt.big')
content=open('lyric.txt','rb').read()
print"Input:",content
words=jieba.tokenize(unicode(content,'utf-8'))
print"Output精確模式FullMode:"
fortkinwords:
print"word%s\t\tstart:%d\t\tend:%d"%(tk[0],tk[1],tk[2])
得到的結果會是:
word我start:0end:1
word沒有start:1end:3
word心start:3end:4
wordstart:4end:5
word我start:5end:6
word沒有start:6end:8
word真實start:8end:10
word的start:10end:11
word自我start:11end:13
...
取出文章中的關鍵詞
jieba使用了tf-idf方法來實作萃取出文章中關鍵詞的功能:
SampleCode:
jieba_cut_lyric_zh_keyword.py
#encoding=utf-8
importjieba
importjieba.analyse
jieba.set_dictionary('dict.txt.big')
content=open('lyric.txt','rb').read()
print"Input:",content
tags=jieba.analyse.extract_tags(content,10)
print"Output:"
print",".join(tags)
程式中的jieba.analyse.extract_tags(content,10),就是告訴jieba我們要從這個文章中取出前10個tf-idf值最大的關鍵詞。
得到的結果會是:
沒有,所謂,是否,一般,雖然,退縮,肌迫,矯作,來說,怯懦
一開始使用這個功能的時候,會不知道jieba的idf值是從哪裡來的,看了一下soucecode才知道原來jieba有提供一個idf的語料庫,但在實務上每個人所使用的語料庫可能會不太一樣,有時我們會想要使用自己的idf語料庫,stopwords的語料庫也可能會想換成自己的,比如目前的結果中,最重要的「座右銘」並沒有出現在關鍵詞裡,我就會想要將「座右銘」加到idf語料庫,並讓idf值高一點,而「沒有」這個關鍵詞對我來說是沒有用的,我就會想把它加到stopwords語料庫,這樣「沒有」就不會出現在關鍵詞裡。
可惜目前pip安裝的jieba版本並不能切換idf及stopwords語料庫,所以我才會修改了一下jieba,讓它可以支援idf及stopwords語料庫的切換,目前在github上的版本已經可以支援idf及stopwords切換的功能了!
結語
使用了jieba之後,其實有蠻深的感嘆,其實中研院的斷詞核心必非不好,想要收費也不是問題,但是API做得這麼差,根本就沒人有信心敢花錢下去使用這樣不可靠的系統,目前又有jieba這樣的opensourceproject,中研院的斷詞系統前途堪慮啊!
後記2017/07/18
我後來有好幾次受邀演講關於中文斷詞的講題,相關的投影片都有分享在網路上了,大家也可以交叉參考:中文斷詞:斷句不要悲劇/HeadfirstChinesetextsegmentation投影片、範例程式碼。
jieba
machinelearning
naturelanguageprocessing
Fukuball
我是林志傑,網路上常用的名字是Fukuball。
我使用PHP及Python,對機器學習及區塊鏈技術感到興趣。
https://www.fukuball.com
Co-Founder/HeadofEngineeringatOurSong
Taipei,Taiwan
by
Ethereum開發筆記2–3:SmartContract初探,從Bytecode到Solidity
Sep9,2018
Ethereum上的EVM(EthereumVirtualMachine)可以執行程式,而EVM上的可執行程式基本上是Bytecode的形式,所以所謂的SmartContract就是存放在Ethereum上的Bytecode,然後可由EVM來執行。
BytecodeSmartContract直接用Bytecode寫SmartContract我們來嘗試一下直接用Bytecode來寫SmartContract,以下這段程式碼主要內容是執行運算後,將運算結果存放在0這個位置:
PUSH10x03PUSH10x05ADD//3+5->8PUSH10x02MUL//8*2->16PUSH10x00SSTORE//將16存到0這個位置這段程式轉成Bytecode就是:
0x600x030x600x050x010x600x020x020x600x000x55也就是:
Ethereum開發筆記2–2:Geth基礎用法及架設Muti-Nodes私有鏈
Sep9,2018
要連上Ethereum就需要安裝EthereumNode,在這邊我們選擇使用Geth來安裝EthereumNode,接下來就來一步一步的學學怎麼使用Geth,甚至如何使用Geth來架設自己的Ethereum私有鏈。
安裝環境首先我們在AWS上開啟兩台Ubuntu虛擬機器,記得開t2.medium(2vCPU,4GBRAM)這個規格以上才跑得動,硬碟可以開100G,SecurityGroup將TCP30303打開,EthereumNode之間是用30303這個port來溝通的。
接下來使用以下指令安裝Geth:
$sudoapt-getinstall-ysoftware-properties-common$sudoadd-apt-repository-yppa:ethereum/ethereum$sudoapt-getupdate$sudoapt-getinstall-yethereum兩台虛擬機器都要安裝,應該幾分鐘就可以裝好了。
使用MainNet安裝完Geth之後,我們就可以透過Geth連上EthereumNetwork了,我們就來連上MainNet看看:
Ethereum開發筆記2–1:Ethereum開發整體脈絡
Sep9,2018
在第一次接觸Ethereum應用程式開發時,會發現有各式各樣工具,不知要從何下手,我們用一個圖來說明一下與Ethereum互動時的整體脈絡及這之間的工具主要做了什麼事,了解之後自己就可以挑選開發時、甚至使用在產品上時要用什麼適合的工具了。
要在自己的機器接上Ethereum首先需要安裝EthereumNode,我們之前安裝的Mist其實就會在我們的機器上安裝EthereumNode並同步帳本,而像這樣安裝Node並同步帳本甚至進行挖礦的軟體有很多,大家可以去選擇適合自己使用的。
Mist其實是將一個叫geth的軟體用GUI包裝起來,如果是開發者的話,可以選擇直接安裝geth。
geth提供了許多API指令可以讓我們跟Ethereum做互動,但有時下指令並不是那麼親和,所以geth提供了RPC(RemoteProcedureCalls)與IPC(Inter-processCommunications)兩種方式來與geth互動,如果你要在local機器連上geth,那就可以使用IPC;如果要讓遠端連上geth,那就使用RPC,可以開HTTP或WebSocket兩種方式來讓遠端使用。
以上就是Ethereum應用程式開發的基礎環境,接下來跟開發網頁應用程式一樣,Ethereum應用程式也分成後端與前端,後端程式就是SmartContract,前端程式就是Dapp。
SmartContract可使用Solidity撰寫,目前也有許多其他語言可以撰寫SmartContract。
SmartContract要在Ethereum上的EVM執行要先Compile成ByteCode之後,再透過IPC或RPC發佈到Ethereum上。
前端程式的Dapp可用Web3JavaScript透過RPC接上Ethereum,以及使用網頁應用常用到的HTML、CSS、JavaScript製作成使用者互動介面,如此就能執行發佈在Ethereum上SmartContract所提供的一些程式功能了。
Ethereum開發筆記1–8:Ethereum的獎勵機制
Sep9,2018
Bitcoin的獎勵機制基本上是挖到新區塊的節點獲得記帳權及獎勵,Ethereum大體也是遵循這樣的概念,但做了一些調整與變化,讓我們整個脈絡了解一下。
由於Blockchain是一種去中心化的系統,所有的礦工(節點)可以同時挖礦(計算合法hash),彼此獨立運作,所以極有可能出現兩的礦工同時發現不同的滿足條件的區塊,如此就會產生我們之前有提過的分叉(Fork)。
那我們該採用誰的區塊當主鏈呢?我們會先依工作量最大的區塊為主鏈,如果工作量一樣,就看誰先接了子區塊,一般來說只有成了主鏈的區塊才能獲得獎勵。
但這樣沒有變成主鏈的區塊之前的算力就都白費了,所以Ethereum創造了UncleBlock(叔塊)這樣的概念,不能成為主鏈的區塊如果後來被收留成為UncleBlock,那這些沒有成為主鏈的區塊也有機會可以做為UncleBlock而獲得獎勵。
這就是Ethereum共識機制中的GHOST(GreedyHeaviestObservedSubtree)協議,Ethereum會這樣設計的原因,是由於Ethereum產生區塊的速度較快,也因此較容易產生分叉,也會使得新區塊較難以在整個網絡傳播,這對於傳播速度較慢的區塊並不公平。
且分叉後的區塊可能在幾個區塊之後整併起來,我們會發現裡面的交易可能會與主鏈一致(雖然單獨查看分塊交易內容不同,不過數個區塊整體一起看交易內容就一致了),符合這種條件的分叉區塊我們就會納入主鏈參考,這些區塊就成了所謂的UncleBlock,這某種角度也是更確認了Blockchain上的交易內容一致,因此UncleBlock也有貢獻,應該給予獎勵。
以上我們已經了解了Ethereum上的區塊大致分成兩種,普通區塊和UncleBlock,Ethereum對這兩種區塊的獎勵方式是不同的。
我們分別來看一下。
普通區塊獎勵固定獎勵5ETH區塊內所有的GasFee如果區塊納入了UncleBlock,那每包含一個UncleBlock可以得到固定獎勵5ETH*1/32,也就是0.15625ETH,一個區塊最多隻能包含2個UncleBlock,也因此不會無限延伸,同時又可鼓勵區塊納入UncleBlock,增加交易內容的一致性。
UncleBlock獎勵用公式計算:(UncleBlock高度+8-包含此UncleBlock的區塊的高度)*普通區塊固定獎勵/8我們用個實例來看一下獎勵怎麼算。
首先我們來看一個普通區塊:https://etherscan.
Ethereum開發筆記1–7:Blockchain的一些重要性質
Sep9,2018
我們這邊再次總結一下Blockchain中幾點較重要的性質,包含共識機制、不可竄改、經濟激勵三項。
共識機制(Consensus)在分散式系統中,我們需要有一套用於協同合作的共識機制來組織行動,但有時候系統中的成員可能會出錯或是故意傳送出錯誤的資訊,而使得網路中不同成員對於全體協作的策略得出不同的結論,進而破壞系統的一致性,這就是所謂的拜占庭將軍問題。
拜占庭將軍問題(ByzantineGeneralsProblem)拜占庭將軍問題這個故事是這樣的:
一組拜占庭將軍分別各率領一支軍隊共同圍困一座城市,這個敵人雖不比拜占庭帝國,但也足以抵禦5支拜占庭軍隊的同時襲擊。
這10支軍隊在分開的包圍狀態下,他們任1支軍隊單獨進攻都毫無勝算,除非有至少6支軍隊(一半以上)同時襲擊才能攻下敵國。
他們分散在敵國的四周,依靠通信兵騎馬相互通信來協商進攻意向及進攻時間。
困擾這些將軍的問題是,他們不確定他們中是否有叛徒,叛徒可能擅自變更進攻意向或者進攻時間。
在這種狀態下,拜占庭將軍們才能保證有多於6支軍隊在同一時間一起發起進攻,從而贏取戰鬥?
上述的故事對映到電腦系統裡,將軍便成了電腦,而通信兵就是通訊系統。
叛徒發送前後不一致的進攻提議,被稱為「拜占庭錯誤」,而能夠處理拜占庭錯誤的這種容錯性稱為「ByzantineFaultTolerance」。
Blockchain上的共識機制通常具有容錯的設計來達成一致性,主要比較常見的共識機制方法有兩個,「工作量證明」以及「股權證明」兩種方法。
工作量證明演算法(ProofofWork,PoW)中本聰在Bitcoin中創造性的引入了「工作量證明」(俗稱挖礦)來解決拜占庭將軍問題,顧名思義,工作量證明就是用來證明你做了一定量的工作,可用工作成果來證明完成相應的工作量。
其中的工作技術原理可以看之前這篇文章:Ethereum開發筆記1–4:Blockchain技術原理簡介
由於工作量證明具相當高的計算成本,因此無誘因去偽造,只有遵守協議約定,才能夠回收成本並獲得收益,也因此減少了叛徒的產生,減少拜占庭錯誤。
股權證明演算法(ProofofStake,PoS)股權證明的出現,主要是希望取代工作量證明,進而減少「挖礦」的大量運算。
它與工作量證明不同地方在於:工作量證明中,大家比的是「算力」(運算能力),透過大量運算得出符合難度的Hash值,進而得到獎勵;而在股權證明,大家比拼的是「股權」,「股權」越大的人(節點)越大機會負責產生新區塊,進而得到獎勵。
舉例來說,在股權證明系統中所有擁有股權(此Blockchain的數位貨幣)的人都有機會被挑選為產生新區塊(也就是記帳)的人,擁有更多股權的人被選中的機率越大。
假這這個系統中共有三個人:Alice持有50股、Bob持有30股、Cathy持有20股,那每次Alice被選為記帳人的機率會是Cathy的兩倍。
所以股權證明會驅使人們購買更多的股權,進而增加獲選為記帳人的機率,以買股權來代替挖礦,同樣需要付出高成本,也因此可以減少叛徒的產生,減少拜占庭錯誤。
不可竄改(Immutability)Blockchain不可竄改的性質主要來自資料結構及hash方式的設計,讓資料的順序緊密鏈結,若從中竄改了某些資料,那之後的鏈結hash都會發生錯誤,形成了Blockchain不可竄改的特性。
Ethereum開發筆記1–6:Blockchain相關的加密基礎知識
Sep9,2018
Blockchain裡應用了一些加密技術來保證及驗證交易訊息的正確性,這也更加強了Blockchain資料不可竄改的特性。
我們來介紹其中比較重要的「公私鑰加密」以及「MerkleTree」加密樹。
公私鑰加密公私鑰加密算法是目前資訊通訊安全的基石,它保證了加密訊息不可被破解,相關的加解密原理大家可以參考這兩篇文章:
RSA算法原理(一)http://www.ruanyifeng.com/blog/2013/06/rsa_algorithm_part_one.htmlRSA算法原理(二)http://www.ruanyifeng.com/blog/2013/07/rsa_algorithm_part_two.html加密與解密公私鑰加密方法是一種非對稱式加密,透過公鑰加密過後的訊息只有私鑰可以解密,也因此只要保護好私鑰就能保證資訊的安全。
現在假設Alice要傳一個訊息給Bob,希望訊息加密過後只有Bob可以解密,大概會經過如下步驟:
Bob傳他的公鑰給AliceAlice使用Bob的公鑰加密訊息Alice將加密過後的訊息傳給BobBob用他的私鑰解密訊息我們這邊使用openssl來練習一下加密與解密,首先我們來產生一對公私鑰:
//CreateRSAprivatekey$opensslgenrsa-des3-outrsa-key.pem2048//Createpublickey$opensslrsa-inrsa-key.pem-outformPEM-pubout-outrsa-key-pub.pem其中rsa-key.pem就是私鑰,rsa-key-pub.pem為公鑰,私鑰會要求設置密碼,請妥善記下密碼。
我們先用rsa-key-pub.pem加密資料:
Ethereum開發筆記1–5:Blockchain的一些定義與名詞
Sep9,2018
在Ethereum開發筆記1–4應該已經將Blockchain的技術原理說明得很清楚了,不過如果要向一般大眾簡單說明Blockchain是什麼,要怎麼說呢?我會說:Blockchain就是一個分散式帳本,大家都有一樣的帳本,大家都可一起參與記帳,且記完帳大家的帳本就會自動更新到最新版本,而帳裡的紀錄都會分塊並用密碼按順序鏈結起來,用以驗證帳的正確性,如果中間有人改了資料,那後面的鏈結密碼都會發生錯誤,因此沒有人可以亂改帳,這就是Blockchain。
但Blockchain這個名詞還包含了許多概念與內涵,我們之前說過,Blockchain是因為分散式去中心化帳本的發展而慢慢產生出來的,這樣慢慢被統稱出來的名詞裡底下也就會包含了許多內涵,很難用三言兩語來說明,所以有一些Blockchain相關的定義與名詞我們都可以了解一下,這樣就能更了解Blockchain。
交易(Transaction)交易是Blockchain帳本中的原子單位,如果將交易再往下拆分就會變得沒有意義,比如下列就是一個交易:
A減少了$10B增加了$9C增加了$1如果只看1,我們就會想那減少的$10到哪裡去了?所以1、2、3一起看才算是一個交易。
Blockchain是一個分散式帳本(DistributedLedger)不像銀行依靠自己的帳本來記帳,Blockchain提供了可靠的分散式帳本,當銀行之間要進行交易時,會需要一個受信任的第三方來進行銀行之間的交易,這也是為何你在做跨國轉帳時,需要付出高昂的手續費以及等待數天處理交易,Blockchain可靠的分散式帳本讓跨國交易可以在幾分鐘甚至幾秒之內完成,這也是為何銀行想要應用Blockchain在金融交易上以降低交易成本。
Blockchain是一個資料結構(DataStructure)通常Blockchain的資料結構如下組成:
交易是原子單位區塊是由一系列的交易組成區塊鏈由排序良好的區塊所組成Blockchain會有分叉(Fork)當有兩名礦工A及B幾乎在相同時間內算出了合法的hash,這兩個區塊傳播到鄰近節點時,有些節點收到了A的區塊,有些節點收到了B的區塊,這兩個區塊都可以是主鏈的延伸,這時就會產生區塊鏈分叉。
Ethereum開發筆記1–4:Blockchain技術原理簡介
Sep9,2018
之前我們簡單地介紹過Blockchain了,但我們還是對Blockchain背後的技術原理不是那麼了解,我們知道Blockchain是因為一個數位貨幣帳本這樣的概念被創造出來的,而數位貨幣最擔心的是什麼問題呢?其實就是雙重支付(Double-Spending)這樣的問題。
數位貨幣不像實體貨幣,數位資產比起實體資產容易複製,也因此如果花用數位貨幣的行為如果沒有處理好,就會產生憑空多出其他交易,這就像是偽鈔一樣,會造成通貨膨脹而導致貨幣貶值,讓人不再信任並願意持與流通。
因此數位貨幣的支付通常需要一個受信任的第三方來做驗證,這樣的做法雖然簡單,卻存在單點脆弱性,只要這第三方受到攻擊或是監守自盜也一樣會讓這個數位貨幣變成一個失敗的貨幣。
分散式去中心化帳本能解決單點脆弱性的問題,但在驗證正確性這點難度卻很高,所有的節點都有記帳的權利,要如何確定由誰來記帳、記的帳對不對?如果無法確定帳是對的,那就存在雙重支付的風險。
為了改善單點脆弱性及雙重支付這樣的問題,許多分散式的雙重支付防範方法慢慢被提出來,中本聰提出了去中心化(以受信任第三方為中心)的方法來展示解決雙重支付問題,並實作出了Bitcoin,使用共識機制來解決記帳及驗證的問題,這帶來去中心化數位貨幣帳本的成功。
Bitcoin的共識協議主要由「工作量證明」(Proof-of-Work,PoW)和「最長鏈機制」兩部分組成,Bitcoin上的各個節點就是透過共識機制中的工作量證明來決定誰有記帳權,然後取得記帳權的節點就能將新的區塊記帳加到最長鏈上並給予該節點獎勵(新區塊獎勵及交易費收益)。
Bitcoin的工作量證明大概會做以下的事情:
收集還未記到帳上的交易檢查每個交易中付款地址有沒有足夠的餘額驗證交易是否有正確的簽名把驗證通過的交易信息進行打包(組成MerkleTree)為自己增加一個交易紀錄獲得Bitcoin獎勵金計算合法的hash爭奪記帳權計算合法hash的方式請見下方影片說明,個人覺得這個影片是目前將Blockchain加密機制說明得最清楚的影片。
我這邊簡略說明一下,合法的hash公式大致看起來像這樣:hash(交易內容+交易簽名+nonce+上一個區塊的hash),我們要取得記帳權,就需要找出前面開頭有N個0的hash,由於交易內容、交易簽名及上一個區塊的hash都是不可變的,所以每個節點就是不斷的調整nonce來計算得出不同的hash,直到找到開頭N個0的hash為止,第一個找的節點就能獲得記帳權,而其他的節點只要計算hash對不對就能驗證這個帳對不對。
其中N個0開頭的hash就代表了計算的難度,越多0代表越難找到這樣的hash,也因此可以調整計算難度。
就是這樣的設計解決了去中心化分散式系統驗證資料及決定記帳順序的難題,也就改善了數位貨幣單點脆弱性及雙重支付的問題。
以上的內容看完應該就能大體了解Blockchain的原理了,甚至要自己做一個Blockchain都沒問題!了解了Blockchain的技術原理之後,應該能更信任去中心化的數位貨幣的安全性,或許有天大家都信任了去中心化的數位貨幣我們就真的能廣泛使用數位貨幣,為經濟活動帶來更有效率的流通。
Ethereum開發筆記練習1:使用Mist發行自己的Token
Sep9,2018
之前說過,Blockchain基本上是因為金流帳本這樣的問題而被創造出來的,也就是說區塊鏈非常適合運用在金流的應用上,我們也可以建立自己的Blockchain來搭建自己的金流系統,不過在Ethereum上SmartContract這種設計讓我們擁有可以在Ethereum區塊鏈上創造自己金流系統的能力,如此我們就不需要自己建一條鏈了。
我們使用SmartContract仿造貨幣性質創造了數位資產(說穿了其實就是在SmartContract上紀錄的變數而已),而這種具貨幣性質的數位資產又被稱作Token,如此我們就可以在應用程式中使用這個去中心化的金流系統,由於Token的應用很普遍,大部分的功能都已經標準化了,我們只要仿造標準來實作就可以發行自己的數位貨幣了。
在這邊我們就練習一下怎麼使用Mist發佈TokenSmartContract來發行自己的數位貨幣。
(目前我們還沒有學習過如何撰寫SmartContract,因此這邊會先直接提供範例程式碼,實作的部分我們之後再慢慢學習)
以下是我們的範例程式碼:
請打開Mist,如下圖點擊Contract,然後點擊DeployNewContract。
你會看到如下圖的頁面,請在SolidityContractSourceCode中貼上我們上面提供的範例程式碼。
貼上範例程式碼之後,Mist會自動編譯程式,檢查是否有語法上的錯誤,如果沒問題,右方的SelectContracttoDeploy就會出現選項,在這邊我們選擇TokenERC20。
選擇TokenERC20之後,右方會出現要初始化Contract的參數表單,有Initialsupply、Tokenname、Tokensymbol需要填寫。
Initialsupply代表Token的總發行量是多少,我這邊設定成7777777777,你可以設成你想要的數字。
Tokenname就是這個Token要叫什麼名字,這邊我設定成7Token,你想要取DogCoin或是CatCoin也都可以。
Tokensymbol就是這個Token要用什麼代號,像是美金就是用$、Ether是用ETH,這邊我設定成7token,你可以取自己覺得帥的代號。
Ethereum開發筆記1–3:使用Mist
Sep9,2018
Mist跟前回介紹的MetaMask一樣是可以與Ethereum進行互動的工具,除了可以管理Ethereum相關密鑰之外,Mist還包含了Ethereum節點以及網頁瀏覽器,方便大家瀏覽Dapp網頁。
首先請到這邊安裝Mist,請選擇適於自己的作業系統安裝。
由於Mist會安裝節點在你的電腦裡,也因此會同步整個帳本下來,所以會花上不少時間同時也會佔用許多硬碟空間。
我們目前僅是要使用測試鏈,所以請切換到Ropsten測試鏈(如下圖),這樣就不用花這麼多時間與空間了。
在Mist的左下角可以觀察目前已同步到你的電腦的區塊數(如下圖),如果這個數字跟Etherscan(Etherscan是一個可以查看Ethereum區塊鏈所有交易的網站)上的最新區塊數一致的話,那就代表已經同步完成了。
接下來讓我們用Mist開一個Ethereum帳戶,請點擊AddAccount,並依指示輸入密碼後創建帳號,密碼請務必要記下來,將來交易時都會需要輸入你的密碼。
學會創建Ethereum帳戶之後,我們要來看一下Mist要怎麼備份帳號,請點擊Mist上方選單的File->Backup->Accounts(如下圖),這樣就會打開帳號存放的資料夾,所有的帳號都會加密存在這邊,所以只要備份這些檔案及當時設定的密碼,你就可以在別台電腦復原你的帳號。
現在你這個Ethereum帳戶還沒有任何Ether,我們仿造之前用MetaMask來跟水龍頭要Ether的步驟來取得Ether看看。
我個人提供了一個水龍頭Dapp,請前往這個網址來取得Ether:https://blog.fukuball.com/dapp/faucet/
由於Mist也是一個Dapp網頁瀏覽器,請在Mist上方的網址列輸入:https://blog.fukuball.com/dapp/faucet/
Mist在揭露你的Ethereum帳戶資訊給Dapp網頁時都會詢問你的同意,請先選擇要瀏覽這個Dapp網頁的帳號(你可能在Mist有多個帳號,所以就需要選擇目前要用哪個帳號瀏覽這個網頁)。
76postsfound
延伸文章資訊
- 1[NLP][Python] 中文斷詞最方便的開源工具之一: Jieba
Jieba 是一款使用Python (或者說在Python 上最知名的?) 的一款開源中文斷詞工具,當然它也有支援許多不同的NLP 任務,比方說POS、關鍵字抽取.
- 2中文自然語言處理基礎 - iT 邦幫忙
因此我個人打選擇使用第二套系統jieba,中文叫做結巴,很幸運地這個套件有python的介面,使用上非常容易,只是這是大陸人開發的系統,必須自行輸入繁體字典,這篇文章 ...
- 3文本前處理:Jieba 斷詞、詞性標記與句法學 - YouTube
- 4python jieba 教學 - Pisani
人工智慧Python斷詞與文字雲教學jieba, wordcloud套件. 人工智慧Python斷詞與文字雲 ... (1) jieba套件(Python中文斷詞套件) pip install ...
- 5Python自然語言處理(二):使用jieba進行中文斷詞
结巴中文分词. Contribute to fxsjy/jieba development by creating an account on GitHub. ... Jieba提供了三種分詞模...