標籤: USB CONNECTOR

  • 聯合國:反疫苗運動 助長薩摩亞麻疹疫情惡化

    摘錄自2019年12月6日中央通訊社綜合報導

    聯合國兒童基金會(UNICEF)太平洋島嶼負責人今天(5日)表示,社群媒體巨頭必須嚴厲取締反疫苗接種貼文,這些貼文助長薩摩亞(Samoa)致命麻疹疫情惡化。

    UNICEF地區代表耶特(Sheldon Yett)表示,推特(Twitter)、臉書(Facebook)和Instagram(IG)等網路平台上「極不負責任」的反疫苗接種訊息,加劇了薩摩亞爆發的麻疹疫情,自10月中旬以來已造成62人死亡。耶特告訴法新社:「很明顯地它們必需負起企業責任並展開行動,確保那些人民,特別是弱勢族群能獲得正確資訊,讓孩童得以存活。」

    在麻疹疫情爆發前,薩摩亞的疫苗接種率降至只剩略超過30%,遠低於公認最佳接種率90%,這也使得該海島國家極易受到感染。世界衛生組織(WHO)把矛頭指向反疫苗宣傳運動。耶特表示,這項運動主要是由海外倡議人士在網路上展開。

    「很不幸的是,這項運動在薩摩亞找到願意相信的民眾,那裡有一部分人懷疑醫療保健服務品質,且可能不信任當地(疫苗)供應者。」他說,來自諸如美國和澳洲等富裕已開發國家的運動人士,在網路上張貼反疫苗訊息,他們必須意識到自己的所作所為會對開發中國家帶來衝擊。

    本站聲明:網站內容來源環境資訊中心https://e-info.org.tw/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

    ※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

    ※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

    ※評比南投搬家公司費用收費行情懶人包大公開

    ※幫你省時又省力,新北清潔一流服務好口碑

  • 奧迪2018年量產首款純電動SUV汽車

    奧迪準備2018年在布魯塞爾量產首款純電動SUV汽車。布魯塞爾的奧迪工廠會同時製造汽車和電池,它還要向大眾其它汽車提供電池。

    在2015年舉行的法蘭克福汽車展上,奧迪展示了e-tron概念車,它預示著奧迪即將推出量產版本的SUV,汽車取名為“Q6 e-tron”。

    Q6 e-tron配有3個電動機,一個位於前軸,兩個放在後面。大型電池組安裝在前後軸之間,位於乘客座位的下方,這樣可以降低重心,提供更好的平衡性。

    Q6 e-tron安裝的電池來自韓國LG化學和三星SDI,充電一次可以行駛約500千米。資料是以歐洲測試週期作為標準的,如果用美國環境保護署(EPA)的標準測試里程會短一些。因此,Q6 e-tron充電一次的行駛距離估計為390千米,這個資料更為合理一些。

    目前布魯塞爾的奧迪工廠主要負責生產A1,奧迪會將A1生產線轉移到西班牙工廠,讓布魯塞爾負責生產Q6 e-tron。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?

  • 英國計畫開發可以同時照明和給電動汽車充電的街燈

    英國政府日前給倫敦市劃撥了4000萬英鎊資金,供其開發可以同時照明和給電動汽車充電的街燈。

    現在尚不清楚這種街燈將會是什麼樣子的,也不清楚它們將於何時推出。

    寶馬公司也在努力競標成為這個項目的贊助商。但是,倫敦的這個街燈項目尚未宣佈任何具體計畫。

    倫敦還斥資1300萬英鎊啟動了“未來鄉鄰”(neighborhoodsofthefuture)計畫。該計畫旨在給電動汽車司機提供免費的停車位以及交通優先權,例如可以使用公共汽車道,以鼓勵更多的人購買這種更環保的汽車。

    此外,倫敦當局證實,到2020年,該市將會出現3000輛混合動力巴士和300輛零排放單層巴士;而且,該市將會撥款60萬英鎊,讓倫敦的消防隊全部配備電動汽車。

    英國總共挑選了4個城市做試點,給它們分別撥款數百萬英鎊讓其推行電動汽車。其中布里斯托爾市還推出了一項為期四周的先試駕再購買的活動,以促使對電動汽車有興趣的人進行購買。

    英國還劃撥了500萬英鎊研發資金,用於開發其他相關專案。例如,約克市的蓋有太陽頂棚的“停放小轎車換乘公共汽車進城”(parkandride)中心。它的設計就是為了減少空氣污染。

    英國還有一個6000萬英鎊的專案,該專案包括有一個名為goultralowcities的基金。該基金旨在支持電動汽車、投資低排放公共交通以及研發超長續航能力的電池。

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※為什麼 USB CONNECTOR 是電子產業重要的元件?

    網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

    ※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

    ※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

    新北清潔公司,居家、辦公、裝潢細清專業服務

  • 特斯拉遭知名放空機構盯上!供需恐出包、股價下挫

    特斯拉遭知名放空機構盯上!供需恐出包、股價下挫

    知名放空機構香櫞研究(Citron Research)去(2015)年10月狙擊加拿大專業製藥公司Valeant Pharmaceuticals International Inc.、質疑該公司認列的藥品收入,導致其股價在一天內慘跌19%後,又在去年12月16日將「2016年年度放空標的」頭銜頒給以色列先進駕駛輔助系統(Advanced Driver Assistance Systems;ADAS)大廠Mobileye N.V.,使其股價一路滾落了42%。   現在,Citron把炮口轉向美國豪華電動車製造商特斯拉(Tesla Motors, Inc.),週二(3月1日)透過Twitter聲稱特斯拉供需出狀況、將使其股價在今年底下探100美元。Citron還指出,消息面看來對股價相當不利。   特斯拉1日聞訊逆勢下挫2.91%、收186.35美元。特斯拉預定3月31日首度公開專為大眾設計的次世代電動車「Model 3」。   其實,在特斯拉於2月中公布第4季財報前,Model X休旅車的產能問題、低油價恐衝擊電動車銷售量等疑慮,就不斷壓抑公司股價。   不過,當特斯拉維持2016年強勁的銷售預估不變、還聲稱會在2017年發售Model 3之後,股價就應聲反彈。   特斯拉執行長Elon Musk更對自家公司展現信心。洛杉磯時報、Forbes報導,Musk已在1月29日執行選擇權,斥資350萬美元購入總值1億美元的特斯拉股票(當時其股價還有191.20美元)。   Citron最近雖因準確看空Valeant、Mobileye而受到矚目,但其實據華爾街日報報導,該機構2013年對特斯拉的空方評價卻成效不彰,特斯拉2013年迄今股價仍上漲了37%。   Citron、Musk這次誰勝誰負,還得看特斯拉能否順利拉高Model X與Model S的產能,而在內華達州占地1,000萬平方英尺的電池廠房也需如期完工,才能生產較為平價的大眾車款Model 3。   (本文內容由授權使用;首圖來源: CC BY 2.0)

    本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

    ※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

    ※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

    ※評比南投搬家公司費用收費行情懶人包大公開

    ※幫你省時又省力,新北清潔一流服務好口碑

  • FastDFS圖片服務器單機安裝步驟(修訂版)

    FastDFS圖片服務器單機安裝步驟(修訂版)

    前面已經講 ,通過此文章可以了解FastDFS組件中單機安裝流程。

    單機版架構圖

    以下為單機FastDFS安裝步驟

    一、環境準備

    CentOS 7.X

    使用的版本: libfastcommon-1.0.41.tar.gz

    使用的版本: fastdfs-6.01.tar.gz

    使用的版本:fastdfs-nginx-module-1.21.tar.gz

    使用的版本: nginx-1.16.1.tar.gz

    二、安裝過程

    1、安裝 libfastcommon-1.0.41.tar.gz

    tar -zxvf libfastcommon-1.0.41.tar.gz
    cd libfastcommon-1.0.41/
    ./make.sh
    ./make.sh install

    2、安裝 FastDFS

    tar -zxvf  fastdfs-6.01.tar.gz
    cd fastdfs-6.01/
    ./make.sh
    ./make.sh install

    準備配置文件

    cp /etc/fdfs/tracker.conf.sample /etc/fdfs/tracker.conf
    cp /etc/fdfs/storage.conf.sample /etc/fdfs/storage.conf
    cp /etc/fdfs/client.conf.sample /etc/fdfs/client.conf
    cd /opt/apps/fastdfs-6.01/conf
    cp http.conf mime.types /etc/fdfs/

    Tracker Server 配置

    vim /etc/fdfs/tracker.conf
    修改配置如下:
    #tracker server端口號
    port=22122
    #存儲日誌和數據的根目錄
    base_path=/opt/fastdfs/tracker
    #HTTP服務端口
    http.server_port=80
    開放防火牆端口

    1、打開跟蹤端口

    vim /etc/sysconfig/iptables

    2、添加以下端口行:

    -A INPUT -m state --state NEW -m tcp -p tcp --dport 22122 -j ACCEPT

    3、重啟防火牆

    service iptables restart
    啟動Tracker
    /etc/init.d/fdfs_trackerd start

    Storage Server 配置

    vim /etc/fdfs/storage.conf
    修改配置如下:
    #storage server端口號
    port=23000
    #數據和日誌文件存儲根目錄
    base_path=/opt/fastdfs/storage
    #第一個存儲目錄
    store_path0=/opt/fastdfs/storepath0
    #tracker服務器IP和端口
    tracker_server=192.168.0.1:22122
    #http訪問文件的端口(默認8888,看情況修改,和nginx中保持一致)
    http.server_port=8888
    開放防火牆端口

    1、打開跟蹤端口

    vim /etc/sysconfig/iptables

    2、添加以下端口行:

    -A INPUT -m state --state NEW -m tcp -p tcp --dport 23000 -j ACCEPT

    3、重啟防火牆

    service iptables restart
    啟動Storage
    /etc/init.d/fdfs_storaged start
    查看集群狀態
     fdfs_monitor /etc/fdfs/storage.conf list
    

    查看狀態是否正常

    Storage 1:
    id = 6.0.36.243
    ip_addr = 6.0.36.243 (anantes-651-1-49-net.w2-0.abo.wanadoo.fr) ACTIVE

    Client配置

    vim /etc/fdfs/client.conf
    
    修改配置如下:
    #
    base_path=/opt/apps/fastdfs/client
    #tracker服務器IP和端口
    tracker_server=192.168.0.1:22122 
    
    上傳一個圖片測試是否能上傳成功
     fdfs_upload_file /etc/fdfs/client.conf test.jpg
    

    test.jpg 是測試本地上傳的圖片,路徑請填寫正確

    3、安裝Nginx和 fastdfs-nginx-module

    #解壓fastdfs-nginx-module
    tar -zxvf fastdfs-nginx-module-1.21.tar.gz
    cd fastdfs-nginx-module-1.21/
    cp ./src/mod_fastdfs.conf /etc/fdfs
    #解壓nginx
    tar -zxvf nginx-1.16.1.tar.gz
    cd nginx-1.16.1/
    #安裝nginx_http_image_filter_module
    yum -y install gd-devel
    yum -y install zlib zlib-devel openssl openssl--devel pcre pcre-devel
    #添加模塊
    ./configure --add-module=../fastdfs-nginx-module-1.21/src --prefix=/usr/local/nginx --with-http_image_filter_module 
    #編譯nginx
    make
    #安裝nginx
    make install
    

    查看是否安裝成功

    /usr/local/nginx/sbin/nginx -V
    

    查看插件是否安裝成功

    [root@FastDFS nginx-1.16.1]# /usr/local/nginx/sbin/nginx -V
    nginx version: nginx/1.16.1
    built by gcc 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC) 
    configure arguments: --add-module=../fastdfs-nginx-module-1.21/src --prefix=/usr/local/nginx --with-http_image_filter_module
    [root@FastDFS nginx-1.16.1]# 
    

    修改Nginx訪問

    vim /etc/fdfs/mod_fastdfs.conf

    修改配置如下:

    #
    connect_timeout=10
    #tracker服務器IP和端口
    tracker_server=192.168.0.1:22122
    #是否啟用group組名
    url_have_group_name=true
    #
    store_path0=/opt/fastdfs/storepath0

    修改Nginx配置:

    vim /usr/local/nginx/conf/nginx.conf
    

    修改配置如下:

    server {
        listen       80;
        server_name  localhost;
    
        #charset koi8-r;
    
        #access_log  logs/host.access.log  main;
    
        location / {
            root   html;
            index  index.html index.htm;
        }
        #圖片帶壓縮訪問
        location ~ /group1/M00/(.*)\.(jpg|gif|png)!format=([0-9]+)_([0-9]+) {
            alias  /home/fastdfs/storage/data/;
            ngx_fastdfs_module;
            set $w $3;
            set $h $4;
    
            rewrite group1/M00(.+)\.(jpg|gif|png)!format=([0-9]+)_([0-9]+)$ group1/M00$1.$2 break;
    
            image_filter resize $w $h;
            image_filter_buffer 5M;
        }
        #主圖訪問
        location ~ /group([0-9])/M00/(.+)\.?(.+) {
            alias /home/fastdfs/storage/data/;
            ngx_fastdfs_module;
        }
    ...
    }
    

    啟動Nginx

    #啟動
    /usr/local/nginx/sbin/nginx
    #停止
    /usr/local/nginx/sbin/nginx -s stop
    #重啟
    /usr/local/nginx/sbin/nginx -s reload

    通過以上配置完成FastDFS的搭建。

    測試圖片訪問

    圖片訪問示例:

    主圖訪問

    http://218.2.204.124:30308/group1/M00/00/03/BgAk813IvTCAIxxxAAD44NFKFPc908.png

    壓縮圖片 (主圖后加 !format=寬度_高度)訪問

    http://218.2.204.124:30308/group1/M00/00/03/BgAk813IvTCAIxxxAAD44NFKFPc908.png!format=400_10

    未解決的問題

    壓縮圖片使用主圖后?format=寬度_高度

    本文由博客一文多發平台 發布!

    再次感謝!!! 您已看完全文,歡迎關注微信公眾號猿碼 ,你的支持是我持續更新文章的動力!

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?

  • 基於 HTML5 + WebGL 實現 3D 挖掘機系統

    基於 HTML5 + WebGL 實現 3D 挖掘機系統

    前言

    在工業互聯網以及物聯網的影響下,人們對於机械的管理,机械的可視化,机械的操作可視化提出了更高的要求。如何在一個系統中完整的显示机械的運行情況,机械的運行軌跡,或者机械的机械動作顯得尤為的重要,因為這會幫助一個不了解這個机械的小白可以直觀的了解机械的運行情況,以及机械的所有可能發生的動作,對於三一或者其它國內國外重工机械的公司能夠有一個更好的展示或者推廣。
    挖掘機,又稱挖掘机械(excavating machinery),從近幾年工程机械的發展來看,挖掘機的發展相對較快,挖掘機已經成為工程建設中最主要的工程机械之一。所以該系統實現了對挖掘機的 3D 可視化,在傳統行業一般都是基於 Web SCADA 的前端技術來實現 2D 可視化監控,而且都是 2D 面板部分數據的監控,從後台獲取數據前台显示數據,但是對於挖掘機本身來說,挖掘機的模型,挖掘機的動作,挖掘機的運行可視化卻是更讓人眼前一亮的,所以該系統對於挖機的 3D 模型做出了動作的可視化,大體包括以下幾個方面:

    • 前進後退 — 用戶可以通過鍵盤 wasd 實現前後左右,或者點擊 2D 界面 WASD 來實現挖機的前進後退。
    • 機身旋轉 — 用戶可以通過鍵盤左右鍵實現機身的旋轉,或者點擊 2D 界面 < > 來實現挖機機身的旋轉。
    • 大臂旋轉 — 用戶可點擊 2D 界面第一個滑塊部分實現大臂的旋轉。
    • 小臂旋轉 — 用戶可點擊 2D 界面第二個滑塊部分實現小臂的旋轉。
    • 挖斗挖掘 — 用戶可點擊 2D 界面第三個滑塊部分實現挖斗部分的旋轉挖掘。
    • 挖機動畫 — 用戶可點擊 2D 界面鏟子圖標,點擊之後系統會把挖機本身幾個動畫做一個串聯展示。

    本篇文章通過對挖掘機可視化場景的搭建,挖機机械動作代碼的實現進行闡述,幫助我們了解如何使用  實現一個挖掘機的可視化。

    預覽地址: 

    界面效果預覽

    挖機机械運動效果

    通過上面 gif 圖片可以看出挖掘機的幾個主要動作。

    挖機挖斗運動效果

    滑動頁面的第三個滑桿控制挖斗的旋轉挖掘。

    挖機機身運動

    通過上面 gif 圖片可以看出挖掘機的前進後退以及機身旋轉幾個運動。

    場景搭建

    該 3D 場景中所有形狀都是用 HT 內部的牆面工具進行構建,通過設置牆面透明屬性 shape3d.transparent 為 true 以及對構建出的牆面進行貼圖來構造出場景中的類似建築的显示效果,具體的樣式可以參考 HT 的 ,場景效果:

    通過上圖我們可以看到場景中有許許多多的牆面建築,所以它們有許多相同的地方,例如樣式以及貼圖都是一樣的,所以在 HT 中可以通過批量的操作對這些牆面進行處理,批量的意思指的是在當前未處理的情況下的牆面圖元是一個個獨立繪製的模型,所以性能會比較差,而當一批圖元聚合成一個大模型進行一次性的繪製時,則會極大提高 WebGL 刷新性能,這就是批量所以要做的事情,具體可以參考 HT 的 

    該系統 2d 面板部分則也是通過 HT 的矢量進行繪製,面板部分主要包括當前挖機的作業情況,工作時間,保修信息,故障信息等,通過二維的方式展示這些數據信息,面板截圖:

    机械運動代碼分析

    該系統中挖機的動作是十分的重要和關鍵的,大小臂運動時液壓杠該如何運動,挖斗運動時液壓桿,旋轉點零件,以及連接到挖鬥上的零部件如何聯動起來是關鍵點,机械動畫中用到大部分數學知識進行點面位置的計算,以下是幾個關鍵的數學知識點作為基礎:

    在數學中,向量(也稱為幾何向量、矢量),指具有大小和方向的量。它可以形象化地表示為帶箭頭的線段。系統中會通過向量的叉乘算出與某個面垂直的向量即法向量,在計算挖斗旋轉時需要計算出與挖斗面垂直的法向量來進行點的計算,HT 中封裝了 ht.Math 的數學函數,裏面的 ht.Math.Vector2 指的即為二維向量,ht.Math.Vector3 則為三維的向量,可以傳入三個數值進行初始化向量,向量的原型中有 cross 方法用來計算兩個向量的法向量,例如以下偽代碼:

    1 var Vector3 = ht.Math.Vector3;
    2 var a = new Vector3([10, 10, 0]);
    3 var b = new Vector3([10, 0, 0]);
    4 var ab = a.clone().cross(b);

    以上代碼中 ab 即為計算法向量,a.clone 是為了避免 cross 運算會修改原本的 a 內容,所以克隆出一個新的向量進行叉乘,以下為示意圖:

    挖斗机械運動分析

    在進行挖斗部分的机械代碼時會將挖斗的位置以及挖斗所有連接點的設備轉化為相對於某個節點的相對位置,例如節點 A 在世界中的坐標為 [100, 100, 100],世界中還有一個節點 B,而且節點 B 的坐標為 [10, 10, 10] 則節點 A 相對於節點 B 的相對位置即為 [90, 90, 90],因為在計算挖斗的位置時,挖機可能此時已經運動到某一點或者旋轉到某一個軸,所以此時不能使用相對世界的坐標,需要使用相對挖機機身的相對坐標來進行計算,代碼中提供了 toLocalPostion(node, worldPosition) 用來將世界的坐標 worldPosition 轉化為相對 node 的相對坐標,以下為代碼實現:

    1 var Matrix4 = ht.Math.Matrix4,
    2 Vector3 = ht.Math.Vector3;
    3 var mat = new Matrix4().fromArray(this.getNodeMat(g3d, node)),
    4 matInverse = new Matrix4().getInverse(mat),
    5 position = new Vector3(worldPosition).applyMatrix4(matInverse);
    6 return position.toArray();

    該函數的返回值即為相對坐標,挖機中需要轉化的坐標為連接着挖斗以及小臂的兩個零部件,系統中用 armHinge 以及 bucketHinge 來分別表示小臂樞紐以及挖斗樞紐這兩個零部件,可以從側面來看挖斗的動作,從下圖可以看出,關鍵點是算出交點 P 的坐標,交點 P 的坐標則是以 armHinge 與 bucketHinge位置為圓心,armHinge 與 bucketHinge 的長度為半徑的兩個圓的交點,而且這兩個圓的圓心在挖斗旋轉的過程中是不斷變化的,所以需要通過數學計算不斷算出交點的位置,以下為示意圖:

    通過上圖可以知道交點的位置有兩個 p1 以及 p2,程序中通過計算圓心 1 與圓心 2 構成的向量 c2ToC1,以下為偽代碼:

    1 var Vector2 = ht.Math.Vector2;
    2 var c2ToC1 = new Vector2({ x: c1.x, y: c1.y }).sub(new Vector2({ x: c2.x, y: c2.y }));

    c1 和 c2 為 armHinge 以及 bucketHinge 的圓心坐標,接下來是計算圓心 2 與點 p1 以及 p2 構成的向量 c2ToP1 以及 c2ToP2,以下為偽代碼:

    1 var Vector2 = ht.Math.Vector2;
    2 var c2ToP1 = new Vector2({ x: p1.x, y: p1.y }).sub(new Vector2({ x: c2.x, y: c2.y }));
    3 var c2ToP2 = new Vector2({ x: p2.x, y: p2.y }).sub(new Vector2({ x: c2.x, y: c2.y }));

    通過上述操作我們可以獲得三個向量 c2ToC1c2ToP1c2ToP2 所以我們可以用到我上述講的向量叉乘的概念進行 p1 與 p2 點的選取,通過向量 c2ToC1 與 c2ToP1,以及向量 c2ToC1 與 c2ToP2 分別進行叉乘得到的結果肯定一個是大於 0 一個小於 0,二維向量的叉乘可以直接把它們視為 3d 向量,z軸補 0 的三維向量,不過二維向量叉乘的結果 result 不是向量而是數值,如果 result > 0 時,那麼 a 正旋轉到 b 的角度為 <180°,如果 k < 0,那麼 a 正旋轉到 b 的角度為 >180°,如果 k = 0 那麼a,b向量平行,所以通過上面的理論知識我們可以知道結果肯定是一個大於 0 一個小於 0,我們可以在程序中測下可以知道我們需要獲取的是大於 0 的那個點 P1,所以每次可以通過上述的方法進行兩個交點的選擇。

    以下為挖斗部分動畫的執行流程圖:

    通過上述運算之後我們可以獲取到最終需要的點 P 坐標,點 P 坐標即為挖斗與小臂連接部分的一個重要點,獲取該點之後我們可以通過 HT 中提供的 lookAtX 函數來實現接下來的操作,lookAtX 函數的作用為讓某個物體看向某一點,使用方式如下:

    1 node.lookAtX(position, 'bottom');

    node 即為需要看向某一個點的節點,position 為看向的點的坐標,第二個參數有六個枚舉值可以選擇,分別為 ‘bottom’,’back’,’front’,’top’,’right’,’left’,第二個參數的作用是當我們需要把某個物體看向某一個點的時候我們也要指定該物體的哪一個面看向該點,所以需要提供第二個參數來明確,獲取到該函數之後我們可以通過將 bucketHinge 看向點 P,armHinge 看向點 P,就可以保持這兩個連接的設備永遠朝向該點,以下為部分偽代碼:

    1 bucketHinge.lookAtX(P, 'front');
    2 armHinge.lookAtX(P, 'bottom');

    所以通過上述操作之後我們已經把挖斗部分的兩個關鍵零件的位置已經擺放正確,接下來是要正確的擺放與挖斗連接的小臂上液壓部分的位置,下一部分為介紹該節點如何進行擺放。

    液壓聯動分析

    在場景中我們可以看到液壓主要分為兩個部分,一部分為白色的較細的液壓桿,一部分為黑色的較厚的液壓桿,白色的液壓桿插在黑色的液壓桿中,所以在小臂或者挖斗旋轉的過程中我們要保持兩個節點始終保持相對的位置,通過上一步驟中我們可以知道 lookAtX 這個函數的作用,所以在液壓桿部分我們也是照樣用該函數來實現。

    在上一步我們獲取到了挖斗旋轉過程中的關鍵點 P,所以在挖斗旋轉的過程我們小臂上的液壓桿也要相應的進行變化,具體的操作就是將小臂的白色液壓桿的位置設置為上步中計算出來的點 P 的位置,當然需要把白色液壓桿的錨點進行相應的設置,之後讓白色液壓桿 lookAt 黑色液壓桿,同時讓黑色液壓桿 lookAt 白色液壓桿,這樣下來兩個液壓桿都在互相看着對方,所以它們呈現出來的效果就是白色液壓桿在黑色液壓桿中進行伸縮,以下為偽代碼:

    1 bucketWhite.p3(P);
    2 bucketWhite.lookAtX(bucketBlack.p3(), 'top');
    3 bucketBlack.lookAtX(P, 'bottom');

    代碼中 bucketWhite 節點即為小臂上白色液壓桿,bucketBlack 節點為小臂上黑色液壓桿,通過以上的設置就可以實現伸縮的動畫效果,以下為液壓的運行圖:

    同理挖機身上的大臂的液壓動作以及機身與大臂連接部分的液壓動作都是使用上面的方法來實現,以下為這兩部分的代碼:


     1 rotateBoom: (rotateVal) = >{
     2     excavatorBoomNode.setRotationX(dr * rotateVal);
     3     let archorVector = [0.5 - 0.5, 0.56 - 0.5, 0.22 - 0.5];
     4     let pos = projectUtil.toWorldPosition(g3d, excavatorBoomNode, archorVector);
     5     boomWhite.lookAtX(boomBlack.p3(), 'bottom');
     6     boomBlack.lookAtX(pos, 'top');
     7 },
     8 rotateArm: (rotateVal) = >{
     9     projectUtil.applyRelativeRotation(excavatorArmNode, excavatorBoomNode, -rotateVal);
    10     let archorVector = [0.585 - 0.5, 0.985 - 0.5, 0.17 - 0.5];
    11     let pos = projectUtil.toWorldPosition(g3d, excavatorArmNode, archorVector);
    12     armWhite.lookAtX(armBlack.p3(), 'bottom');
    13     armBlack.lookAtX(pos, 'top');
    14 }


    我將兩部分的運動封裝為兩個函數 rotateBoom 以及 rotateArm 分別是大臂與機身連接處的液壓運動與大臂上的液壓運動,在該部分中為了精確的獲取看向的點,我通過 toWorldPosition 方法將相對坐標轉化為世界坐標,相對坐標為黑白液壓桿的錨點坐標,轉化為相對大臂或者機身的世界坐標。

    基本運動分析

    挖機的基本運動包括前進後退,機身旋轉,這一部分會相對上面的運動簡單許多,在 HT 的三維坐標系中,不斷修改挖機機身的 x,y,z 的坐標值就可以實現挖機的前進後退,通過修改機身的 y 軸旋轉角度則可以控制機身的旋轉,當然挖機身體上的所有其它零部件需要吸附在機身身上,當機身進行旋轉時其它零部件則會進行相應的旋轉,在進行前進的時候挖機底部的履帶會進行對應的滾動,當然履帶我們這邊是用了一個履帶的貼圖貼在上面,當挖機前進的時候修改貼圖的偏移值就可以實現履帶的滾動,修改偏移值的偽代碼如下:

    1 node.s('shape3d.uv.offset', [x, y]);

    上面的 x,y 分別為 x 軸與 y 軸方向的偏移值,在挖機前進後退的過程中不斷修改 y 的值可以實現履帶的滾動效果,具體的文檔說明可以查看 

    在挖機前進後退的過程中我們可以 wasd 四個鍵同時按下,並且可以對按鍵進行一直的響應,在 js 中可以通過 document.addEventListener(‘keydown’, (e) => {}) 以及 document.addEventListener(‘keyup’, (e) => {}) 進行監聽,但是這隻能每次執行一次需要執行的動作,所以我們可以在外部起一個定時器,來執行 keydown 時候需要不斷執行的動作,可以用一個 keyMap 來記錄當前已經點擊的按鍵,在 keydown 的時候紀錄為 true 在 keyup 的時候記錄為 false,所以我們可以在定時器中判斷這個 bool 值,當為 true 的時候則執行相應的動作,否則不執行,以下為對應的部分關鍵代碼:


     1 let key_pressed = {
     2     65 : {
     3         status: false,
     4         action: turnLeft
     5     },
     6     87 : {
     7         status: false,
     8         action: goAhead
     9     },
    10     68 : {
    11         status: false,
    12         action: turnRight
    13     },
    14     83 : {
    15         status: false,
    16         action: back
    17     },
    18     37 : {
    19         status: false,
    20         action: bodyTurnLeft
    21     },
    22     39 : {
    23         status: false,
    24         action: bodyTurnRight
    25     }
    26 };
    27 setInterval(() = >{
    28     for (let key in key_pressed) {
    29         let {
    30             status,
    31             action
    32         } = key_pressed[key];
    33         if (status) {
    34             action();
    35         }
    36     }
    37 },
    38 50);
    39 document.addEventListener('keydown', (event) = >{
    40     let keyCode = event.keyCode;
    41     key_pressed[keyCode] && (key_pressed[keyCode].status = true);
    42     event.stopPropagation();
    43 },
    44 true);
    45 document.addEventListener('keyup', (event) = >{
    46     let keyCode = event.keyCode;
    47     key_pressed[keyCode] && (key_pressed[keyCode].status = false);
    48     event.stopPropagation();
    49 },
    50 true);


    從上面代碼可以看出我在 key_pressed 變量中記錄對應按鍵以及按鍵對應的 action 動作,在 keydown 與 keyup 的時候對應修改當前 key 的 status 的狀態值,所以可以在 Interval 中根據 key_pressed 這個變量的 status 值執行對應的 action 動作,以下為執行流程圖:

    HT 的輕量化,自適應讓當前系統在手機端也能流暢的運行,當然目前移動端與電腦端的 2D 圖紙部分是加載不同的圖紙,在移動端的 2D 部分只留下操作挖機的操作部分,其它部分進行了相應的捨棄,不然在移動端小屏幕下無法展示如此多的數據,在 3D 場景部分都是共用同一個場景,通過場景搭建部分的批量操作使得 3D 在手機端也十分流暢的運行,以下為手機端運行截圖:

    總結

    物聯網已經融入了現代生活,通過內嵌到机械設備中的电子設備,我們能夠完成對机械設備的運轉、性能的監控,以及對机械設備出現的問題進行及時的預警。在該系統 2D 面板監控部分就是對採集過來的數據進行可視化的展示,而且我們可以藉助大數據和物聯網技術,將一台台机械通過機載控制器、傳感器和無線通訊模塊,與一個龐大的網絡連接,每揮動一鏟、行動一步,都形成數據痕迹。大數據精準描繪出基礎建設開工率等情況,成為觀察固定資產投資等經濟變化的風向標。所以在實現上述挖機動作之後,通過與挖機傳感器進行連接之後,可以將挖掘機此時的真實動作通過數據傳遞到系統,系統則會根據動作進行相應的真實操作,真正實現了挖機與網絡的互聯互通。

    程序運行截圖:

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※為什麼 USB CONNECTOR 是電子產業重要的元件?

    網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

    ※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

    ※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

    新北清潔公司,居家、辦公、裝潢細清專業服務

  • 自動任務調度 – Timer

    自動任務調度 – Timer

    一、概述:

    最近維護一個老項目,裏面使用的是Timer的時間調度器,以前沒接觸過,對着代碼鼓搗了半天,查閱了部分博客,最後總結出自己的見解,新項目一般是不會用這種老掉牙的時間調度器了,但是維護老項目還是用的着的。就當筆記記錄一下了,自己寫的才是符合自己的思路走向的。有時間再補上Quartz調度器,這個才是現在使用最多的。

    二、常用的三種調度器分類

    Java自帶的java.util.Timer類,這個類允許你調度一個java.util.TimerTask任務。使用這種方式可以讓你的程序按照某一個頻度執行,但不能在指定時間運行。

    使用Quartz,這是一個功能比較強大的的調度器,可以讓你的程序在指定時間執行,也可以按照某一個頻度執行,配置起來稍顯複雜。

    Spring3.0以後自帶的task,可以將它看成一個輕量級的Quartz,而且使用起來比Quartz簡單許多。

    三、使用Spring體系來完成代碼的搭建

    1、代碼結構:

                                      

     

     

     

    2、springContext.xml文件

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"
           default-lazy-init="true">
    
        <!--定義了一個TimerFactoryBean類,並且把ScheduledTimerTask類的實例作為需要調度的task。-->
        <bean id="timerFactory" class="org.springframework.scheduling.timer.TimerFactoryBean" lazy-init="false">
            <property name="scheduledTimerTasks">
                <list>
                    <ref local="scheduledTask1"/>
                    <ref local="scheduledTask2"/>
                </list>
            </property>
        </bean>
    
        <!--利用ScheduledTimerTask類來配置每個task的啟動時間延時,每次啟動之間的間隔,當然還有最重要的是需要運行那個對象,也就是MethodInvokingTimerTaskFactoryBean類的實例-->
        <bean id="scheduledTask1" class="org.springframework.scheduling.timer.ScheduledTimerTask">
            <property name="delay" value="0" />
            <property name="period" value="1000" />
            <property name="timerTask">
                <ref bean="methodInvokingTask1"/>
            </property>
        </bean>
    
        <bean id="scheduledTask2" class="org.springframework.scheduling.timer.ScheduledTimerTask">
            <property name="delay" value="0" />
            <property name="period" value="1000" />
            <property name="timerTask">
                <ref bean="methodInvokingTask2"/>
            </property>
        </bean>
    
        <!--利用spring提供的MethodInvokingTimerTaskFactoryBean類來實現來實現對對task類和方法的聲明,聲明目標對象和方法,從而使spring知道要運行那個類的那個方法-->
        <bean id="methodInvokingTask1" class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">
            <property name="targetObject" ref="myTask1"/>
            <property name="targetMethod" value="run"/>
        </bean>
    
        <bean id="methodInvokingTask2" class="org.springframework.scheduling.timer.MethodInvokingTimerTaskFactoryBean">
            <property name="targetObject" ref="myTask2"/>
            <property name="targetMethod" value="run"/>
        </bean>
    
        <!--被指定自動任務的類對象-->
        <bean id="myTask1" class="com.turtle.test.MyTask">
            <property name="name" value="啟動一"/>
        </bean>
    
        <bean id="myTask2" class="com.turtle.test.MyTask_2">
            <property name="name" value="啟動二"/>
        </bean>
    
    </beans>

     

    3、MyTask文件

    package com.turtle.test;
    
    import java.util.TimerTask;
    
    /**
     * 自定義一個定時任務
     * 推薦是繼承自 TimerTask
     */
    public class MyTask extends TimerTask {
    
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        private static int i = 0;
    
        // 使用線程中的方法  run
        @Override
        public void run() {
            System.out.println("定時任務啟動"+name+"----出現了"+i++);
        }
    }

     

    4、MyTask_2文件

    package com.turtle.test;
    
    import java.util.TimerTask;
    
    /**
     * 自定義一個定時任務
     * 推薦是繼承自 TimerTask
     */
    public class MyTask_2 extends TimerTask {
    
        private String name;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        private static int i = 0;
    
        // 使用線程中的方法  run
        @Override
        public void run() {
            System.out.println("定時任務啟動"+name+"----出現了"+i++);
        }
    }

     

     

    5、MyTestTask_Test_01

    package com.turtle.test;
    
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;
    
    public class MyTestTask_Test_01 {
        public static void main(String[] args) {
            // 啟動測試
            ApplicationContext applicationContext = new ClassPathXmlApplicationContext("springContext.xml");
        }
    }

     

     

    6、結果:

     

                            

    四、總結:

    如果要使用TImer的調度器的話,推薦使用新的ScheduledExecutorService,這個目前沒使用,就沒進行代碼驗證了,推薦一博客,大概看了下,寫得挺好的

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

    ※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

    ※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

    ※評比南投搬家公司費用收費行情懶人包大公開

    ※幫你省時又省力,新北清潔一流服務好口碑

  • Spring Boot 2.X(十六):應用監控之 Spring Boot Actuator 使用及配置

    Spring Boot 2.X(十六):應用監控之 Spring Boot Actuator 使用及配置

    Actuator 簡介

    Actuator 是 Spring Boot 提供的對應用系統的自省和監控功能。通過 Actuator,可以使用數據化的指標去度量應用的運行情況,比如查看服務器的磁盤、內存、CPU等信息,系統的線程、gc、運行狀態等等。

    Actuator 通常通過使用 HTTP 和 JMX 來管理和監控應用,大多數情況使用 HTTP 的方式。

    Actuator 端點說明

    端點 描述
    auditevents 獲取當前應用暴露的審計事件信息
    beans 獲取應用中所有的 Spring Beans 的完整關係列表
    caches 獲取公開可以用的緩存
    conditions 獲取自動配置條件信息,記錄哪些自動配置條件通過和沒通過的原因
    configprops 獲取所有配置屬性,包括默認配置,显示一個所有 @ConfigurationProperties 的整理列版本
    env 獲取所有環境變量
    flyway 獲取已應用的所有Flyway數據庫遷移信息,需要一個或多個 Flyway Bean
    liquibase 獲取已應用的所有Liquibase數據庫遷移。需要一個或多個 Liquibase Bean
    health 獲取應用程序健康指標(運行狀況信息)
    httptrace 獲取HTTP跟蹤信息(默認情況下,最近100個HTTP請求-響應交換)。需要 HttpTraceRepository Bean
    info 獲取應用程序信息
    integrationgraph 显示 Spring Integration 圖。需要依賴 spring-integration-core
    loggers 显示和修改應用程序中日誌的配置
    logfile 返回日誌文件的內容(如果已設置logging.file.name或logging.file.path屬性)
    metrics 獲取系統度量指標信息
    mappings 显示所有@RequestMapping路徑的整理列表
    scheduledtasks 显示應用程序中的計劃任務
    sessions 允許從Spring Session支持的會話存儲中檢索和刪除用戶會話。需要使用Spring Session的基於Servlet的Web應用程序
    shutdown 關閉應用,要求endpoints.shutdown.enabled設置為true,默認為 false
    threaddump 獲取系統線程轉儲信息
    heapdump 返回hprof堆轉儲文件
    jolokia 通過HTTP公開JMX bean(當Jolokia在類路徑上時,不適用於WebFlux)。需要依賴 jolokia-core
    prometheus 以Prometheus服務器可以抓取的格式公開指標。需要依賴 micrometer-registry-prometheus

    Actuator 使用及配置

    快速使用

    項目依賴

    <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!-- actuator -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
    </dependencies>

    配置文件

    management.endpoints.enabled-by-default=true
    #啟動所有端點
    management.endpoints.web.exposure.include=*
    #自定義管理端點路徑
    #management.endpoints.web.base-path=/manage

    Spring Boot 2.X 中,Actuator 默認只開放 health 和 info 兩個端點。

    添加management.endpoints.web.exposure.include=*配置后啟動應用,訪問 http://127.0.0.1:8080/actuator 我們可以看到所有的 Actuator 端點列表。

    如果將management.endpoints.enabled-by-default設置為false,則禁用所有端點,如需啟用則如下:

    management.endpoints.enabled-by-default=false
    management.endpoint.info.enabled=true

    禁用的端點將從應用程序上下文中完全刪除。如果只想更改公開端點,使用include和exclude屬性。使用如下:

    management.endpoints.web.exposure.include=*
    management.endpoints.web.exposure.exclude=env,beans

    management.endpoints.web.base-path=/manage 配置表示將 /actuator 路徑重定義為 /manage。

    常用端點詳解

    health

    主要用來檢測應用的運行狀況,是使用最多的一個監控點。監控軟件通常使用該接口實時監測應用運行狀況,在系統出現故障時把報警信息推送給相關人員,如磁盤空間使用情況、數據庫和緩存等的一些健康指標。
    默認情況下 health 端點是開放的,訪問 http://127.0.0.1:8080/actuator/health 即可看到應用運行狀態。

    {"status":"UP"}

    如果需要看到詳細信息,則需要做添加配置:

    management.endpoint.health.show-details=always

    訪問返回信息如下:

    {"status":"UP","details":{"diskSpace":{"status":"UP","details":{"total":180002725888,"free":8687988736,"threshold":10485760}}}}

    info

    查看應用信息是否在 application.properties 中配置。如我們在項目中配置是:

    info.app.name=Spring Boot Actuator Demo
    info.app.version=v1.0.0
    info.app.description=Spring Boot Actuator Demo

    啟動項目,訪問 http://127.0.0.1:8080/actuator/info 返回信息如下:

    {"app":{"name":"Spring Boot Actuator Demo","version":"v1.0.0","description":"Spring Boot Actuator Demo"}}

    env

    通過 env 可以獲取到所有關於當前 Spring Boot 應用程序的運行環境信息,如:操作系統信息(systemProperties)、環境變量信息、JDK 版本及 ClassPath 信息、當前啟用的配置文件(activeProfiles)、propertySources、應用程序配置信息(applicationConfig)等。

    可以通過 http://127.0.0.1:8080/actuator/env/{name} ,name表示想要查看的信息,可以獨立显示。

    beans

    訪問 http://127.0.0.1:8080/actuator/beans 返回部分信息如下:

    {
        "contexts": {
            "Spring Boot Actuator Demo": {
                "beans": {
                    "endpointCachingOperationInvokerAdvisor": {
                        "aliases": [
                        ],
                        "scope": "singleton",
                        "type": "org.springframework.boot.actuate.endpoint.invoker.cache.CachingOperationInvokerAdvisor",
                        "resource": "class path resource [org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.class]",
                        "dependencies": [
                            "environment"
                        ]
                    },
                    "defaultServletHandlerMapping": {
                        "aliases": [
                        ],
                        "scope": "singleton",
                        "type": "org.springframework.web.servlet.HandlerMapping",
                        "resource": "class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]",
                        "dependencies": [
                        ]
                    },
                    ...
                }
            }
        }
    }

    從返回的信息中我們可以看出主要展示了 bean 的別名、類型、是否單例、類的地址、依賴等信息。

    conditions

    通過 conditions 可以在應用運行時查看代碼了某個配置在什麼條件下生效,或者某個自動配置為什麼沒有生效。

    訪問 http://127.0.0.1:8080/actuator/conditions 返回部分信息如下:

    {
        "contexts": {
            "Spring Boot Actuator Demo": {
                "positiveMatches": {
                    "SpringBootAdminClientAutoConfiguration": [
                        {
                            "condition": "OnWebApplicationCondition",
                            "message": "@ConditionalOnWebApplication (required) found 'session' scope"
                        },
                        {
                            "condition": "SpringBootAdminClientEnabledCondition",
                            "message": "matched"
                        }
                    ],
                    "SpringBootAdminClientAutoConfiguration#metadataContributor": [
                        {
                            "condition": "OnBeanCondition",
                            "message": "@ConditionalOnMissingBean (types: de.codecentric.boot.admin.client.registration.metadata.CompositeMetadataContributor; SearchStrategy: all) did not find any beans"
                        }
                    ],
                    ...
                }
            }
        }
    }

    loggers

    獲取系統的日誌信息。

    訪問 http://127.0.0.1:8080/actuator/loggers 返回部分信息如下:

    {
        "levels": [
            "OFF",
            "ERROR",
            "WARN",
            "INFO",
            "DEBUG",
            "TRACE"
        ],
        "loggers": {
            "ROOT": {
                "configuredLevel": "INFO",
                "effectiveLevel": "INFO"
            },
            "cn": {
                "configuredLevel": null,
                "effectiveLevel": "INFO"
            },
            "cn.zwqh": {
                "configuredLevel": null,
                "effectiveLevel": "INFO"
            },
            "cn.zwqh.springboot": {
                "configuredLevel": null,
                "effectiveLevel": "INFO"
            },
            ...
        }
    }

    mappings

    查看所有 URL 映射,即所有 @RequestMapping 路徑的整理列表。

    訪問 http://127.0.0.1:8080/actuator/mappings 返回部分信息如下:

    {
        "contexts": {
            "Spring Boot Actuator Demo": {
                "mappings": {
                    "dispatcherServlets": {
                        "dispatcherServlet": [
                            {
                                "handler": "ResourceHttpRequestHandler [class path resource [META-INF/resources/], class path resource [resources/], class path resource [static/], class path resource [public/], ServletContext resource [/], class path resource []]",
                                "predicate": "/**/favicon.ico",
                                "details": null
                            },
                            ...
                        ]
                    }
                }
            }
        }
    }

    heapdump

    訪問:http://127.0.0.1:8080/actuator/heapdump會自動生成一個 GZip 壓縮的 Jvm 的堆文件 heapdump,我們可以使用 JDK 自帶的 Jvm 監控工具 VisualVM 打開此文件查看。如圖:

    VisualVM下載:https://visualvm.github.io/download.html

    threaddump

    獲取系統線程的轉儲信息,主要展示了線程名、線程ID、線程的狀態、是否等待鎖資源等信息。在工作中,我們可以通過查看線程的情況來排查相關問題。

    訪問 http://127.0.0.1:8080/actuator/threaddump 返回部分信息如下:

    {
        "threads": [
            {
                "threadName": "DestroyJavaVM",
                "threadId": 40,
                "blockedTime": -1,
                "blockedCount": 0,
                "waitedTime": -1,
                "waitedCount": 0,
                "lockName": null,
                "lockOwnerId": -1,
                "lockOwnerName": null,
                "inNative": false,
                "suspended": false,
                "threadState": "RUNNABLE",
                "stackTrace": [
                ],
                "lockedMonitors": [
                ],
                "lockedSynchronizers": [
                ],
                "lockInfo": null
            },
            ...
        ]
    }

    shutdown

    開啟可以接口關閉 Spring Boot 應用,要使用這個功能需要做如下配置:

    management.endpoint.shutdown.enabled=true

    可以通過 post(僅支持 post) 請求訪問 http://127.0.0.1:8080/actuator/shutdown 關閉應用。

    metrics

    訪問 http://127.0.0.1:8080/actuator/metrics 可以獲取系統度量指標信息項如下:

    {
        "names": [
            "jvm.memory.max",
            "jvm.threads.states",
            "jvm.gc.pause",
            "http.server.requests",
            "process.files.max",
            "jvm.gc.memory.promoted",
            "system.load.average.1m",
            "jvm.memory.used",
            "jvm.gc.max.data.size",
            "jvm.memory.committed",
            "system.cpu.count",
            "logback.events",
            "tomcat.global.sent",
            "jvm.buffer.memory.used",
            "tomcat.sessions.created",
            "jvm.threads.daemon",
            "system.cpu.usage",
            "jvm.gc.memory.allocated",
            "tomcat.global.request.max",
            "tomcat.global.request",
            "tomcat.sessions.expired",
            "jvm.threads.live",
            "jvm.threads.peak",
            "tomcat.global.received",
            "process.uptime",
            "tomcat.sessions.rejected",
            "process.cpu.usage",
            "tomcat.threads.config.max",
            "jvm.classes.loaded",
            "jvm.classes.unloaded",
            "tomcat.global.error",
            "tomcat.sessions.active.current",
            "tomcat.sessions.alive.max",
            "jvm.gc.live.data.size",
            "tomcat.threads.current",
            "process.files.open",
            "jvm.buffer.count",
            "jvm.buffer.total.capacity",
            "tomcat.sessions.active.max",
            "tomcat.threads.busy",
            "process.start.time"
        ]
    }

    對應訪問 names 中的指標,可以查看具體的指標信息。如訪問 http://127.0.0.1:8080/actuator/metrics/jvm.memory.used 返回信息如下:

    {
        "name": "jvm.memory.used",
        "description": "The amount of used memory",
        "baseUnit": "bytes",
        "measurements": [
            {
                "statistic": "VALUE",
                "value": 1.16828136E8
            }
        ],
        "availableTags": [
            {
                "tag": "area",
                "values": [
                    "heap",
                    "nonheap"
                ]
            },
            {
                "tag": "id",
                "values": [
                    "Compressed Class Space",
                    "PS Survivor Space",
                    "PS Old Gen",
                    "Metaspace",
                    "PS Eden Space",
                    "Code Cache"
                ]
            }
        ]
    }

    示例代碼

    參考文檔

    https://docs.spring.io/spring-boot/docs/2.2.1.RELEASE/reference/html/production-ready-features.html

    非特殊說明,本文版權歸 所有,轉載請註明出處.

    原文標題:Spring Boot 2.X(十六):應用監控之 Spring Boot Actuator 使用及配置

    原文地址:

    如果文章對您有幫助,請掃碼關注下我的公眾號,文章持續更新中…

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※帶您來了解什麼是 USB CONNECTOR  ?

    ※自行創業 缺乏曝光? 下一步"網站設計"幫您第一時間規劃公司的門面形象

    ※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

    ※綠能、環保無空污,成為電動車最新代名詞,目前市場使用率逐漸普及化

    ※廣告預算用在刀口上,網站設計公司幫您達到更多曝光效益

    ※教你寫出一流的銷售文案?

  • go中的數據結構-切片slice

    go中的數據結構-切片slice

    1. 部分基本類型

      go中的類型與c的相似,常用類型有一個特例:byte類型,即字節類型,長度為,默認值是0;

    1 bytes = [5]btye{'h', 'e', 'l', 'l', 'o'}

      變量bytes的類型是[5]byte,一個由5個字節組成的數組。它的內存表示就是連起來的5個字節,就像C的數組。

    1.1 字符串

      字符串在Go語言內存模型中用一個2字長(64位,32位內存布局方式下)的數據結構表示。它包含一個指向字符串數據存儲地方的指針,和一個字符串長度數據如下圖:

      s是一個string類型的字符串,因為string類型不可變,對於多字符串共享同一個存儲數據是安全的。切分操作str[i:j]會得到一個新的2字長結構t,一個可能不同的但仍指向同一個字節序列(即上文說的存儲數據)的指針和長度數據。所以字符串切分不涉及內存分配或複製操作,其效率等同於傳遞下標。

    1.2 數組

      數組是內置(build-in)類型,是一組同類型數據的集合,它是值類型,通過從0開始的下標索引訪問元素值。數組類型定義了長度和元素類型。如, [4]int 類型表示一個四個整數的數組,其長度是固定的,長度是數組類型的一部分( [4]int 和 [5]int 是完全不同的類型)。 數組可以以常規的索引方式訪問,表達式 s[n] 訪問數組的第 n 個元素。數組不需要顯式的初始化;數組的零值是可以直接使用的,數組元素會自動初始化為其對應類型的零值。

    1  var a [4]int
    2  a[0] = 1
    3  i := a[0]
    4  // i == 1
    5  // a[2] == 0, int 類型的零值
    6 [5] int {1,2}  //長度為5的數組,其元素值依次為:1,2,0,0,0 。在初始化時沒有指定初值的元素將會賦值為其元素類型int的默認值0,string的默認值是"" 
    7 [...] int {1,2,3,4,5}  //長度為5的數組,其長度是根據初始化時指定的元素個數決定的 
    8 [5] int { 2:1,3:2,4:3}  //長度為5的數組,key:value,其元素值依次為:0,0,1,2,3。在初始化時指定了2,3,4索引中對應的值:1,2,3 
    9 [...] int {2:1,4:3}  //長度為5的數組,起元素值依次為:0,0,1,0,3。由於指定了最大索引4對應的值3,根據初始化的元素個數確定其長度為5賦值與使用

      Go的數組是值語義。一個數組變量表示整個數組,它不是指向第一個元素的指針(不像 C 語言的數組)。 當一個數組變量被賦值或者被傳遞的時候,實際上會複製整個數組。 (為了避免複製數組,你可以傳遞一個指向數組的指針,但是數組指針並不是數組。) 可以將數組看作一個特殊的struct,結構的字段名對應數組的索引,同時成員的數目固定。

    b := [2]string{"Penn", "Teller"}
    b := [...]string{"Penn", "Teller"}

      這兩種寫法, b 都是對應 [2]string 類型。

    2. 切片slice 

    2.1 結構

      切片類型的寫法是[]T ,T是切片元素的類型。和數組不同的是,切片類型並沒有給定固定的長度。切片的字面值和數組字面值很像,不過切片沒有指定元素個數,切片可以通過數組來初始化,也可以通過內置函數make()初始化。

    letters := []string{"a", "b", "c", "d"}   //直接初始化切片,[]表示是切片類型,{"a", "b", "c", "d"},初始化值依次是a,b,c,d.其cap=len=4
    s := letters [:]  //初始化切片s,是數組letters的引用(a slice referencing the storage of x)
    func make([]T, len, cap) []T    //使用內置函數 make 創建
    s :=make([]int,len,cap)    //通過內置函數make()初始化切片s,[]int 標識為其元素類型為int的切片
    s := arr[startIndex:endIndex]   //將arr中從下標startIndex到endIndex-1 下的元素創建為一個新的切片
    s := arr[startIndex:]   //缺省endIndex時將表示一直到arr的最後一個元素
    s := arr[:endIndex]   //缺省startIndex時將表示從arr的第一個元素開始
    s1 := s[startIndex:endIndex]   //通過切片s初始化切片s1

      slice可以從一個數組或一個已經存在的slice中再次聲明。slice通過array[i:j]來獲取,其中i是數組的開始位置,j是結束位置,但不包含array[j],它的長度是j-i

    1 var ar = [10]byte{'a','b','c','d','e','f','g','h','i','j'}   // 聲明一個含有10個元素元素類型為byte的數組
    2 var a, b []byte  // 聲明兩個含有byte的slice
    3 a = ar[2:5]  //現在a含有的元素: ar[2]、ar[3]和ar[4]
    4  
    5 // b是數組ar的另一個slice
    6 b = ar[3:5]// b的元素是:ar[3]和ar[4]

      一個slice是一個數組某個部分的引用。在內存中它是一個包含三個域的結構體:指向slice中第一個元素的指針ptr,slice的長度數據len,以及slice的容量cap。長度是下標操作的上界,如x[i]中i必須小於長度。容量是分割操作的上界,如x[i:j]中j不能大於容量。slice在Go的運行時庫中就是一個C語言動態數組的實現,在$GOROOT/src/pkg/runtime/runtime.h中定義:

    struct    Slice
    {    // must not move anything
        byte*    array;        // actual data
        uintgo    len;        // number of elements
        uintgo    cap;        // allocated number of elements
    };

      數組的slice會創建一份新的數據結構,包含一個指針,一個指針和一個容量數據。如同分割一個字符串,分割數組也不涉及複製操作,它只是新建了一個結構放置三個數據。如下圖:

      示例中,對[]int{2,3,5,7,11}求值操作會創建一個包含五個值的數組,並設置x的屬性來描述這個數組。分割表達式x[1:3]不重新分配內存數據,只寫了一個新的slice結構屬性來引用相同的存儲數據。上例中,長度為2–只有y[0]和y[1]是有效的索引,但是容量為4–y[0:4]是一個有效的分割表達式。

      因為slice分割操作不需要分配內存,也沒有通常被保存在堆中的slice頭部,這種表示方法使slice操作和在C中傳遞指針、長度對一樣廉價。

    2.2 擴容

      其實slice在Go的運行時庫中就是一個C語言動態數組的實現,要增加切片的容量必須創建一個新的、更大容量的切片,然後將原有切片的內容複製到新的切片。在對slice進行append等操作時,可能會造成slice的自動擴容。其擴容時的大小增長規則是:

    • 如果新的大小是當前大小2倍以上,則大小增長為新大小
    • 否則循環以下操作:如果當前大小小於1024,按每次2倍增長,否則每次按當前大小1/4增長。直到增長的大小超過或等於新大小。

      下面的例子將切片 s 容量翻倍,先創建一個2倍 容量的新切片 t ,複製 s 的元素到 t ,然後將 t 賦值給 s : 

    t := make([]byte, len(s), (cap(s)+1)*2) // +1 in case cap(s) == 0
    for i := range s {
            t[i] = s[i]
    }
    s = t

      循環中複製的操作可以由 copy 內置函數替代,返回複製元素的數目。此外, copy 函數可以正確處理源和目的切片有重疊的情況。

    一個常見的操作是將數據追加到切片的尾部。必要的話會增加切片的容量,最後返回更新的切片:

    func AppendByte(slice []byte, data ...byte) []byte {
        m := len(slice)
        n := m + len(data)
        if n > cap(slice) { // if necessary, reallocate
            // allocate double what's needed, for future growth.
            newSlice := make([]byte, (n+1)*2)
            copy(newSlice, slice)
            slice = newSlice
        }
        slice = slice[0:n]
        copy(slice[m:n], data)
        return slice
    }

      Go提供了一個內置函數 append,也實現了這樣的功能。

    func append(s []T, x ...T) []T
    //append 函數將 x 追加到切片 s 的末尾,並且在必要的時候增加容量。
    a := make([]int, 1)
    // a == []int{0}
    a = append(a, 1, 2, 3)
    // a == []int{0, 1, 2, 3}

      如果是要將一個切片追加到另一個切片尾部,需要使用 ... 語法將第2個參數展開為參數列表。

    a := []string{"John", "Paul"}
    b := []string{"George", "Ringo", "Pete"}
    a = append(a, b...) // equivalent to "append(a, b[0], b[1], b[2])"
    // a == []string{"John", "Paul", "George", "Ringo", "Pete"}

      由於切片的零值 nil 用起來就像一個長度為零的切片,我們可以聲明一個切片變量然後在循環 中向它追加數據:

    // Filter returns a new slice holding only
    // the elements of s that satisfy fn()
    func Filter(s []int, fn func(int) bool) []int {
        var p []int // == nil
        for _, v := range s {
            if fn(v) {
                p = append(p, v)
            }
        }
        return p
    }

    3. 使用切片需要注意的陷阱

      切片操作並不會複製底層的數組。整個數組將被保存在內存中,直到它不再被引用。 有時候可能會因為一個小的內存引用導致保存所有的數據。

      如下, FindDigits 函數加載整個文件到內存,然後搜索第一個連續的数字,最後結果以切片方式返回。

    var digitRegexp = regexp.MustCompile("[0-9]+")
    
    func FindDigits(filename string) []byte {
        b, _ := ioutil.ReadFile(filename)
        return digitRegexp.Find(b)
    }

      這段代碼的行為和描述類似,返回的 []byte 指向保存整個文件的數組。因為切片引用了原始的數組, 導致 GC 不能釋放數組的空間;只用到少數幾個字節卻導致整個文件的內容都一直保存在內存里。要修復整個問題,可以將需要的數據複製到一個新的切片中:

    func CopyDigits(filename string) []byte {
        b, _ := ioutil.ReadFile(filename)
        b = digitRegexp.Find(b)
        c := make([]byte, len(b))
        copy(c, b)
        return c
    }

      使用 append 實現一個更簡潔的版本:

        8  func CopyDigitRegexp(filename string) []byte {
        7     b,_ := ioutil.ReadFile(filename)
        6     b = digitRefexp.Find(b)
        5     var c []intb
        4    // for _,v := range b{
        3         c =append(c, b)
        2     //}
        1     return c
        0  }

    4. make和new

    Go有兩個數據結構創建函數:make和new,也是兩種不同的內存分配機制。

    make和new的基本的區別是new(T)返回一個*T,返回的是一個指針,指向分配的內存地址,該指針可以被隱式地消除引用)。而make(T, args)返回一個普通的T。通常情況下,T內部有一些隱式的指針。所以new返回一個指向已清零內存的指針,而make返回一個T類型的結構。更詳細的區別在後面內存分配的學習里研究。

    5. 數組和切片的區別

    • 數組長度不能改變,初始化后長度就是固定的;切片的長度是不固定的,可以追加元素,在追加時可能使切片的容量增大。
    • 結構不同,數組是一串固定數據,切片描述的是截取數組的一部分數據,從概念上說是一個結構體。
    • 初始化方式不同,如上。另外在聲明時的時候:聲明數組時,方括號內寫明了數組的長度或使用...自動計算長度,而聲明slice時,方括號內沒有任何字符。
    • unsafe.sizeof的取值不同,unsafe.sizeof(slice)返回的大小是切片的描述符,不管slice里的元素有多少,返回的數據都是24。unsafe.sizeof(arr)的值是在隨着arr的元素的個數的增加而增加,是數組所存儲的數據內存的大小。

      unsafe.sizeof總是在編譯期就進行求值,而不是在運行時,這意味着,sizeof的返回值可以賦值給常量。  在編譯期求值,還意味着可以獲得數組所佔的內存大小,因為數組總是在編譯期就指明自己的容量,並且在以後都是不可變的。

      unsafe.sizeof(string)時大小始終是16,不論字符串的len有多大,sizeof始終返回16,這是因為字符串類型對應一個結構體,該結構體有兩個域,第一個域是指向該字符串的指針,第二個域是字符串的長度,每個域佔8個字節,但是並不包含指針指向的字符串的內容。

    6. nil

      按照Go語言規範,任何類型在未初始化時都對應一個零值:布爾類型是false,整型是0,字符串是””,而指針,函數,interface,slice,channel和map的零值都是nil。

    interface

      一個interface在沒有進行初始化時,對應的值是nil。也就是說var v interface{},此時v就是一個nil。在底層存儲上,它是一個空指針。與之不同的情況是,interface值為空。比如:

    1 var v *T
    2 var i interface{}
    3 i = v

      此時i是一個interface,它的值是nil,但它自身不為nil。

    string

      string的空值是””,它是不能跟nil比較的。即使是空的string,它的大小也是兩個機器字長的。slice也類似,它的空值並不是一個空指針,而是結構體中的指針域為空,空的slice的大小也是三個機器字長的。

    channel

      channel跟string或slice有些不同,它在棧上只是一個指針,實際的數據都是由指針所指向的堆上面。

      跟channel相關的操作有:初始化/讀/寫/關閉。channel未初始化值就是nil,未初始化的channel是不能使用的。下面是一些操作規則:

    • 讀或者寫一個nil的channel的操作會永遠阻塞。
    • 讀一個關閉的channel會立刻返回一個channel元素類型的零值。
    • 寫一個關閉的channel會導致panic。

    map

      map也是指針,實際數據在堆中,未初始化的值是nil。

     

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    ※為什麼 USB CONNECTOR 是電子產業重要的元件?

    網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

    ※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

    ※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

    新北清潔公司,居家、辦公、裝潢細清專業服務

  • 通俗地說邏輯回歸【Logistic regression】算法(二)sklearn邏輯回歸實戰

    通俗地說邏輯回歸【Logistic regression】算法(二)sklearn邏輯回歸實戰

    前情提要:

    上一篇主要介紹了邏輯回歸中,相對理論化的知識,這次主要是對上篇做一點點補充,以及介紹sklearn 邏輯回歸模型的參數,以及具體的實戰代碼。

    1.邏輯回歸的二分類和多分類

    上次介紹的邏輯回歸的內容,基本都是基於二分類的。那麼有沒有辦法讓邏輯回歸實現多分類呢?那肯定是有的,還不止一種。

    實際上二元邏輯回歸的模型和損失函數很容易推廣到多元邏輯回歸。比如總是認為某種類型為正值,其餘為0值。

    舉個例子,要分類為A,B,C三類,那麼就可以把A當作正向數據,B和C當作負向數據來處理,這樣就可以用二分類的方法解決多分類的問題,這種方法就是最常用的one-vs-rest,簡稱OvR。而且這種方法也可以方便得推廣到其他二分類模型中(當然其他算法可能有更好的多分類辦法)。

    另一種多元邏輯回歸的方法是Many-vs-Many(MvM),它會選擇一部分類別的樣本和另一部分類別的樣本來做邏輯回歸二分類。

    聽起來很不可思議,但其實確實是能辦到的。比如數據有A,B,C三個分類。

    我們將A,B作為正向數據,C作為負向數據,訓練出一個分模型。再將A,C作為正向數據,B作為負向數據,訓練出一個分類模型。最後B,C作為正向數據,C作為負向數據,訓練出一個模型。

    通過這三個模型就能實現多分類,當然這裏只是舉個例子,實際使用中有其他更好的MVM方法。限於篇幅這裏不展開了。

    MVM中最常用的是One-Vs-One(OvO)。OvO是MvM的特例。即每次選擇兩類樣本來做二元邏輯回歸。

    對比下兩種多分類方法,通常情況下,Ovr比較簡單,速度也比較快,但模型精度上沒MvM那麼高。MvM則正好相反,精度高,但速度上比不過Ovr。

    2.邏輯回歸的正則化

    所謂正則化,其目的是為了減弱邏輯回歸模型的精度,難道模型的準確度不是越高越好嘛?看看下面這張圖就明白了:

    左邊那個圖就是過擬合的情況,過擬合其實就是模型的精度太過高了,它能非常好得匹配訓練集的數據,但一旦有新的數據,就會表現得很差。

    而我們要的非過擬合的模型是,精度可以差一些,但泛化性能,也就是對新的數據的識別能力,要比較好。

    正則化就是減弱模型精度,提高泛化效果的這個東西。

    3.sklearn各個參數

    def LogisticRegression(penalty='l2', 
                                        dual=False, 
                                        tol=1e-4, 
                                        C=1.0,
                                        fit_intercept=True, 
                                        intercept_scaling=1, 
                                        class_weight=None,
                                        random_state=None, 
                                        solver='warn', 
                                        max_iter=100,
                                        multi_class='warn', 
                                        verbose=0, 
                                        warm_start=False, 
                                        n_jobs=None,
                                        l1_ratio=None
                                        )
    跟線性回歸一比,邏輯回歸的參數那還真是多啊,不過我們一個一個來看看參數都是什麼意思吧。                                 
    
    - dual:對偶或者原始方法,布爾類型,默認為False。Dual只適用於正則化相為l2的‘liblinear’的情況,通常樣本數大於特徵數的情況下,默認為False。
    
    - tol:停止迭代求解的閾值,單精度類型,默認為1e-4。
    
    - C:正則化係數的倒數,必須為正的浮點數,默認為 1.0,這個值越小,說明正則化效果越強。換句話說,這個值越小,越訓練的模型更泛化,但也更容易欠擬合。
    
    - fit_intercept:是否要使用截距(在決策函數中使用截距),布爾類型,默認為True。
    
    - intercept_scaling:官方解釋比較模糊,我說下個人理解。浮點型,默認值是1.0。這個參數僅在“solver”參數(下面介紹)為“liblinear”“fit_intercept ”參數為True的時候生效。作用是給特徵向量添加一個常量,這個常量就是intercept_scaling。比如原本的向量是[x],那麼添加后就變成[x,intercept_scaling]。
    
    - class_weight:分類權重,可以是一個dict(字典類型),也可以是一個字符串"balanced"字符串。默認是None,也就是不做任何處理,而"balanced"則會去自動計算權重,分類越多的類,權重越低,反之權重越高。也可以自己輸出一個字典,比如一個 0/1 的二元分類,可以傳入{0:0.1,1:0.9},這樣 0 這個分類的權重是0.1,1這個分類的權重是0.9。這樣的目的是因為有些分類問題,樣本極端不平衡,比如網絡攻擊,大部分正常流量,小部分攻擊流量,但攻擊流量非常重要,需要有效識別,這時候就可以設置權重這個參數。
    
    - random_state:設置隨機數種子,可以是int類型和None,默認是None。當"solver"參數為"sag"和"liblinear"的時候生效。
    
    - verbose:輸出詳細過程,int類型,默認為0(不輸出)。當大於等於1時,輸出訓練的詳細過程。僅當"solvers"參數設置為"liblinear"和"lbfgs"時有效。
    
    - warm_start:設置熱啟動,布爾類型,默認為False。若設置為True,則以上一次fit的結果作為此次的初始化,如果"solver"參數為"liblinear"時無效。
    
    - max_iter:最大迭代次數,int類型,默認-1(即無限制)。注意前面也有一個tol迭代限制,但這個max_iter的優先級是比它高的,也就如果限制了這個參數,那是不會去管tol這個參數的。
    

    OK,上述就是對一些比較簡略的參數的說明,但是還有幾個重要的參數沒講到,這是因為這幾個參數我覺得需要單獨拎出來講一講。

    sklearn邏輯回歸參數 –penalty

    正則化類型選擇,字符串類型,可選’l1’,’l2’,’elasticnet’和None,默認是’l2’,通常情況下,也是選擇’l2’。這個參數的選擇是會影響到參數’solver’的選擇的,下面會介紹。

    其中’l1’和’l2’。分別對應L1的正則化和L2的正則化,’elasticnet’則是彈性網絡(這玩意我也不大懂),默認是L2的正則化。

    在調參時如果主要的目的只是為了解決過擬合,一般penalty選擇L2正則化就夠了。但是如果選擇L2正則化發現還是過擬合,即預測效果差的時候,就可以考慮L1正則化。另外,如果模型的特徵非常多,我們希望一些不重要的特徵係數歸零,從而讓模型係數稀疏化的話,也可以使用L1正則化。

    penalty參數的選擇會影響我們損失函數優化算法的選擇。即參數solver的選擇,如果是L2正則化,那麼4種可選的算法{‘newton-cg’,‘lbfgs’,‘liblinear’,‘sag’}都可以選擇。但是如果penalty是L1正則化的話,就只能選擇‘liblinear’了。這是因為L1正則化的損失函數不是連續可導的,而{‘newton-cg’,‘lbfgs’,‘sag’}這三種優化算法時都需要損失函數的一階或者二階連續導數。而‘liblinear’並沒有這個依賴。最後還有一個’elasticnet’,這個只有solver參數為’saga’才能選。

    sklearn邏輯回歸參數 –solver

    優化算法參數,字符串類型,一個有五種可選,分別是”newton-cg”,”lbfgs”,”liblinear”,”sag”,”saga。默認是”liblinear”。分別介紹下各個優化算法:

    • a) liblinear:使用了開源的liblinear庫實現,內部使用了坐標軸下降法來迭代優化損失函數。
    • b) lbfgs:擬牛頓法的一種,利用損失函數二階導數矩陣即海森矩陣來迭代優化損失函數。
    • c) newton-cg:也是牛頓法家族的一種,利用損失函數二階導數矩陣即海森矩陣來迭代優化損失函數。
    • d) sag:即隨機平均梯度下降,是梯度下降法的變種,和普通梯度下降法的區別是每次迭代僅僅用一部分的樣本來計算梯度,適合於樣本數據多的時候。
      在優化參數的選擇上,官方是這樣建議的:
    • e)saga:優化的,無偏估計的sag方法。(‘sag’ uses a Stochastic Average Gradient descent, and ‘saga’ uses its improved, unbiased version named SAGA.)
      對小的數據集,可以選擇”liblinear”,如果是大的數據集,比如說大於10W的數據,那麼選擇”sag”和”saga”會讓訓練速度更快。

    對於多分類問題,只有newton-cg,sag,saga和lbfgs能夠處理多項損失(也就是MvM的情況,還記得上面說到的多分類嘛?),而liblinear僅處理(OvR)的情況。啥意思,就是用liblinear的時候,如果是多分類問題,得先把一種類別作為一個類別,剩餘的所有類別作為另外一個類別。一次類推,遍歷所有類別,進行分類。

    這個的選擇和正則化的參數也有關係,前面說到”penalty”參數可以選擇”l1″,”l2″和None。這裏’liblinear’是可以選擇’l1’正則和’l2’正則,但不能選擇None,’newton-cg’,’lbfgs’,’sag’和’saga’這幾種能選擇’l2’或no penalty,而’saga’則能選怎’elasticnet’正則。好吧,這部分還是挺繞的。

    歸納一下吧,二分類情況下,數據量小,一般默認的’liblinear’的行,數據量大,則使用’sag’。多分類的情況下,在數據量小的情況下,追求高精度,可以用’newton-cg’或’lbfgs’以’MvM’的方式求解。數據量一大還是使用’sag’。

    當然實際情況下還是要調參多次才能確定參數,這裏也只能給些模糊的建議。

    sklearn邏輯回歸參數 –multi_class

    multi_class參數決定了我們分類方式的選擇,有 ovr和multinomial兩個值可以選擇,默認是 ovr。
    ovr即前面提到的one-vs-rest(OvR),而multinomial即前面提到的many-vs-many(MvM)。如果是二元邏輯回歸,ovr和multinomial並沒有任何區別,區別主要在多元邏輯回歸上。

    4.sklearn實例

    實例這部分,就直接引用sklearn官網的,使用邏輯回歸對不同種類的鳶尾花進行分類的例子吧。

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn import linear_model, datasets
    
    # 加載鳶尾花數據
    iris = datasets.load_iris()
    # 只採用樣本數據的前兩個feature,生成X和Y
    X = iris.data[:, :2]  
    Y = iris.target
    
    h = .02  # 網格中的步長
    
    # 新建模型,設置C參數為1e5,並進行訓練
    logreg = linear_model.LogisticRegression(C=1e5)
    logreg.fit(X, Y)
    
    # 繪製決策邊界。為此我們將為網格 [x_min, x_max]x[y_min, y_max] 中的每個點分配一個顏色。
    x_min, x_max = X[:, 0].min() - .5, X[:, 0].max() + .5
    y_min, y_max = X[:, 1].min() - .5, X[:, 1].max() + .5
    xx, yy = np.meshgrid(np.arange(x_min, x_max, h), np.arange(y_min, y_max, h))
    Z = logreg.predict(np.c_[xx.ravel(), yy.ravel()])
    
    # 將結果放入彩色圖中
    Z = Z.reshape(xx.shape)
    plt.figure(1, figsize=(4, 3))
    plt.pcolormesh(xx, yy, Z, cmap=plt.cm.Paired)
    
    # 將訓練點也同樣放入彩色圖中
    plt.scatter(X[:, 0], X[:, 1], c=Y, edgecolors='k', cmap=plt.cm.Paired)
    plt.xlabel('Sepal length')
    plt.ylabel('Sepal width')
    
    plt.xlim(xx.min(), xx.max())
    plt.ylim(yy.min(), yy.max())
    plt.xticks(())
    plt.yticks(())
    
    plt.show()

    運行上面那段代碼會有如下的結果:

    可以看到,已將三種類型的鳶尾花都分類出來了。

    小結

    邏輯回歸算是比較簡單的一種分類算法,而由於簡單,所以也比較適合初學者初步接觸機器學習算法。學習了之後,對後面一些更複雜的機器學習算法,諸如Svm,或更高級的神經網絡也能有一個稍微感性的認知。

    而實際上,Svm可以看作是邏輯回歸的更高級的演化。而從神經網絡的角度,邏輯回歸甚至可以看作一個最初級,最淺層的神經網絡。

    邏輯回歸就像是金庸小說裏面,獨孤九劍的第一式,最為簡單,卻又是其他威力極大的招式的基礎,其他的招式都又第一式演化而出。

    夯實基礎,才能砥礪前行。

    以上~

    參考文章:

    本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

    【其他文章推薦】

    USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

    ※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

    ※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

    ※評比南投搬家公司費用收費行情懶人包大公開

    ※幫你省時又省力,新北清潔一流服務好口碑