LibPostal是使用統計NLP和開放數據在世界範圍內解析/歸一化街道地址的C庫。該項目的目的是了解各種語言的基於位置的字符串。有關LibPostal背後研究的更全面概述,請務必查看(冗長)介紹性博客文章:
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
地址及其代表的位置對於任何處理地圖的應用程序(位置搜索,運輸,按需/送貨服務,簽到,評論)至關重要。然而,即使是最簡單的地址也充滿了當地慣例,縮寫和上下文,因此很難用傳統的全文搜索引擎有效地索引/查詢。該庫有助於將人類使用的自由形式地址轉換為適合機器比較和全文索引的清潔歸一化形式。儘管LibPostal本身並不是完整的地理編碼器,但它可以用作預處理步驟,以使任何地理編碼應用程序更聰明,更簡單,更一致。
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?
核心庫用純C編寫。語言綁定為Python,Ruby,Go,Java,PHP和Nodejs正式支持,並且很容易用其他語言編寫綁定。
如果您的公司正在使用LibPostal,請考慮要求您的組織贊助該項目。解釋人類在提到地點時的含義遠非解決問題,並且贊助可以幫助我們在地理空間NLP中追求新的邊界。作為贊助商,您的公司徽標將出現在GitHub回購頁面上,以及指向您網站的鏈接。贊助信息
單個用戶還可以通過每月捐款來幫助支持開放的GEO NLP研究:
在安裝之前,請確保有以下先決條件:
在Ubuntu/Debian上
sudo apt-get install curl autoconf automake libtool pkg-config
在Centos/Rhel上
sudo yum install curl autoconf automake libtool pkgconfig
在Mac OSX上
brew install curl autoconf automake libtool pkg-config
然後安裝C庫:
如果您使用的是M1 Mac,則將--disable-sse2添加到./configure命令。這將導致性能較差,但構建將成功。
git clone https://github.com/openvenues/libpostal
cd libpostal
./bootstrap.sh
./configure --datadir=[...some dir with a few GB of space...]
make -j4
sudo make install
# On Linux it's probably a good idea to run
sudo ldconfig
LibPostal對PKG-Config有支持,因此您可以使用PKG-Config打印將您的程序鏈接到它的標誌:
pkg-config --cflags libpostal # print compiler flags
pkg-config --libs libpostal # print linker flags
pkg-config --cflags --libs libpostal # print both
例如,如果您編寫一個名為app.c的程序,則可以這樣編譯:
gcc app.c `pkg-config --cflags --libs libpostal`
msys2/mingw
對於Windows,構建過程當前需要MSYS2和MINGW。可以從http://msys2.org下載。請按照MSYS2網站上的說明進行安裝。
請通過運行確保MSYS2是最新的:
pacman -Syu
安裝以下先決條件:
pacman -S autoconf automake curl git make libtool gcc mingw-w64-x86_64-gcc
然後構建C庫:
git clone https://github.com/openvenues/libpostal
cd libpostal
cp -rf windows/* ./
./bootstrap.sh
./configure --datadir=[...some dir with a few GB of space...]
make -j4
make install
注意:設置datadir時, C:驅動器將作為/c輸入。 libpostal構建腳本會在路徑末端自動添加libpostal ,因此'/c'將變成C:libpostal 。
編譯的.dll將在src/.libs/ Directory中,應稱為libpostal-1.dll 。
如果您需要.lib導入庫將其鏈接到您的應用程序。您可以使用Visual Studio lib.exe工具和libpostal.def定義文件生成一個:
lib.exe /def:libpostal.def /out:libpostal.lib /machine:x64
可用於libpostal的替代數據模型。它是由Senzing Inc.創建的,用於改善對美國,英國和新加坡地址的解析,並改善了美國農村路線地址處理。要啟用此添加MODEL=senzing :
./configure --datadir=[...some dir with a few GB of space...] MODEL=senzing
該模型的數據來自OpenAddress,OpenStreetMap和由客戶反饋(幾百個記錄)生成的數據,總計約有230個國家 /地區的數據記錄,使用100多種語言。來自OpenStreetMap和OpenAddress的數據很好,但不是完美的,因此通過過濾不良形成的地址來修改數據集,糾正錯誤分類的地址令牌和刪除不屬於地址的代幣,每當遇到這些條件時。
Senzing創建了來自89個國家 /地區的12950個地址的數據集,用於測試和驗證其模型的質量。數據集使用來自OSM的隨機地址生成,每個國家 /地區最少50。從Senzing支持團隊和客戶以及LibPostal Github頁面上獲得了難以實現的地址,並將其添加到該集合中。使用此測試集,Senzing模型比默認模型獲得了4.3%的解析結果。
該模型的大小約為2.2GB,默認模型為1.8GB,因此請記住,如果Storages空間很重要。
有關此數據模型的更多信息,請訪問以下網址:https://github.com/senzing/libpostal-data,如果您遇到此模型的任何問題,無論它們是否與Parses,安裝或任何其他問題有關
Libpostal的國際地址解析器使用機器學習(有條件的隨機字段),並接受了地球上每個居住國家的10億個地址的培訓。我們將OpenStreetMap和OpenAddresses用作結構化地址的來源,以及OpenCage地址格式模板,網址為:https://github.com/opencagedata/addressata/address-formatting來構建培訓數據,補充包含多邊形的多邊形,並產生了多邊形組件,並產生了公寓/地面/地板/地板盒和PO盒。我們還添加了縮寫,隨機掉出組件等,以使解析器盡可能穩健,以使現實世界中的輸入盡可能強。
這些示例解析結果取自Interactive address_parser程序,該程序在運行時用libpostal make 。請注意,解析器可以處理逗號與無逗號以及各種套管和組件的排列(如果輸入是僅僅是城市或城市/郵政編碼)。
解析器在持有數據方面達到了很高的精度,目前為99.45%的正確解析(這意味著分子中的1個以使每個令牌在地址中正確正確)。
這是使用Python綁定的解析器API的示例:
from postal . parser import parse_address
parse_address ( 'The Book Club 100-106 Leonard St Shoreditch London EC2A 4RH, United Kingdom' )以及C API的一個例子:
#include <stdio.h>
#include <stdlib.h>
#include <libpostal/libpostal.h>
int main ( int argc , char * * argv ) {
// Setup (only called once at the beginning of your program)
if (! libpostal_setup () || ! libpostal_setup_parser ()) {
exit ( EXIT_FAILURE );
}
libpostal_address_parser_options_t options = libpostal_get_address_parser_default_options ();
libpostal_address_parser_response_t * parsed = libpostal_parse_address ( "781 Franklin Ave Crown Heights Brooklyn NYC NY 11216 USA" , options );
for ( size_t i = 0 ; i < parsed -> num_components ; i ++ ) {
printf ( "%s: %sn" , parsed -> labels [ i ], parsed -> components [ i ]);
}
// Free parse result
libpostal_address_parser_response_destroy ( parsed );
// Teardown (only called once at the end of your program)
libpostal_teardown ();
libpostal_teardown_parser ();
}地址解析器可以從技術上使用培訓數據中定義的任何字符串標籤,但是根據Opencage的地址構造庫中定義的字段,這些字符標籤以及當前定義的標籤,以及LibPostal添加的一些字段來處理特定模式:
Expand_Address API將混亂的現實世界地址轉換為適合搜索索引,哈希等的歸一化等效物。
這是使用Python綁定的交互式示例:
libpostal包含一個受OSM訓練的語言分類器,以檢測給定地址中使用了哪些語言,因此可以應用適當的正常化。唯一需要的輸入是原始地址字符串。這是各種語言中一些較不直接的正常化的簡短列表。
| 輸入 | 輸出(可能在libpostal中是多重的) |
|---|---|
| 一百二十E 96街 | 東96街120號 |
| c/ ocho,pi 4 | Calle 8Polígono工業4 |
| v xx settembre,20 | 通過20 settembre 20 |
| Quatre vingt duze R. del'église | 92 Rue de l eglise |
| 啟,4,strimа | 當函 |
| 啟,4,strimа | Ulitsa Karetnyy Ryad Dom 4 Stroyeniye 7 |
| Marktstraße14 | Markt Strasse 14 |
libpostal當前支持60多種語言的這些類型的正常化,您可以添加更多(而無需編寫任何C)。
有關進一步的閱讀和一些奇異的地址邊緣案例,請參見:虛假的程序員相信地址。
這是使用Python綁定以簡潔的示例(大多數高級語言綁定都是相似的):
from postal . expand import expand_address
expansions = expand_address ( 'Quatre-vingt-douze Ave des Champs-Élysées' )
assert '92 avenue des champs-elysees' in set ( expansions )c API等效是更多的行,但仍然相當簡單:
#include <stdio.h>
#include <stdlib.h>
#include <libpostal/libpostal.h>
int main ( int argc , char * * argv ) {
// Setup (only called once at the beginning of your program)
if (! libpostal_setup () || ! libpostal_setup_language_classifier ()) {
exit ( EXIT_FAILURE );
}
size_t num_expansions ;
libpostal_normalize_options_t options = libpostal_get_default_options ();
char * * expansions = libpostal_expand_address ( "Quatre-vingt-douze Ave des Champs-Élysées" , options , & num_expansions );
for ( size_t i = 0 ; i < num_expansions ; i ++ ) {
printf ( "%sn" , expansions [ i ]);
}
// Free expansions
libpostal_expansion_array_destroy ( expansions , num_expansions );
// Teardown (only called once at the end of your program)
libpostal_teardown ();
libpostal_teardown_language_classifier ();
}構建Libpostal之後:
cd src/
./libpostal "Quatre vingt douze Ave des Champs-Élysées"
如果您有一個文本文件或流式的每行地址,則命令行接口還接受stdin的輸入:
cat some_file | ./libpostal --json
構建Libpostal之後:
cd src/
./address_parser
address_parser是一個交互式外殼。只需鍵入地址,libpostal將解析它們並打印結果。
LibPostal設計為高級語言使用。如果您看不到自己選擇的語言,或者您正在寫一種語言綁定,請告訴我們!
正式支持的語言綁定
非正式語言綁定
數據庫擴展
非正式的REST API
libpostal休息碼頭
Libpostal Zeromq Docker
Libpostal用於自動測試最大。要運行測試,請使用:
make check
即使您的C生鏽/不存在,添加測試用例也很容易,我們也很喜歡貢獻。我們主要使用功能測試來檢查字符串輸出的字符串輸入。
Libpostal還會定期通過OSM(清潔)的數百萬個地址以及生產地理編碼器(不那麼乾淨)的匿名查詢進行戰鬥測試。在此過程中,我們使用Valgrind檢查內存洩漏和其他錯誤。
LibPostal需要從S3下載一些數據文件。基本文件是執行擴展所需的數據結構的盤表示。對於地址解析,由於模型培訓需要幾天,因此我們將經過全面訓練的模型發佈到S3,並隨著新地址被添加到OSM,OpenAddresses等,將自動更新它。語言分類器模型也是如此。
運行時,數據文件將自動下載。要檢查並下載任何新數據文件,您可以make或運行:
libpostal_data download all $YOUR_DATA_DIR/libpostal
並將$ your_data_dir替換為您在安裝過程中進行配置的任何內容。
libpostal包含許多影響擴展,語言分類器和解析器的每語言詞典。要探索詞典或用您的語言撰寫縮寫/短語,請參閱資源/詞典。
在機器學習中,大量培訓數據通常對於獲得良好的結果至關重要。許多開源機器學習項目僅發布模型代碼(當且僅當您是Google時才可重複的結果),或者在訓練條件未知的情況下進行烘焙的模型。
libpostal有些不同,因為它經過了每個人都可以使用的開放數據培訓,因此我們發布了整個培訓管道(此存儲庫中的Geodata軟件包),以及Internet存檔上產生的培訓數據本身。超過100GB解壓縮。
培訓數據存儲在Archive.org上,到創建日期。此存儲庫的主目錄中還存儲了一個名為current_parser_training_set的文件,該文件存儲了最近創建的培訓集的日期。要始終指向最新數據,請嘗試以下內容: latest=$(cat current_parser_training_set) ,然後使用該變量代替日期。
所有文件均可在https://archive.org/download/libpostal-parser-training-data-yyymmdd/quil as Gzip'd tab-separated值(TSV)文件(如: languagetcountrytaddress 。
如果解析器的性能不如您在特定類型的地址上所希望的,那麼最好的追索方法是使用GREP/AWK查看培訓數據,並嘗試確定是否存在某些未捕獲的模式/地址。
縮寫擴展:例如擴展“ RD” =>“道路”,但幾乎用於任何語言。 LibPostal支持> 50種語言,並且添加新語言或擴展當前字典很容易。意識形態語言(不被白色空格分開,例如中文),以及將通道類型串聯到弦末端的日耳曼語言,並且可以選擇分開,因此Rosenstraße和RosenStraße等效。
國際地址解析:有條件的隨機場,將“ 123 Main Street New York New York”解析為{“ House_number”:123,“ Road”:“ Main Street”,“ City”,“ City”:“ New York”,“ State”,“ State”:“ New York”}。解析器適用於各種各樣的國家和語言,而不僅僅是我們/英語。該模型經過超過10億個地址和地址式字符串的培訓,使用“ Opencage地址格式格式”存儲庫中的模板,為世界上每個居民的國家構建格式化的,標記為格式的,標記的傳輸示例。進行了許多類型的規範化,以使訓練數據盡可能接近真正的混亂地理編碼器輸入。
語言分類:經過訓練的多項式邏輯回歸(使用ftrl-proximal方法來誘導稀疏性)在所有openstreetmap方法上,addr:* tag,toponyms和格式化地址。標籤是使用OSM國家/地區的Point-in-Polygon測試來得出的,分別針對國家/地區和Admin 1邊界來得出標籤。因此,例如,西班牙語是西班牙的默認語言,但在不同地區,例如加泰羅尼亞,加利西亞,巴斯克地區,各自的區域語言是默認的。在區域語言是非默認的情況下,例如威爾士,布雷頓,Occitan的情況下,採用了基於字典的歧義。詞典還用於縮寫規範短語,例如“ calle” =>“ c/”(在語言分類器和地址分析器培訓集上執行)
數字表達式解析(“二十一個” => 21st,“ quatre-wvingt-douze” => 92,再次使用CLDR中提供的數據)支持> 30種語言。處理具有串聯表達式的語言,例如milleottocento => 1800。可選地將羅馬數字歸一化,無論語言如何(ix => 9),這些語言以許多君主,教皇和。
快速,準確的令牌化 / Lexing :以> 1M令牌 /秒為單位,以UTF8單詞分割的形式實現TR-29規格,將East Asian語言以字符而不是在WhiteSpace上為單位。
UTF8歸一化:可選地將UTF8分解為NFD歸一化形式,條紋標記標記為a和/或應用拉丁語ASCII音譯。
音譯:例如μ=> ulica或ulitsa。使用所有CLDR變換,儘管LibPostal不需要拉動所有ICU(可能與您的系統版本衝突),但使用ICU使用的完全相同的源數據。注意:某些語言,尤其是希伯來語,阿拉伯語和泰語可能不包含元音,因此通常不符合人類所做的音譯。可以為其中一些語言實施統計音譯者。
腳本檢測:檢測給定字符串使用的腳本(可以是多個腳本,例如自由形式的香港或澳門地址可以在同一地址中同時使用Han和Latin腳本)。在音譯中,我們可以為給定的Unicode腳本使用所有適用的音譯器(例如,可以用希臘 - 拉丁,希臘 - 拉汀-BGN和希臘語 - 拉丁蛋白 - ungegn來譯)。
LibPostal最初是作為開放式項目的一部分而創建的,以解決場地縮減問題。在OpenVenues中,我們有一個數據集的數據集,這些數據集源自來自Common Crawl的網頁的trabytes。共同的爬網每月發表,因此即使合併了兩個爬網的結果也會產生重要的重複。
辯論是一個相對良好的領域,對於諸如網頁,學術論文等的文本文檔。存在相當不錯的近似相似性方法,例如Minhash。
但是,對於物理地址,經常使用常規縮寫,例如Road == RD,California == CA或紐約市== NYC會使事情變得有些複雜。即使使用Minhash之類的技術,該技術非常適合大約匹配,並且相當於Jaccard兩組的相似性,我們也必須使用非常簡短的文本,通常情況下,兩個等效的地址(一個縮寫和一個完全指定)在N-gram集合中的非常緊密的匹配。在非拉丁文腳本中,說俄羅斯的地址及其相當的音譯相當,可以想像的兩個地址指的是同一地點,即使是一個角色也可能不匹配。
作為一個激勵人物的例子,請考慮以下兩種同等的方式,以不同的慣例和詳細的詳細說法來編寫特定的曼哈頓街道地址:
顯然,'30 W 26th st fl#7!= '30西二十六街7'從字符串比較意義上,但是人類可以抓住這兩個地址指的是相同的物理位置。
LibPostal旨在創建分解為組件的歸一化地理字符串,以便我們可以更有效地理解兩個地址如何真正匹配並做出有關DUPES的自動化服務器端決策。
如果以上聽起來很像地理編碼,那是因為它在某種程度上,僅在OpenVenues情況下,我們必須在沒有UI或用戶的情況下進行地理位置,以在自動完整的下拉列表中選擇正確的地址。給定一個源地址的數據庫,例如OpenAddresses或OpenStreetMap(或以上所有內容),可以使用LibPostal在MapReduce或流中心處理等設置中實現地址刪除和服務器端批次地理編碼等內容。
現在,使用巨型同義詞文件,腳本,自定義分析儀,象徵器等,而不是試圖將特定於地址的約定烘烤到傳統文檔搜索引擎中,而是看起來像這樣:
這樣,libpostal可以相對於數據集的大小執行恆定時間匹配的模糊地址。
libpostal用C撰寫的三個原因(根據重要性順序):
可移植性/無處不在:LibPostal的目標是人們實際使用的日常使用的高級語言:Python,Go,Ruby,Nodejs等。C的優點在於,幾乎任何編程語言都可以綁定到它,並且C與其無處不在,因此,您可以在應用程序中直接使用libostal,而無需使用libpostal,而無需單獨使用libostal。我們支持MAC/Linux(Windows不是優先事項,但樂於接受補丁),具有標準的自動工具構建和用於數據文件的Endian-nessness-grognostic文件格式。 Python綁定是作為此存儲庫的一部分維護的,因為它們需要構建培訓數據。
內存效率:libpostal旨在在MAPREDUCE設置中運行,根據機器配置,我們可能僅限於每個過程的RAM <1GB。盡可能多地使用連續的數組,嘗試(建立在連續數組),Bloom過濾器和壓縮的稀疏矩陣來保持內存使用量較低。可以在移動設備上使用Libpostal,該設備具有在一個國家或少數國家 /地區接受培訓的模型。
性能:這是列表中的最後一個原因。 LibPostal中的大多數優化用於內存使用而不是性能。考慮到它的工作量,Libpostal非常快。它可以在我們測試的平台上的單個線程 /過程中處理10-30k地址 /秒(這意味著在一個多小時內處理OSM Planet中的每個地址)。查看簡單的基準計劃,以測試您的環境和各種輸入。在MAPREDUCE設置中,每核性能並不重要,因為一切都在並行完成,但是在Mapzen上有一些流式攝入應用程序,需要在其中運行進程。
Libpostal用現代,清晰的C99編寫,並使用以下慣例:
LibPostal Repo中的Geodata Python軟件包包含用於預處理各種GEO數據集和構建C模型使用的培訓數據的管道。對於大多數用戶而言,不需要此軟件包,而是對於那些有興趣生成新類型地址或改善Libpostal的培訓數據的人,這是可以尋找的地方。
在持有的測試數據(這意味著模型以前從未見過的標籤)時,地址解析器可實現99.45%的完整分析精度。
對於某些任務(例如命名實體識別),最好使用諸如F1分數或變體之類的東西,主要是因為存在類偏見問題(大多數單詞是非實體,並且一個簡單地預測每個標記的非實體的系統實際上在準確性方面都可以很好地做得很好)。地址解析並非如此。每個令牌都有一個標籤,並且在培訓數據中都有數百萬個班級的示例,因此,準確性是可取的,因為它是一種干淨,簡單和直觀的性能度量。
在這裡,我們使用完整的解析精度,這意味著我們只會在分子中獲得一個“點”,如果地址中的每個令牌都可以正確。這應該是一個更好的措施,而不是簡單地看每個令牌是否正確。
儘管當前的解析器在大多數標準地址方面都可以很好地工作,但仍有改進的餘地,尤其是在確保我們使用的培訓數據盡可能接近地解決野外。地址解析器可以進一步改進兩種主要方法(按困難順序):
歡迎錯誤報告,問題和拉動請求。在提交問題,錯誤報告或提取請求之前,請閱讀貢獻指南。
提交問題:https://github.com/openvenues/libpostal/issues。
特別感謝 @benk10的初始Windows Build和@aeroxuk,將其無縫集成到項目中並設置Appveyor構建。
該軟件可根據MIT許可條款作為開源。