跳至主要内容

Docker 入門實戰教學:如何使用 Docker Compose 建置 Python Flask + Redis 記數器

· 閱讀時間約 6 分鐘

Docker101

身為一個開發者最惱人的莫過於環境建置和部屬應用程式。隨著 Docker 容器和虛擬化技術進步以及 DevOps、Infrastructure as Code 文化的推廣,讓我們可以更容易在不同環境開發部屬並調度(Orchestration)我們的專案應用程式。在 Docker 中,除了 Docker 指令和 Docker Engine 背後的技術外,最重要的莫過於 Docker Machine、Docker Compose 和 Docker Swarm 三劍客了。接下來我們將透過 Docker Compose 來啟動並執行 Python Flask + Redis 網頁人數統計的專案,讓讀者能夠理解 Docker Compose 的優勢和使用方式。那就讓我們開始吧!

Docker101

Docker Compose 簡介

一開始我們先了解 Docker Compose 是一個工具可以讓你可以透過一個指令就可以控制所有專案(project)中所需要的 services。Docker Compose 是用 YAML 檔案格式來描述和定義 project 中 services 運作關係,白話來說就是用來管理 Container 的文件檔。

什麼意思呢?

試想一下,我們在開發一個典型的 Web project 時通常不是只有一個 service,有可能需要 app server、database、cache,甚至是 reverse proxy 等 service 才能構成一個可以上線運行的專案,這些 service 往往會需要多個 container 來運行。此時若是使用 Docker CLI 需要手動輸入多少行才能正式啟動一個 project?這時候就是 Docker Compose 發揮功能的時候啦!

我們先來看看,一個基本的 docker-compose.yml 檔案長這樣(YAML 檔案格式,使用空格來縮排,附檔名為 .yml):

version: '3' # 目前使用的版本,可以參考官網:
services: # services 關鍵字後面列出 web, redis 兩項專案中的服務
web:
build: . # Build 在同一資料夾的 Dockerfile(描述 Image 要組成的 yaml 檔案)成 container
ports:
- "5000:5000" # 外部露出開放的 port 對應到 docker container 的 port
volumes:
- .:/code # 要從本地資料夾 mount 掛載進去的資料
links:
- redis # 連結到 redis,讓兩個 container 可以互通網路
redis:
image: redis # 從 redis image build 出 container

Dockerfile 和 Docker Compose 的差異是?

在了解到 Docker Compose 主要是用來描述 Service 之間的相依性和調度方式後,我們來看看同樣初學者會比較容易搞混的觀念:Dockerfile。事實上 Dockerfile 是用來描述映像檔(image)的文件。

所謂的 Image,就是生產 Container 的模版,你可以從 Docker Hub 官方下載或是根據官方的 Image 自己加工後打包成 Image 或是完全自己使用 Dockerfile 描述 Image 內容來製作 Image。而 Container 則是透過 Image 產生隔離的執行環境,稱之為 Container,也就是我們一般用來提供 microservice 的最小單位。

# 這是一個創建 ubuntu 並安裝 nginx 的 image
FROM ubuntu:16.04 # 從 Docker hub 下載基礎的 image,可能是作業系統環境或是程式語言環境,這邊是 ubuntu 16.04
MAINTAINER demo@gmail.com # 維護者

RUN apt-get update # 執行 CMD 指令跑的指令,更新 apt 套件包資訊
RUN apt-get install –y nginx # 執行 CMD 指令跑的指令,安裝 nginx
CMD ["echo", "Nginx Image created"]

以上為簡單的 Dockerfile。我們可以看到,只需一個文字檔,就清楚描述一個 Docker image。利於使用版本控制,也可以減少 shell script 的工作量。

透過 Docker 建立 Python Pageview App

在建立了 Dockerfile 和 Docker Compose 的基礎觀念後,我們來透過一個簡單 Python Flask + Redis 網頁人數統計的專案讓讀者可以更深刻理解 Docker Compose 的威力。

環境準備: Lniux/MacOS 為主 可以輸入指令的終端機(若為 windows 可以使用 cmder) 到官網安裝 Docker 基本 Docker 和 Web 知識

  1. 創建專案資料夾
$ mkdir docker-compose-python-flask-redis-counter
$ cd docker-compose-python-flask-redis-counter
  1. 在資料夾下建立 app.py 當做 web app 進入點,裡面有 flask 和 redis 操作,當使用者瀏覽首頁時,redis 會記錄次數,若有 exception 則有 retry 機制
import time
import redis
from flask import Flask

app = Flask(__name__)
cache = redis.Redis(host='redis', port=6379)

def get_hit_count():
retries = 5
while True:
try:
return cache.incr('hits')
except redis.exceptions.ConnectionError as exc:
if retries == 0:
raise exc
retries -= 1
time.sleep(0.5)


@app.route('/')
def get_index():
count = get_hit_count()
return 'Yo! 你是第 {} 次瀏覽\n'.format(count)

if __name__ == "__main__":
app.run(host="0.0.0.0", debug=True)
  1. 建立套件 requirements.txt 安裝資訊讓 Dockerfile 可以下指令安裝套件

    flask
    redis
  2. 建立 Web App 的 Dockerfile

    FROM python:3.4-alpine # 從 python3.4 基礎上加工
    ADD . /code # 將本地端程式碼複製到 container 裡面 ./code 資料夾
    WORKDIR /code # container 裡面的工作目錄
    RUN pip install -r requirements.txt
    CMD ["python", "app.py"]
  3. 用 Docker Compose file 描述 services 運作狀況,我們的專案共有 web 和 redis 兩個 service

    version: '3'
    services:
    web:
    build: .
    ports:
    - "5000:5000"
    volumes:
    - .:/code # 把當前資料夾 mount 掛載進去 container,這樣你可以直接在本地端專案資料夾改動檔案,container 裡面的檔案也會更動也不用重新 build image!
    redis:
    image: "redis:alpine" # 從 Docker Hub registry 來的 image
  4. 用 Docker Compose 執行你的 Web app(-d detached 是在背景執行,可以使用 $ docker ps -a 觀看目前所有 docker container 狀況,使用 $ docker-compose ps 觀看 docker-compose process 狀況)

    $ docker-compose up -d

    若要終止並移除 container 則可以使用 $ docker-compose down

  5. http://127.0.0.1:5000/ 觀看成果

Docker101

總結

以上透過 Docker Compose 來啟動並執行 Python Flask + Redis 網頁人數統計的專案,讓讀者能夠理解 Docker Compose 的優勢和使用方式(Docker Compose 是一個工具可以讓你可以透過一個指令就可以控制所有專案(project)中所需要的 services)。同時也複習了 Dockerfile、Docker Image、Container 相關知識。Ya,自從有了 Docker Compose 在本地開發測試專案更加方便,考試都考一百分了!

參考文件

  1. Get started with Docker Compose
  2. 深入淺出 Dockerfile 與 Docker Compose
  3. 部署Docker Compose 實例示範定義檔撰寫
  4. Docker Compose 初步閱讀與學習記錄

(image via cuelogicZabbix

如何在 Windows 打造 Python Web 開發環境入門教學 Part2

· 閱讀時間約 1 分鐘

如何在 Windows 打造 Python Web 開發環境

所謂工欲善其事,必先利其器。我們開發程式之前我們最重要的就是要設定好開發環境,接下來我們將帶領讀者體驗如何在 Windows 打造 Python Web 開發環境。

撰寫第一個 Python Django 程式

  1. 創建虛擬開發環境:conda create -n <自定義虛擬環境名稱> python=3.5
  2. 觀看已建立的虛擬環境:conda info -e
  3. 進入虛擬環境:activate <自定義虛擬環境名稱>
  4. 安裝套件:pip install django
  5. 觀看已安裝套件:pip list
  6. 建立第一個 django 專案:django-admin startproject my_first_app
  7. 啟動伺服器:python manage.py runserver
  8. 到瀏覽器觀看成果!http://localhost:8000http://127.0.0.1:8000

其他常用指令

  1. 離開虛擬環境:deactivate
  2. 移除虛擬環境:conda remove <自定義虛擬環境名稱> -n --all
  3. pip uninstall 套件名稱

影片教學

如何在 Windows 打造 Python Web 開發環境入門教學 Part1

· 閱讀時間約 2 分鐘

如何在 Windows 打造 Python Web 開發環境

所謂工欲善其事,必先利其器。我們開發程式之前我們最重要的就是要設定好開發環境,接下來我們將帶領讀者體驗如何在 Windows 打造 Python Web 開發環境。

安裝軟體步驟

  1. 下載安裝 google chrome 瀏覽器
  2. 下載安裝 Visual Studio CodeSublime text 文字編輯器
  3. 下載安裝 cmder terminal 終端機程式 (請下載含 git 的 full 完整版本)
  4. 下載安裝 anaconda for windows (請依你的作業系統位元 32/64 下載對應程式,記得安裝時要勾選加入環境變數)
  5. 在終端機輸入 (若正確顯示版本即為安裝成功):python -V
  6. 輸入 python 可進入互動式對話環境,可以執行 python 程式

撰寫第一個 Python 程式

  1. 打開 Visual Studio Code 或 Sublime text 並建立一個 hello.py 檔案:
print('hello python')
  1. 到 cmder 終端機移動到 hello.py 資料夾下輸入 python hello.py

就可以看到你撰寫的第一個 Python 程式 hello python 啦!

影片教學

如何在 Windows 打造 JavaScript Web 開發環境入門教學

· 閱讀時間約 2 分鐘

如何在 Windows 打造 JavaScript Web 開發環境

所謂工欲善其事,必先利其器。我們開發程式之前我們最重要的就是要設定好開發環境,接下來我們將帶領讀者體驗如何在 Windows 打造 JavaScript Web 開發環境。

安裝軟體步驟

  1. 下載安裝 google chrome 瀏覽器
  2. 下載安裝 Visual Studio CodeSublime text 文字編輯器
  3. 下載安裝 cmder terminal 終端機程式 (請下載含 git 的 full 完整版本)
  4. 下載安裝 Node.JS 選擇左邊穩定版本,按照指令安裝完成
  5. 在終端機輸入 node -v 若成功顯示版本,代表安裝完成
  6. 安裝 http-server 套件:npm install http-server -g

撰寫第一個 JavaScript 程式

  1. 打開 Visual Studio Code 或 Sublime text 並建立一個 index.html 檔案:

  2. index.html 輸入:

    <!DOCTYPE html>
    <html>
    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>Test</title>
    <script>
    console.log(‘hello JS!);
    </script>
    </head>
    <body>
    </body>
    </html>
  3. 儲存後在終端機移動到該檔案資料夾下,輸入 http-server -p 7777 啟動伺服器

  4. 打開瀏覽器輸入網址:http://127.0.0.1:7777http://localhost:7777

  5. 開發者工具,可以在 console 中看到 hello JS!

  6. 恭喜讀者完成第一個 JavaScript 應用程式啦!

影片教學

自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

· 閱讀時間約 17 分鐘

自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

要成為一個真正的軟體工程師(Software Engineer)除了掌握基礎開發能力外,更重要的是和其他工程師和開發者團隊合作和溝通的能力,所以若你能培養出掌握 Git 等版本控制操作和 Git server 架設的能力,你會更容易參與開放原始碼(open source)的社群和提昇自己在職場上的價值。關於相關環境工具若你還沒準備好,可以參考 如何在 Windows 打造 Python 開發環境設定基礎入門教學 這篇教學文章。好,那我們就準備開始吧!

什麼是版本控制系統(Version Control System)?

自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

版本控制系統是一種軟體工程的開發技巧,可以透過這個系統讓每位成員的軟體版本可以方便同步和維護管理(不然要用 email 或是其他工具傳送和管理十分麻煩,尤其程式又常常會有不同版本修改的問題!)。在沒有版本控制系統時,我們常會在編輯檔案前複製一個備份,或是在更新檔案後產生許多重複檔案,非常不便且難以維護。因此,使用版本控制系統的需求就應運而生啦!

自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

一般在軟體開發中又分為中央式系統(例如:SubversionCVS 等)與分散式系統(例如:GitBitKeepermercurial 等),中央式版本控制系統的工作主要在一個伺服器進行,由中央管理存取權限「鎖上」檔案庫中的檔案,一次只能讓一個開發者進行工作。而分散式系統讓不同開發者直接在各自的本地檔案庫工作,並容許多個開發者同時更動同一個檔案,而每個檔案庫有另外一個合併各個改變的功能。分散式系統讓開發者能在沒有網路的情況下也能繼續工作,也讓開發者有充分的版本控制能力,而不需經中央管理者的許可,但分散式系統仍然可以有檔案上鎖功能。

自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

什麼是 Git?什麼是 Github?

Git 是一個分散式版本控制軟體,最初由 Linus Torvalds 創作(也是作業系統 Linux 系統的開發者),其最初目的是為更好地管理 Linux kernel 開發而設計,其具備優秀的 merge tracing 合併程式碼的能力(使用程式碼 snapshot 來比較歷史版本差異)。

Github 則是一個支援 git 程式碼存取和遠端托管的平台服務,有許多的開放原始碼的專案都是使用 Github 進行程式碼的管理。若是讀者未來有志於從事程式設計相關工作的話,建議可以熟悉掌握 Git 和 Github 的使用,並建立自己的 Github profile 作品集。

Git 基本觀念

自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

Git 可以分為 Local(本地)和 Remote(遠端)兩個環境,由於 Git 屬於分散式的版本控制系統,所以開發者可以在離線 local 環境下開發,等到有網路時再將自己的程式推到 Remote 環境或 pull 下其他開發者程式碼進行整合。在 Local 中我們又分為 working directory(工作資料夾)、staging area(暫存區)和 repositories(檔案庫)。

當自己開發時會在工作資料夾工作,當要進入檔案庫之前會先將檔案加入暫存區,確認沒問題則 commit 到檔案庫中,最後 push 上去 remote 環境。在 Git 中若是有和其他開發者一起合作,則會需要處理不同 branch 之間 conflict 和 merge 的問題。

自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

Git 與 Github 實戰操作入門教學

接下來我們用一個實際的實戰範例讓讀者可以快速的掌握那些基礎必知必會的 Git/Github 操作技能:

  1. 安裝並且設定 Git

    任務 1:安裝 Git 到你的電腦上,並且設定好 Git 內部的使用者名稱和電子信箱

    Linux 若是使用 Debian 基礎的作業系統可以在終端機輸入以下指令安裝 git:

    $ apt-get install git

    若是 Fedora 系列可以輸入:

    $ yum install git-core

    若是 windows 可以下載安裝 cmder 這個模擬 Linux terminal 終端機時選擇完整版本就會順便安裝或是到 Git 官網安裝。當然在市面上有許多免費 GUI 圖形化的 Git 操作軟體,若是初學者則建議先熟悉整個 git 工作模式和指令,再去使用圖形化工具會比較好,這樣你才比較知道圖形化程式背後做了什麼事情。Mac 則是可以到 Git 官方網站 選擇對應作業系統,按照步驟完整下載安裝。另外也可以參考中文安裝教學

    由於我們會選擇 Github 當作遠端托管程式的環境,所以我們也可以根據作業系統安裝 Github 桌面版當作操作工具(內建安裝 Git)。

    自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

    若是安裝完成,打開終端機(terminal)或 cmder 輸入以下指令,若成功顯示版本(建議 Git 版本在 2 以上),代表安裝成功囉!terminal(終端機)是一個可以下指令讓電腦做事情的互動介面(例如:新增檔案、移動到資料夾等)

    // 其中 $ 為提示字元,在輸入指令時不用輸入該符號,否則會錯誤,若是使用 windows cmder 預設是 λ
    $ git --version

    接下來設定你的帳戶,讓 Git 知道這台電腦做的修改要連結到哪一個使用者(待會我們要在 Github 上註冊帳號,建議使用一致的帳號和電子信箱):

    $ git config --global user.name "<Your Name>"

    設定電子郵件:

    $ git config --global user.email "<your@gmail.com>"
  2. 建立一個本機的 repository

    任務二:在自己的電腦上建立一個新的 local repositories(本地檔案庫)

    自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

    repository(檔案庫)是一個什麼樣的概念呢?事實上 repository 就是一個專案,又簡稱 repo。以電腦的檔案資料管理來看,我們通常會把同一個專案的資料放到同一個資料夾下,所以我們也可以把 repository 看成一個資料夾。

    // 建立一個 hello-git 資料夾
    $ mkdir hello-git
    // 移動到 hello-git 資料夾
    $ cd hello-git
    // 將專案資料夾建立成 git repository
    $ git init
    // 列出專案資料夾下的檔案和資料夾(-l 參數為列出詳細資料,-a 為列出隱藏資料夾)
    $ ls -la

    當你執行 git init 後,你可以發現多出了 .git 這個隱藏資料夾,可以看到裡面檔案和資料夾如下:

    自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

    到這邊恭喜讀者,完成你第一個 git 專案資料夾改造計畫!

  3. 檢視狀態、新增或修改 commits

    任務三:在你的 repository 檔案庫中建立一個新檔案,新增一些內容到該檔案並且將那些檔案修改提交 commit 到 Git 中

    接著我們使用文字編輯器,新增一個 hello.py 的檔案(裡面是一個會印出 hello python & git 字串的 python 程式):

    print('hello python & git')

    然後在終端機的專案資料夾下輸入 git status 顯示目前工作環境狀態:

    $ git status
    On branch master

    Initial commit

    Untracked files:
    (use "git add <file>..." to include in what will be committed)

    hello.py

    nothing added to commit but untracked files present (use "git add" to track)

    我們會發現因為我們有新增新的檔案,但是還沒進到 git 追蹤範圍中/暫存區,所以我們要使用 git add hello.py 加入追蹤,這樣之後檔案有修改就可以追蹤到。

    $ git add hello.py
    $ git status
    On branch master

    Initial commit

    Changes to be committed:
    (use "git rm --cached <file>..." to unstage)

    new file: hello.py

    若是確認沒問題我們就準備 commit 進去 repository 囉!

    // 比較現在檔案和上次 commit 之間的差異,也就是說你做了哪些修改
    $ git diff
    // -m 為輸入 commit message,也就是說這個 commit 內做了哪些事情
    $ git commit -m "Init hello.py"
    [master (root-commit) ad6d328] Init hello.py
    1 file changed, 1 insertion(+)
    create mode 100644 hello.py

    // commmit 完成
    $ git status
    On branch master
    nothing to commit, working tree clean

    若是想反悔不想把檔案加入追蹤呢?

    // 檔案尚未加入過追蹤時使用,即可恢復到檔案尚未加入暫存區
    $ git rm --cached hello.py

    // 若檔案已經在 repository 內,則使用以下指令
    // repository 與 stage 的檔案都會被還原到 HEAD,但 working directory 內的檔案不變
    $ git reset HARD

    當你追蹤後修改了檔案,例如把 hello.py 的內容改成:

    print('hello python & git rock')

    若有檔案修改,記得要再 add 修改的檔案(這是新手比較容易忘記的部分),若是要放棄修改可以使用 git checkout -- 檔案名稱

    // 比較現在檔案和上次 commit 之間的差異,也就是說你做了哪些修改
    $ git diff
    // 查看目前工作狀態
    $ git status
    Changes not staged for commit:
    (use "git add <file>..." to update what will be committed)
    (use "git checkout -- <file>..." to discard changes in working directory)

    modified: hello.py

    commit 這個修改時簡寫會寫成這樣(-a 是 add,-m 為 message 簡寫,後面接訊息資訊):

    $ git commit -a -m "修改了 hello.py"
  4. 註冊 GitHub 帳號

    任務四:建立一個 GitHub 帳號,並在 Git 設定中加入使用者帳號

    到目前為主我們程式主要是在我們 local 工作環境中操作,但還記得我們在 Git 基本觀念中有提到,git 分為 local 和 remote,若是我們想要和全世界其他開發者合作或是貢獻開放原始碼的話,我們可以透過 github 來當作我們 remote 工作環境,去管理我們程式碼,同樣的也可以透過 github 平台和其他開發者一起合作,參與開放原始碼的開發。github 若是公開的 repo 是無限制數量免費的,但是若是想使用 private repo 可以參考付費方案

    // 注意大小寫要一致
    $ git config --global user.username <你的 github 使用者名稱>

    先到 github.com 註冊帳號:

    自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

    註冊成功後登入,可以點選右上顯圖下拉式選單進到個人頁面(profile),觀看個人頁面:

    自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

    自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

    點選右上角 + 來新增 new repository(檔案庫):

    自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

    輸入 repository name(你要取的專案名稱),最好跟電腦 local 專案一致,我們這邊輸入 git-example。然後輸入簡短專案描述並先不勾選初始化 README 和,也先不要選擇 .gitignore 和 License 授權(不然會造成本地端和遠端不一致會需要額外一些處理):

    .gitignore:要忽略的檔案清單,這是用來告訴 Git,當在做版本控制記錄的時候,忽略這些檔案。通常一些機密資料,如資料庫帳號密碼或是 server IP 位置等,記得要加入。也可以參考 github 上面的一些範本 在新增 repository 時選取對應的程式語言

    README.md:repository 介紹和使用方式說明(例如:使用方法、參與專案方式等),使用 markdown 語法撰寫。另外通常有 CONTRIBUTING.md 額外說明如何參與貢獻。

    LICENSE:專案使用何種授權方式,例如:MIT、BSD 等

    自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

    接著按 create 按鈕!恭喜你新增成功,創建了自己第一個 github repository(遠端檔案庫)!

  5. 將 repository 做本機和遠端的連結

    任務五:把電腦裡 Local(本地端)的 repository(檔案庫)和 remote(遠端)的 repository(檔案庫)連結起來,並 push 電腦上的修改

    自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

    因我們已經在專案有把 hello.py 修改加入追蹤並 commit 到 local 檔案庫,所以我們可以參考下方的指令說明把 remote 網址加入:

    // 本地端專案知道 origin 對應到遠端網址
    $ git remote add origin <remote 網址>

    接者準備將本地端程式 push 到遠端檔案庫:

    // 觀看情況
    $ git status
    // 將本地端程式 push 到遠端檔案庫
    $ git push -u origin master
    Counting objects: 3, done.
    Writing objects: 100% (3/3), 239 bytes | 0 bytes/s, done.
    Total 3 (delta 0), reused 0 (delta 0)
    To https://github.com/happycodergit/git-example.git
    * [new branch] master -> master
    Branch master set up to track remote branch master from origin.

    參數 -u 等同於 --set-upstream,設定 upstream 可以使分支開始追蹤指定的遠端分支。事實上,只要做過一次 $ git push -u <remote name> <branch name>,並且成功 push 出去;本機端的 master 就會被設定去追蹤遠端的 <remote name>/<branch name> 分支。只要成功設定好 upstream 後,第二次以後要上傳分支時,就只需要透過 git push 就可以了,不必再帶 <remote name><branch name> 等參數。例如:$ git push

    事實上,$ git push -u origin master 可以拆解成:

    $ git push origin master
    $ git checkout master
    $ git branch -u origin/master

    恭喜你成功把你的專案推送上去 github 啦!

    自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

  6. Fork 和 clone 一個 open source(開源)的計畫

    任務六:從 GitHub.com 建立專案,複本 fork,並下載 clone 到電腦上

    點選左上角 github icon 回到首頁,我們從上面搜尋欄搜尋 react:

    自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

    點選右上角 fork 按鈕,複製一份專案到我們這:

    自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

    等待 fork 中:

    自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

    點選右邊綠色按鈕 clone download 複製 HTTP 網址:

    自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

    // 複製到本地端
    $ git clone https://github.com/happycodergit/react.git
    // 移動到 react 資料夾
    $ cd react
    // 切出自己的新分支(使用 -b)
    $ git checkout -b happycoder@feature_branch
    // 做一些 README.md 檔案修改,然後 commit 到自己 fork 過來的專案
    $ git commit -a -m "Update README"
    $ git push origin happycoder@feature_branch

    事實上,每個開放原始碼都有他自己貢獻的方式,記得要先了解。例如可以參考 react 貢獻說明

    自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

    你可以透過將自己的修改 commit 到自己 fork 過來的專案,然後到原始專案頁面點選 new pull request 按鈕發 pull request(會比對程式碼的差異)。若對方 review 完後接受就可以將自己的程式碼合併到原始專案中,為開放原始碼做出第一步貢獻!

    // 若完成 pull request 記得讓 master(或是合併進去的 branch)保持同步
    $ git pull upstream master
  7. 練習建立一個 feature branch

    任務七:回來原來的 git-example 專案新增 feature branch(分支)

    // 建立一個名為 dev 的 branch
    $ git checkout -b dev

    hello.py 最上面多加一行 # hi, this is comment 註解後存檔

    // commit 到本地端更新
    $ git commit -a -m "Init dev branch"
    $ gut push origin dev
  8. 邀請別人和你合作

    任務八:在專案新增夥伴 collaborator

    在右上角進入 setting 可以選擇到 collaborator 新增合作者:

    自學程式設計與電腦科學入門實戰:Git 與 Github 版本控制基本指令與操作入門教學

  9. 利用 push 和 pull 來和 GitHub.com 同步

    任務九:用 pull 來和其他 collaborators(合作者)同步更新,確保程式是最新的版本

    請其他開發者 git colone 下來你的 git-example 專案並 checkout 到 dev branch,並完成新增一個 README.md 檔案後發 pull request 過來,若沒問題就按同意並合併。我們則透過 git pull 來保持本地端和遠端程式碼同步:

    $ git pull origin dev
  10. Merge(合併)和刪除 branches

    任務十:在本機上 merge 合併你的 branch(分支),刪除舊的 branch(分支)

    // 移動到 master branch
    $ git checout master
    // 合併 dev 到 master
    $ git merge dev
    // 刪除 dev branch
    $ git branch -d dev
    // 將合併後的 master 推送到遠端
    $ git push origin master

總結

以上就是 Git 與 Github 版本控制基本指令與操作入門教學!希望讀者可以動手一起操作,漸漸就能感受到 git 的威力和好處,同時也有能力參與開放原始碼(open source)的社群和提昇自己在職場上的價值,朝成為一個真正的軟體工程師(Software Engineer)邁進!

參考文件

  1. 30 天精通 Git 版本控管
  2. Git 官方網站
  3. Try Git
  4. Git-it
  5. GitHub Guides
  6. 如何將檔案從 stage 移除?
  7. Git 教學

(image via git-scmqboxquoracdnytimglinuximgurmartinfitzpatrick

自學程式設計與電腦科學入門實戰:Linux Command 命令列指令與基本操作入門教學

· 閱讀時間約 11 分鐘

自學程式設計與電腦科學入門實戰:Linux Command 命令列指令與基本操作入門教學

要成為一個真正的軟體工程師(Software Engineer)不一定一定要使用 vim 之類的編輯器進行開發,但熟悉使用終端機(terminal)操作和常用的 Linux 命令列指令碼操作則是必須的。因此接著我們將介紹軟體工程師在開發上常用的 Linux 命令列指令碼給讀者參考。若讀者使用的是 Windows 建議安裝 VirtualBox 並在上面跑 Linux/Ubuntu 來進行指令碼操作,或是使用像是 Cmder 的工具來進行操作。關於相關工具安裝可以參考 如何在 Windows 打造 Python 開發環境設定基礎入門教學 這篇教學文章。好,那我們就準備開始吧!

自學程式設計與電腦科學入門實戰:Linux Command 命令列指令與基本操作入門教學

什麼是 Linux?

Linux 是一種自由開放原始碼的類 Unix 的作業系統,其廣泛運用於伺服器和嵌入式系統中。目前主流的 Linux 發佈版本(Linux distributions,係指可完整安裝使用的套件版本)包括:Debian、Fedora、CentOS、Ubuntu 等。以下我們主要將會聚焦在 Linux/Ubuntu 常用指令和基礎操作的入門教學介紹上(每個指令前使用 $ 當作提示字元,不用輸入)。

自學程式設計與電腦科學入門實戰:Linux Command 命令列指令與基本操作入門教學

Linux 檔案系統架構

理論上所有的 Linux 發佈版本應該都要遵守檔案系統的標準(Filesystem Hierarchy Standard, FHS),但根據發佈版本不同或有差異,不過大致上檔案系統架構如下:

  1. /bin, /sbin
    /bin 主要放置一般使用者可以操作的指令,/sbin 放置系統管理員可以操作的指令。連結到 /usr/bin/usr/sbin

  2. /boot
    主要放置開機相關檔案

  3. /dev
    放置 device 裝置檔案,包話滑鼠鍵盤等

  4. /etc
    主要放置系統檔案

  5. /home, /root /home 主要是一般帳戶的家目錄,/root 為系統管理者的家目錄

  6. /lib, /lib64 主要為系統函式庫和核心函式庫,若是 64 位元則放在 /lib64。連結到 /usr/lib, /usr/lib64

  7. /proc 將記憶體內的資料做成檔案類型

  8. /sys 與 /proc 類似,但主要針對硬體相關參數

  9. /usr /usr 全名為 unix software resource 縮寫,放置系統相關軟體、服務(注意不是 user 的縮寫喔!)

  10. /var 全名為 variable,放置一些變數或記錄檔

  11. /tmp 全名為 temporary,放置暫存檔案

  12. /media, /mnt 放置隨插即用的裝置慣用目錄, /mnt 為管理員/使用者手動掛上(mount)的目錄

  13. /opt 全名為 optional,通常為第三方廠商放置軟體處

  14. /run 系統進行服務軟體運作管理處

  15. /srv 通常是放置開發的服務(service),如:網站服務 www

檔案與目錄管理指令

在 Ubuntu 中我們可以打開終端機進行指令操作,就可以透過指令來管理檔案。

一般指令格式如下:

$ 指令 [選項] [選項值]

自學程式設計與電腦科學入門實戰:Linux Command 命令列指令與基本操作入門教學

  1. ls:list,查看檔案及子目錄

    列出基本資料夾資料:

    ls

    列出詳細資料和隱藏資料:

    // -l 列出詳細資料 -a 列出隱藏資料
    $ ls -la

    列出部分檔案:

    // 列出為 .js 的檔案
    $ ls *.js
  2. pwd:print work directory,印出目前工作目錄

    $ pwd
    // /Users/happycoder/Desktop/projects/HappyCoder
  3. cd:change directory,移動進入資料夾

    移動到目前資料夾下的 examples 資料夾:

    $ cd ./examples

    移動到家目錄:~

    $ cd ~

    移動到上一層目錄 ..

    $ cd ..

    移動到根目錄 /

    $ cd /
  4. mkdir:make directory,創建新資料夾

    $ mkdir examples
  5. cp:copy,複製檔案

    先將字串 TEST 存入 README.md 文件中

    $ echo "TEST" > README.md
    $ cp README.md
  6. mv:move (rename) files,移動檔案或是重新命名檔案

    移動檔案:

    $ mv README.md /examples/README.md

    重新命名

    $ mv README.md README_MV.md
  7. rm:remove file,刪除檔案

    $ rm README.md

    刪除目前資料夾下副檔名為 .js 檔案:

    $ rm *.js

    刪除資料夾和所有檔案:

    $ rm -f examples
  8. touch:用來更新已存在文件的 timestamp 時間戳記或是新增空白檔案

    $ touch README.md
  9. cat:將文件印出在終端機上

    $ cat README.md
  10. tail:顯示檔案最後幾行內容

    $ tail README.md

    持續顯示更新內容,常用於 web server 看 log debug 使用:

    $ tail -f README.md
  11. more:將檔案一頁頁印在終端機上

    可以使用上下移動換頁,按 q 離開:

    $ more README.md
  12. file:檢查檔案類型

    $ file README.md
    // README.md: HTML document text, UTF-8 Unicode text

編輯文字檔案

  1. nano:在終端機編輯文字檔案

    編輯或是新增文字檔案:

    $ nano README.md

    啟動編輯完後可以使用 Ctrl + X 離開,Ctrl + V 移動到上一頁,Ctrl + Y 移動到下一頁,Ctrl + W 搜尋文字內容

  2. vim:在終端機編輯文字檔案

    $ vim README.md

    啟動後,使用 i 進入編輯,esc 離開編輯模式,:q 不儲存離開,:wq 儲存離開,:q! 強制離開

檔案權限設定

在 Linux 系統中,每一個 Linux 檔案都具有四種存取權限:

  1. 可讀取(r,Readable),用數字 4 表示
  2. 可寫入(w,writable),用數字 2 表示
  3. 可執行:(x,eXecute),用數字 1 表示
  4. 無權限(-),用數字 0 表示

系統管理者依據使用者需求來設定檔案權限,若我們想檢視檔案權限可以使用 $ ls -l 來查看

自學程式設計與電腦科學入門實戰:Linux Command 命令列指令與基本操作入門教學

  1. 第一欄:使用者權限 由 10 個字元組成,第一個字元表示檔案型態(- 為檔案,d 表示目錄,1 表示連結檔案)。字元 2、3、4 表示檔案擁有者的存取權限。字元 5、6、7 表示檔案擁有者所屬群組成員的存取權限。字元 8、9、10 表示其他使用者的存取權限

    舉例來說 -rwxrwxr--,代表這是一格檔案,擁有者和群組都具備讀取、寫入和執行權限,其他使用者只擁有讀取權限

  2. 第二欄:檔案數量

  3. 第三欄:擁有者

  4. 第四欄:群組

  5. 第五欄:檔案大小

  6. 第六欄:檔案建立時間

  7. 第七欄:檔案名稱

接下來介紹如何透過指令修改權限:

  1. chmod:修改檔案權限

    將權限設為 rw-rw-r--

    $ chmod 664 README.md

    將檔案的使用者和群組加入執行權限

    $ chmod ug+x README.md
  2. chown:修改檔案擁有者與群組

    $ chown www-data:www-data README.md

系統管理

  1. sudo:使用最高權限(superuser)執行指令,會要求輸入自己密碼,使用上必須非常小心

    $ sudo git clone xxx.py
  2. su:su 指令可以讓一般的 Linux 使用者輸入 root 密碼取得 root 權限,暫時取得 root 權限的使用者就如同 root 一樣可以對系統進行各種變更動作

    $ su
  3. kill:根據 Process ID 指定要終止程式

    $ kill PID

    立即強制執行:

    $ kill -9 PID
  4. killall:直接使用程式的名稱來指定要終止的程式

    $ killall hello.py

套件管理

  1. apt-get:套件管理工具

    更新套件資料庫列表:

    $ sudo apt-get update

    升級套件並下載安裝套件:

    $ sudo apt-get upgrade

    搜尋相關軟體套件(使用名稱):

    $ apt-cache search --names-only fortune

    安裝套件:

    $ sudo apt-get install fortune

    移除套件:

    $ sudo apt-get remove fortune

網際網路相關操作

  1. ping:網路檢測工具,透過發送 ICMP ECHO_REQUEST 的封包,檢查自己與特定設備之間的網路是否暢通,速度是否正常

    可輸入 hostname 或是 IP:

    $ ping google.com

    PING google.com (172.217.160.110): 56 data bytes 64 bytes from 172.217.160.110: icmp_seq=0 ttl=57 time=7.037 ms 64 bytes from 172.217.160.110: icmp_seq=1 ttl=57 time=9.411 ms 64 bytes from 172.217.160.110: icmp_seq=2 ttl=57 time=22.690 ms 64 bytes from 172.217.160.110: icmp_seq=3 ttl=57 time=6.561 ms 64 bytes from 172.217.160.110: icmp_seq=4 ttl=57 time=6.909 ms 64 bytes from 172.217.160.110: icmp_seq=5 ttl=57 time=6.311 ms 64 bytes from 172.217.160.110: icmp_seq=6 ttl=57 time=6.860 ms 64 bytes from 172.217.160.110: icmp_seq=7 ttl=57 time=6.583 ms

  2. traceroutes:檢查從你的電腦到網路另一端的主機是走的什麼路徑

    $ traceroute google.com

    traceroute to google.com (172.217.27.142), 64 hops max, 52 byte packets 1 zyxel.home (192.168.1.1) 2.047 ms 1.208 ms 1.888 ms 2 h254.s98.ts.hinet.net (168.95.98.254) 6.189 ms 8.556 ms 5.875 ms 3 168-95-85-2.hinet-ip.hinet.net (168.95.85.2) 7.057 ms 5.796 ms 5.998 ms 4 211-22-226-1.hinet-ip.hinet.net (211.22.226.1) 9.766 ms 10.422 ms 72.14.222.94 (72.14.222.94) 9.744 ms 5 108.170.244.97 (108.170.244.97) 8.386 ms 108.170.244.129 (108.170.244.129) 11.500 ms 12.247 ms 6 209.85.142.13 (209.85.142.13) 7.015 ms 7.505 ms 209.85.240.15 (209.85.240.15) 6.750 ms 7 tsa03s02-in-f142.1e100.net (172.217.27.142) 11.478 ms 6.608 ms 6.893 ms

  3. nslookup:查詢 DNS 回應是否正常

    $ nslookup google.com

    Server: 192.168.1.1 Address: 192.168.1.1#53

    Non-authoritative answer: Name: google.com Address: 216.58.200.238

其他好用指令

  1. man:查詢 Linux 線上手冊(man page)

    $ man

    例如我們可以使用 man 來查詢 ls 的使用用法:

    $ man ls
  2. find:查詢檔案

    在目前目錄下尋找檔名為 README.md 檔案

    $ find . -name README.md
  3. grep:強大文件字串搜尋工具

    $ grep '找這個字串' file_name

    找所有目錄(含子目錄)下檔案

    $ grep -r '字串' *

  4. crontab:例行性工作排程

    編輯 crontab

    $ crontab -e

    crontab 格式:

    分 時 日 月 星期 要執行的指令

    30 12 * * * python /projects/hello.py &

    在 12:30 時執行 hello.py,& 表示背景執行
    * 號表示每日每月每星期都執行

撰寫第一個 shell script

Shell 是我們和 Linux 系統的介面,我們可以透過終端機在上面輸入指令和作業系統互動,讓他做我們想做的事情。在 Linux 中標準的 Shell 為(Bourne Again Shell),檔案路徑為 /bin/sh,我們可以透過 $ echo $SHELL 去印出目前使用的 shell

其中 Shell Script 為使用 shell 所提供的語法所撰寫的程式碼,其為直譯式不用編譯。可以讓你將複雜或是重複性的指令寫成程式碼檔案

$ vim example.sh

在編輯模式輸入以下程式碼,:

#!/bin/bash
# 這是註解,上面所使用的 shell

echo "日期"
date
echo "印出檔案列表"
ls -l

修改權限成可以執行:

$ chmod u+x example.sh

接著執行,若是一切順利就可以在終端機看到時間日期和檔案列表!恭喜你完成你的第一個 shell script!

$ ./example.sh

總結

以上介紹了 Linux/Ubuntu 常用指令和基礎操作的入門教學介紹上,實際上讀者不用刻意去背誦,而是在實際上操作中練習,多累積撰寫程式並使用指令碼去加快程式開發的速度自然而然就會把指令碼記憶起來了,若是真的忘記再去網路上查找就好,加油!

參考文件

  1. 初窥Linux 之 我最常用的20条命令
  2. 【L】Linux 常用指令集
  3. Linux 的 su 與 sudo 指令教學與範例
  4. dig、host 與 nslookup 指令的查詢語法
  5. nslookup — 查詢 DNS 指令
  6. 在 Linux 下使用 find 指令查詢目錄與檔案的速查筆記
  7. grep 搜尋目錄下所有檔案字串
  8. 第十五章、例行性工作排程(crontab)

(image via unixmencloudxlabytimgytimglinuximgur

如何在 Windows 打造 Python 開發環境設定基礎入門教學

· 閱讀時間約 13 分鐘

如何設定開發環境應該是每個初學程式設計者的痛(即便是老手有時也會覺得苦惱),尤其當你需要在終端機(terminal)輸入指令(command)來操控你的指令時(好吧,若你完全只走圖形化介面,習慣 GUI 操作就另當別論,但若你有志於往程式設計領域發展,建議還是熟悉一下指令碼)。

要在 LinuxMac OS 這種屬於類 Unix 系統(指各種 Unix 的衍生系統,而 Unix 指的是一種電腦作業系統,具有多工、多使用者的特色,是許多作業系統的父親)上打造 Python 開發環境相對容易,但當你使用 Windows 作業系統並希望在終端機下指令操作或開發應用程式時,往往受限於環境而產生許多困難和誤踩地雷。因此,接下來本文將教大家如何在 Windows 打造屬於自己的 Python 開發環境(包含一般 Winodows 安裝和使用虛擬機在 Windows 環境下建立 Linux/Ubuntu 作業系統,開發 Python 程式一般建議使用 Linux/Ubuntu 環境避免環境設定除錯困擾)!

開始建置 Python 開發環境

所謂工欲善其事,必先利其器,在開始之前我們必須先建置相關的開發環境,讓自己從麻瓜(不會寫程式的人)變成擁有程式魔力的魔法師。以下介紹我們在接下來開發 Python Web 應用程式所需要安裝的開發環境工具(強烈建議使用 Virtual Box 虛擬機搭配 Linux/Ubuntu 環境,若你真的很想使用 Windows 環境就繼續往下看吧!)。

  1. Microsoft VSCode 編輯器 Microsoft VSCode 是 Microsoft 推出的編輯器(非整合開發環境 IDE),夾帶著 Microsoft 過去打造 Visual studio 整合開發環境的豐富經驗,相比 Sublime Text 和其他編輯器,VSCode 的優勢在於開源且活躍的開發社群、內建 debugger 框架、原生 Git 整合、套件整合容易等特性。綜合以上幾點,對於初學者來說 VSCode 是一個蠻適合入門的開發環境。它的安裝方式也十分簡易,在官網下載後按照指示安裝完成即可,下載完成後可以打開看看。

    title: 如何在 Windows 打造 Python 開發環境設定

    我們可以點選左邊 icon 欄的第五個(長得像正方形拼圖),安裝 Python 語法和格式檢查的相關套件幫助除錯(搜尋 Python),選擇 Python 並點選 install 安裝:

    title: 如何在 Windows 打造 Python 開發環境設定

    你也可以於檔案(file)-> 開啟(open)打開你在電腦中已經準備好的專案資料夾,同時也可以在資料夾中新增檔案,我們之後的程式也會希望在建立好的專案資料夾中進行開發。這邊我們建立一個 hello.py 的檔案並印出 hello 訊息。

    print('hello python')
  2. 終端機環境(iTterm/內建 terminal) terminal(終端機)是我們下指令的地方,許多時候我們進行程式開發時不會使用 GUI 圖形化介面而是使用下指令方式請電腦做相對應的行為(記得寫程式就是下指令請電腦做事情!)。在 Linux 和 Mac 裡面都有內建的 terminal 的應用程式,以下為 MacOS 的 iTerm2 終端機下指令示意圖(iTerm2 中 $ 為提示字元,不用輸入):

    title: 如何在 Windows 打造 Python 開發環境設定

    使用 Windows 讀者可以使用 Cmder 這個軟體當做終端機環境。

    title: 如何在 Windows 打造 Python 開發環境設定

    比起 Winodws 內建的命令列 CMD,cmder 更貼近 Unix 的命令列指令碼:

    title: 如何在 Windows 打造 Python 開發環境設定

    首先到 Cmder 官網先安裝 Cmder Full 版本(含 git),安裝完成後解壓縮資料夾到桌面,執行裡面的 cmder.exe 檔案即可。

    title: 如何在 Windows 打造 Python 開發環境設定

    Cmder 預設是 λ,如果不習慣可以改成 Mac / Linux 環境下的 $,具體流程請參考這份文件

    title: 如何在 Windows 打造 Python 開發環境設定

    對於有志於從事程式開發相關工作的讀者建議可以多熟悉指令碼的輸入,更多指令碼可以參考鳥哥撰寫的 Linux 基本指令介紹Linux 學習資源

    以下是常用指令
    # 移動到桌面
    cd \Users\XXXX\Desktop
    # 列出資料夾下檔案
    ls
    # 刪除檔案
    rm 檔名
    # 複製檔案
    cp 檔名
  3. Git 版本控制系統/註冊 GitHub 帳戶 Git 是一種分散式版本控制系統,可以讓我們可以更方便地管理我們的程式碼。在網路上有非常多優秀的 Git 教學文件(連猴子都能懂的Git入門指南寫給大家的 Git 教學初心者 Git 上手攻略)。安裝 Git 方式是到官網下載軟體,依照指示安裝(若您使用 Cmder 的完整安裝 Download Full 的版本就不用安裝 git,因為已經幫你安裝好了)。

    title: 如何在 Windows 打造 Python 開發環境設定

    互動式語法學習:

    title: 如何在 Windows 打造 Python 開發環境設定

    在介紹完 git 之後我們來了解一下 GitHub。GitHub 是一個可以存放 git 程式碼專案的平台,透過 GitHub 我們可以接觸到最新的開放原始碼資訊,也可以將我們的程式碼開源出來。

    title: 如何在 Windows 打造 Python 開發環境設定

    從 GitHub 上複製程式碼

    # 複製一份到本地端
    $ git clone https://github.com/happycoderorg/python101.git
    # 移動到資料夾
    $ cd python101

    常見 Git 指令:

    # 初始化專案
    $ git init
    # 查看狀態
    $ git status
    # 檢查差異
    $ git diff
    # 將變更檔案放入暫存區
    $ git add index.py
    # 使用 commit -m 提交變更
    $ git -a -m 'init commit'
    # 查看歷史
    $ git log
    # 放棄已經 commit 的檔案重回暫存區
    $ git reset HEAD index.py
    # 放棄檔案變更
    $ git checkout index.py
  4. Anaconda Python3 版本 Anaconda 是一個 all-in-one 的 Python 開發環境,對於初學者來說是個十分合適的開發環境包。Anaconda 具備了幾項特點:

    • 便於安裝許多流行的科學、數學、工程、資料分析的 Python 模組
    • 免費並支援跨平台:Linux、Windows、Mac
    • 內建 Spyder 編輯器和 Jupyter Notebook 環境
    • 方便建立不同的虛擬開發環境

    安裝流程也十分簡單,進入 Anaconda 首頁,選擇對應作業系統(這邊使用 Windows)和是屬於 64 還是 32 位元: title: 如何在 Windows 打造 Python 開發環境設定

    Windows10 可以在系統看到位元資訊; title: 如何在 Windows 打造 Python 開發環境設定

    Windows7 可以在控制台->系統與安全->系統觀看作業系統位元資訊: title: 如何在 Windows 打造 Python 開發環境設定

    選擇對應 Python 版本下載(這裡選擇 Python3 以上版本),我們使用 Graphical Installer(圖像介面安裝方式),接著在下載完成時按照預設的安裝方式完成安裝; title: 如何在 Windows 打造 Python 開發環境設定

    記得安裝時要注意建議在安裝 anaconda 時勾選把環境變數加入(path environment variable),這樣在使用 cmder 時使用 conda 相關指令才不會出現錯誤,若一開始沒有勾選的話建議解除安裝後再重新安裝 anaconda 勾選加入環境變數。

    title: 如何在 Windows 打造 Python 開發環境設定

    若是完整安裝成功,可以打開 Cmder 終端機輸入,若是顯示 Python 3.6.0 :: Anaconda 4.3.0 (x86_64) 版本號即安裝成功(若沒成功可能要檢查一下是不是環境變數路徑的問題):

    $ python -V
    Python 3.6.0 :: Anaconda 4.3.0 (x86_64)

    接著要建立我們專案虛擬環境,這樣在安裝操作套件時比較不容易被污染到 root 全域的環境(因為你可能會有很多專案,專案使用的套件不盡相同,正式上線時只要把相關套件資訊透過 pip freeze > requirements.txt 存起來,然後在正式上線的伺服器安裝 pip install -r requirements.txt 即可),啟動後會出現(套件名稱)的提示字元:

    顯示目前虛擬環境列表
    conda info -e
    創建虛擬環境
    conda create -n 套件名稱 python=3.6
    進入虛擬環境(若是非 Windows cmder 環境加 source 於開頭) ,成功後提示字元變成:(套件名稱)$
    activate 虛擬環境名稱
    離開虛擬環境(若是非 Windows cmder 環境加 source 於開頭)
    deactivate

建立虛擬環境(virtual environment)

接著我們正式來建立一個 Python 的專案,打開終端機移動到桌面,建立專案資料夾(在輸入指令時可以使用 tab 自動補完指令)

# 移動到桌面
cd \Users\XXXX\Desktop
# 建立資料夾
mkdir python_examples
# 移動到資料夾
cd python_examples

建立獨立虛擬環境,並進入虛擬環境:

# 創立虛擬環境
conda create -n python_examples_venv python
# 啟動虛擬環境
activate python_examples_venv

成功進入虛擬環境後(會出現小括號 python_examples_venv)代表已經進入虛擬環境,即可以在裡面執行 Python 程式並安裝相關套件於該虛擬環境下:

# 安裝 django web 框架套件
pip install django
# 執行 python 檔案
python hello.py

事實上,在 Python3 中還有另外兩種建立虛擬開發環境的方式,包括使用 Python 內建工具:

# 使用 Python3 內建工具建立名為 example_venv 的虛擬開發環境
python -m venv example_venv

使用 virtualenv,和 anaconda 不同的是 virtualenv 會在建立虛擬環境的專案資料夾下建立一個資料夾裡面放虛擬環境的東西:

# 先安裝 virtualenv
pip install virtualenv
# 使用 virtualenv 產生一個名為 example_venv 的
virtualenv example_venv
# 移動到 example_venv 的外面資料夾,執行進入虛擬環境
example_venv\Scripts\activate
# 安裝 django web 框架套件到虛擬環境中(只會安裝在該虛擬環境中)
pip install django

整合在一起:在 Windows 撰寫你的第一個 Python 程式

確認安裝好以下工具後,我們就可以開始撰寫你的第一個 Python 程式

  1. 安裝 Microsoft VSCode
  2. 安裝 Cmder
  3. 安裝 Anaconda(記得勾選加入環境變數)
  4. 安裝 virtualenv (在終端機使用:pip install virtualenv 安裝)
  5. 在桌面創建一個 python_example 資料夾,打開 Microsoft VSCode 後開啟該專案資料夾,創建一個 hello.py 的檔案並在裡面打上 print('hello python!!')
  6. 打開 cmder 終端機 cd 移動到 hello.py 所在資料夾
  7. 執行 python hello.py,恭喜你完成第一個 Python 程式!

在 Windows 上安裝 Linux/Ubuntu

  1. 安裝 VirtualBox 對應版本虛擬機(這邊安裝 Windows 版本,若你是 Mac 想嘗試 Linux 也可以安裝 Mac 版本),下載完按照步驟安裝完成

    title: 如何在 Windows 打造 Python 開發環境設定

  2. 官網下載 Linux/Ubuntu 光碟映像檔案,請根據電腦位元架構選擇最新桌面穩定版本 16.04 LTS(for windows)

    title: 如何在 Windows 打造 Python 開發環境設定

  3. 建立 Linux Ubuntu 虛擬機,可以參考這篇 VirtualBox 虛擬機器安裝 Ubuntu 設定教學,設定一下名稱、作業系統類型和版本,欲分配給虛擬的記憶體大小(建議調整為大約實體記憶體的 1/3,舉例來說你有 30G 記憶體,可以分配 10G 給虛擬機)。接著選擇立即建立虛擬硬碟、VDI (VirtualBox 磁碟映像)、動態配置硬碟大小不會造成浪費(虛擬硬碟容量建議 30G 以上)。

    title: 如何在 Windows 打造 Python 開發環境設定

  4. 選擇建立好的虛擬機並選設定值按鈕,選擇存放位置選項,控制器中選擇虛擬 CD/DVD 檔案選擇剛剛從官網下載下來的檔案,確定後接著選擇虛擬機並啟動,接下來選擇安裝 Linux/Ubuntu,選擇立即安裝和預設值,需要一段時間安裝和設定(中間會有語言相關的選擇和密碼設定)

    title: 如何在 Windows 打造 Python 開發環境設定

  5. 啟動使用 Linux/Ubuntu,按照上面教學安裝 Microsoft VSCode 編輯器,安裝 Anaconda,建立第一個 Python 檔案、打開終端機(termical)安裝 ,執行 Python 程式

    title: 如何在 Windows 打造 Python 開發環境設定

網路上也有許多相關參考教學文章:VirtualBox 5.2安裝Ubuntu 16.04 相關教學VirtualBox 虛擬機器安裝 Ubuntu 設定教學

若是螢幕太小可以在上排選單中選擇:裝置->插入 Guest Additions CD 映像...->執行->重開虛擬機->可以調整大小

整合在一起:用 Linux 撰寫你的第一個 Python 程式

確認安裝好以下工具後,我們就可以開始撰寫你的第一個 Python 程式

  1. 進入虛擬機的 Linux/Ubuntu
  2. 安裝 Microsoft VSCode
  3. 安裝 Anaconda(記得勾選加入環境變數)
  4. 安裝 virtualenv (在終端機使用:pip install virtualenv 安裝)
  5. 在桌面創建一個 python_example 資料夾,打開 Microsoft VSCode 後開啟該專案資料夾,創建一個 hello.py 的檔案並在裡面打上 print('hello python!!')
  6. 打開 terminal 終端機 cd 移動到 hello.py 所在資料夾
  7. 執行 python hello.py,恭喜你完成第一個 Python 程式!

總結

如何設定開發環境應該是每個初學程式設計者的痛(強烈建議使用 Virtual Box 虛擬機搭配 Linux/Ubuntu 環境),以上介紹了如何在 Windows 打造 Python 開發環境設定,請讀者務必照著自己的電腦作業系統環境安裝一次,當然若你有志於往程式設計領域發展,也要熟悉一下指令碼操作。

參考文件

  1. VirtualBox 5.2安裝Ubuntu 16.04
  2. Create virtual environments for python with conda
  3. conda vs. pip vs. virtualenv
  4. Anacodna之conda VS Virtualenv VS Python 3 venv 对比使用教程,创建虚拟环境
  5. 命令列指令碼查詢

(image via githubusercontentwebsiteoptimizationytimgytimgostechnix

用 Python 自學資料科學與機器學習入門實戰:Scikit Learn 基礎入門

· 閱讀時間約 17 分鐘

 如何使用 Python 學習機器學習(Machine Learning)

本系列文章將透過 Python 及其資料科學與機器學習生態系(Numpy、Scipy、Pandas、scikit-learn、Statsmodels、Matplotlib、Scrapy、Keras、TensorFlow 等)來系統性介紹資料科學與機器學習相關的知識。在這個單元中我們將介紹 scikit-learn 這個機器學習和資料分析神兵利器和基本的機器學習工作流程。接下來我們的範例將會使用 Ananconda、Python3 和 Jupyter Notebook 開發環境進行,若還沒安裝環境的讀者記得先行安裝。首先我們先來認識一下基本機器學習工作流程,讓讀者對於機器學習工作流有基本而全面的認識。

基本機器學習工作流程(Machine Learning Workflow)

 如何使用 Python 學習機器學習(Machine Learning)

  1. 明確定義問題 (Problem Definition)
  2. 獲取資料與探索性資料分析 (Get Data & Exploratory Data Analysis)
  3. 資料預處理與特徵工程 (Data Clean/Preprocessing & Feature Engineering)
  4. 訓練模型與校調 (Model Training)
  5. 模型驗證 (Model Predict & Testing)
  6. 模型優化 (Model Optimization)
  7. 上線運行 (Deploy Model)

明確定義問題 (Problem Definition)

 如何使用 Python 學習機器學習(Machine Learning)

明確定義問題是進行機器學習工作流的第一步。由於機器學習和一般的 Web 網頁應用程式開發比較不一樣,其需要的運算資源和時間成本比較高,若能一開始就定義好問題並將問題抽象為數學問題將有助於我們要蒐集的資料集和節省工作流程的時間。

舉例來說,本篇文章範例希望預測 Iris 鳶尾花屬於哪一個類別(setosa 山鳶尾、versicolor 變色鳶尾、virginica 維吉尼亞鳶尾),這邊我們就可以決定是要進行有對應結果的監督式學習:二元分類問題(binary classification)、多類別分類問題(multi-classification)還是連續量的迴歸問題(regression),或是沒有標籤結果的非監督式學習(例如:clustering)等,我們這邊假設這是一個多類別分類問題:給定未知資料希望能預測花朵屬於哪一類。換句話說,就是說我們先定義好我們想要解決或是預測的問題,然後去蒐集對應的資料。

獲取資料與探索性資料分析 (Get Data & Exploratory Data Analysis)

 如何使用 Python 學習機器學習(Machine Learning)

基本上資料集的完整性某種程度決定了預測結果是否能發揮模型最大功效。由於我們是教學文章,這邊我們的範例使用 scikit-learn 內建的玩具資料集 Iris(鳶尾花)的花萼、花蕊長寬進行花朵類別判別(setosa 山鳶尾、versicolor 變色鳶尾、virginica 維吉尼亞鳶尾)。在這個資料集中已經幫我們標註好每筆資料對應的類別,所以我們可以視為多類別分類問題(multi-classification)。

 如何使用 Python 學習機器學習(Machine Learning)

引入模組

# 引入 numpy、pd 和 sklearn(scikit-learn) 模組
import numpy as np
import pandas as pd
from sklearn import datasets
# 引入 train_test_split 分割方法,注意在 sklearn v0.18 後 train_test_split 從 sklearn.cross_validation 子模組搬到 sklearn.model_selection 中
from sklearn.model_selection import train_test_split
# 引入 KNeighbors 模型
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import LinearSVC

引入資料集並進行探索性資料分析

# 引入 iris 資料集
raw_iris = datasets.load_iris()
# 探索性分析 Exploratory data analysis,了解資料集內容
# 先印出 key 值,列出有哪些值:['data', 'target', 'target_names', 'DESCR', 'feature_names']
print(raw_iris.keys())

# 印出 feature 值
print(raw_iris['data'])
# 印出目標值,分別對應的是三種花的類別:['setosa 山鳶尾' 'versicolor 變色鳶尾' 'virginica 維吉尼亞鳶尾']
print(raw_iris['target'])
# 印出目標標籤,三種花的類別:['setosa' 'versicolor' 'virginica']
print(raw_iris['target_names'])
# 印出資料集內容描述
print(raw_iris['DESCR'])
# 印出屬性名稱,['sepal length 花萼長度 (cm)', 'sepal width 花萼寬度 (cm)', 'petal length 花蕊長度 (cm)', 'petal width 花蕊寬度 (cm)']
print(raw_iris['feature_names'])

# 類別種類
print(np.unique(raw_iris.target))

dict_keys(['data', 'target', 'target_names', 'DESCR', 'feature_names']) [[ 5.1 3.5 1.4 0.2] [ 4.9 3. 1.4 0.2] [ 4.7 3.2 1.3 0.2] [ 4.6 3.1 1.5 0.2] [ 5. 3.6 1.4 0.2] [ 5.4 3.9 1.7 0.4] [ 4.6 3.4 1.4 0.3] [ 5. 3.4 1.5 0.2] [ 4.4 2.9 1.4 0.2] [ 4.9 3.1 1.5 0.1] [ 5.4 3.7 1.5 0.2] [ 4.8 3.4 1.6 0.2] [ 4.8 3. 1.4 0.1] [ 4.3 3. 1.1 0.1] [ 5.8 4. 1.2 0.2] [ 5.7 4.4 1.5 0.4] [ 5.4 3.9 1.3 0.4] [ 5.1 3.5 1.4 0.3] [ 5.7 3.8 1.7 0.3] [ 5.1 3.8 1.5 0.3] [ 5.4 3.4 1.7 0.2] [ 5.1 3.7 1.5 0.4] [ 4.6 3.6 1. 0.2] [ 5.1 3.3 1.7 0.5] [ 4.8 3.4 1.9 0.2] [ 5. 3. 1.6 0.2] [ 5. 3.4 1.6 0.4] [ 5.2 3.5 1.5 0.2] [ 5.2 3.4 1.4 0.2] [ 4.7 3.2 1.6 0.2] [ 4.8 3.1 1.6 0.2] [ 5.4 3.4 1.5 0.4] [ 5.2 4.1 1.5 0.1] [ 5.5 4.2 1.4 0.2] [ 4.9 3.1 1.5 0.1] [ 5. 3.2 1.2 0.2] [ 5.5 3.5 1.3 0.2] [ 4.9 3.1 1.5 0.1] [ 4.4 3. 1.3 0.2] [ 5.1 3.4 1.5 0.2] [ 5. 3.5 1.3 0.3] [ 4.5 2.3 1.3 0.3] [ 4.4 3.2 1.3 0.2] [ 5. 3.5 1.6 0.6] [ 5.1 3.8 1.9 0.4] [ 4.8 3. 1.4 0.3] [ 5.1 3.8 1.6 0.2] [ 4.6 3.2 1.4 0.2] [ 5.3 3.7 1.5 0.2] [ 5. 3.3 1.4 0.2] [ 7. 3.2 4.7 1.4] [ 6.4 3.2 4.5 1.5] [ 6.9 3.1 4.9 1.5] [ 5.5 2.3 4. 1.3] [ 6.5 2.8 4.6 1.5] [ 5.7 2.8 4.5 1.3] [ 6.3 3.3 4.7 1.6] [ 4.9 2.4 3.3 1. ] [ 6.6 2.9 4.6 1.3] [ 5.2 2.7 3.9 1.4] [ 5. 2. 3.5 1. ] [ 5.9 3. 4.2 1.5] [ 6. 2.2 4. 1. ] [ 6.1 2.9 4.7 1.4] [ 5.6 2.9 3.6 1.3] [ 6.7 3.1 4.4 1.4] [ 5.6 3. 4.5 1.5] [ 5.8 2.7 4.1 1. ] [ 6.2 2.2 4.5 1.5] [ 5.6 2.5 3.9 1.1] [ 5.9 3.2 4.8 1.8] [ 6.1 2.8 4. 1.3] [ 6.3 2.5 4.9 1.5] [ 6.1 2.8 4.7 1.2] [ 6.4 2.9 4.3 1.3] [ 6.6 3. 4.4 1.4] [ 6.8 2.8 4.8 1.4] [ 6.7 3. 5. 1.7] [ 6. 2.9 4.5 1.5] [ 5.7 2.6 3.5 1. ] [ 5.5 2.4 3.8 1.1] [ 5.5 2.4 3.7 1. ] [ 5.8 2.7 3.9 1.2] [ 6. 2.7 5.1 1.6] [ 5.4 3. 4.5 1.5] [ 6. 3.4 4.5 1.6] [ 6.7 3.1 4.7 1.5] [ 6.3 2.3 4.4 1.3] [ 5.6 3. 4.1 1.3] [ 5.5 2.5 4. 1.3] [ 5.5 2.6 4.4 1.2] [ 6.1 3. 4.6 1.4] [ 5.8 2.6 4. 1.2] [ 5. 2.3 3.3 1. ] [ 5.6 2.7 4.2 1.3] [ 5.7 3. 4.2 1.2] [ 5.7 2.9 4.2 1.3] [ 6.2 2.9 4.3 1.3] [ 5.1 2.5 3. 1.1] [ 5.7 2.8 4.1 1.3] [ 6.3 3.3 6. 2.5] [ 5.8 2.7 5.1 1.9] [ 7.1 3. 5.9 2.1] [ 6.3 2.9 5.6 1.8] [ 6.5 3. 5.8 2.2] [ 7.6 3. 6.6 2.1] [ 4.9 2.5 4.5 1.7] [ 7.3 2.9 6.3 1.8] [ 6.7 2.5 5.8 1.8] [ 7.2 3.6 6.1 2.5] [ 6.5 3.2 5.1 2. ] [ 6.4 2.7 5.3 1.9] [ 6.8 3. 5.5 2.1] [ 5.7 2.5 5. 2. ] [ 5.8 2.8 5.1 2.4] [ 6.4 3.2 5.3 2.3] [ 6.5 3. 5.5 1.8] [ 7.7 3.8 6.7 2.2] [ 7.7 2.6 6.9 2.3] [ 6. 2.2 5. 1.5] [ 6.9 3.2 5.7 2.3] [ 5.6 2.8 4.9 2. ] [ 7.7 2.8 6.7 2. ] [ 6.3 2.7 4.9 1.8] [ 6.7 3.3 5.7 2.1] [ 7.2 3.2 6. 1.8] [ 6.2 2.8 4.8 1.8] [ 6.1 3. 4.9 1.8] [ 6.4 2.8 5.6 2.1] [ 7.2 3. 5.8 1.6] [ 7.4 2.8 6.1 1.9] [ 7.9 3.8 6.4 2. ] [ 6.4 2.8 5.6 2.2] [ 6.3 2.8 5.1 1.5] [ 6.1 2.6 5.6 1.4] [ 7.7 3. 6.1 2.3] [ 6.3 3.4 5.6 2.4] [ 6.4 3.1 5.5 1.8] [ 6. 3. 4.8 1.8] [ 6.9 3.1 5.4 2.1] [ 6.7 3.1 5.6 2.4] [ 6.9 3.1 5.1 2.3] [ 5.8 2.7 5.1 1.9] [ 6.8 3.2 5.9 2.3] [ 6.7 3.3 5.7 2.5] [ 6.7 3. 5.2 2.3] [ 6.3 2.5 5. 1.9] [ 6.5 3. 5.2 2. ] [ 6.2 3.4 5.4 2.3] [ 5.9 3. 5.1 1.8]] [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2] ['setosa' 'versicolor' 'virginica'] Iris Plants Database

Notes

Data Set Characteristics: :Number of Instances: 150 (50 in each of three classes) :Number of Attributes: 4 numeric, predictive attributes and the class :Attribute Information:

  • sepal length in cm
  • sepal width in cm
  • petal length in cm
  • petal width in cm
  • class:
    • Iris-Setosa
    • Iris-Versicolour
    • Iris-Virginica :Summary Statistics:

============== ==== ==== ======= ===== ==================== Min Max Mean SD Class Correlation ============== ==== ==== ======= ===== ==================== sepal length: 4.3 7.9 5.84 0.83 0.7826 sepal width: 2.0 4.4 3.05 0.43 -0.4194 petal length: 1.0 6.9 3.76 1.76 0.9490 (high!) petal width: 0.1 2.5 1.20 0.76 0.9565 (high!) ============== ==== ==== ======= ===== ====================

:Missing Attribute Values: None :Class Distribution: 33.3% for each of 3 classes. :Creator: R.A. Fisher :Donor: Michael Marshall (MARSHALL%PLU@io.arc.nasa.gov) :Date: July, 1988

This is a copy of UCI ML iris datasets. http://archive.ics.uci.edu/ml/datasets/Iris

The famous Iris database, first used by Sir R.A Fisher

This is perhaps the best known database to be found in the pattern recognition literature. Fisher's paper is a classic in the field and is referenced frequently to this day. (See Duda & Hart, for example.) The data set contains 3 classes of 50 instances each, where each class refers to a type of iris plant. One class is linearly separable from the other 2; the latter are NOT linearly separable from each other.

References

  • Fisher,R.A. "The use of multiple measurements in taxonomic problems" Annual Eugenics, 7, Part II, 179-188 (1936); also in "Contributions to Mathematical Statistics" (John Wiley, NY, 1950).
  • Duda,R.O., & Hart,P.E. (1973) Pattern Classification and Scene Analysis. (Q327.D83) John Wiley & Sons. ISBN 0-471-22361-1. See page 218.
  • Dasarathy, B.V. (1980) "Nosing Around the Neighborhood: A New System Structure and Classification Rule for Recognition in Partially Exposed Environments". IEEE Transactions on Pattern Analysis and Machine Intelligence, Vol. PAMI-2, No. 1, 67-71.
  • Gates, G.W. (1972) "The Reduced Nearest Neighbor Rule". IEEE Transactions on Information Theory, May 1972, 431-433.
  • See also: 1988 MLC Proceedings, 54-64. Cheeseman et al"s AUTOCLASS II conceptual clustering system finds 3 classes in the data.
  • Many, many more ...

['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)'] [0 1 2]

資料預處理與特徵工程 (Data Clean/Preprocessing & Feature Engineering)

 如何使用 Python 學習機器學習(Machine Learning)

良好的資料輸入取決於資料預處理與特徵工程,而好的輸入將大大影響到模型是否可以發揮其理論正常水準。以下把資料轉成 DataFrame 格式方便進行操作。由於這邊的資料集已經是相當完整的資料集,所以我們這邊就不用特別進行資料預處理和特徵工程的部份,然而在真實世界中,真正在進行機器學習工作流程的時候資料預處理往往是最花時間的部份。同時為了方便模型的校調,我們這邊把資料集分為 70% 訓練資料,30% 驗證資料。

# 將資料轉為 pandas DataFrame
# data 為觀察目標變數
df_X = pd.DataFrame(raw_iris.data)
# target 為預測變數
df_y = pd.DataFrame(raw_iris.target)

# 將資料切分為 training data 和 testing data,其中 random_state 若設為 0 或不設則即便實例不同但因種子相同產生同樣隨機編號,若設為 1 則每次隨機產生不同編號
# test_size 為切分 training data 和 testing data 的比例
X_train, X_test, y_train, y_test = train_test_split(df_X, df_y, test_size=0.3)
# 印出所有資料集筆數
print(len(df_y))

150

# 印出切分 y_train 的數量為所有資料集的 70%,共 105 筆
print(y_train)
print(len(y_train))

0 39 0 106 2 99 1 0 0 16 0 118 2 80 1 29 0 11 0 104 2 100 2 72 1 108 2 42 0 20 0 31 0 115 2 111 2 89 1 83 1 130 2 41 0 66 1 120 2 113 2 6 0 126 2 62 1 23 0 97 1 .. .. 10 0 76 1 129 2 144 2 137 2 12 0 79 1 123 2 127 2 36 0 74 1 37 0 131 2 110 2 22 0 32 0 147 2 134 2 102 2 75 1 88 1 148 2 33 0 56 1 28 0 90 1 82 1 25 0 121 2 13 0

[105 rows x 1 columns] 105

# 印出切分的 y_test 資料為所有資料集的 30%,共 45 筆
print(y_test)
print(len(y_test))

0 102 2 53 1 143 2 70 1 61 1 67 1 24 0 124 2 36 0 92 1 114 2 31 0 120 2 87 1 74 1 47 0 69 1 56 1 93 1 16 0 144 2 133 2 29 0 57 1 116 2 50 1 86 1 44 0 3 0 21 0 82 1 99 1 134 2 111 2 135 2 4 0 2 0 91 1 85 1 122 2 127 2 11 0 27 0 79 1 51 1 45

訓練模型與校調 (Model Training)

 如何使用 Python 學習機器學習(Machine Learning)

上面是 scikit-learn 提供的演算法 cheat-sheet,當你面對琳琅滿目的模型一開始不知道要選擇什麼的話可以按圖索驥參考,另外這邊提供大圖支援連結

這邊我們參考上圖來選擇適合模型:

  1. 樣本資料是否大於 50 筆:範例資料集總共有 150 筆資料,大於 50
  2. 是否為分類問題:Iris 花朵類別預測是多類別分類問題
  3. 是否有標籤好的資料:已經有 label 資料
  4. 樣本資料是否小於 100K:資料小於 100K
  5. 選擇 Linear SVC 模型(第一個選擇的模型)
  6. 是否是文字資料:不是
  7. 選擇 KNeighborsClassifier 模型(第二個選擇的模型)
  8. 後續優化 / SVC / Ensemble
# 初始化 LinearSVC 實例
lin_clf = LinearSVC()
# 使用 fit 來建置模型,其參數接收 training data matrix, testing data array,所以進行 y_train.values.ravel() Data Frame 轉換
lin_clf.fit(X_train, y_train.values.ravel())

LinearSVC(C=1.0, class_weight=None, dual=True, fit_intercept=True, intercept_scaling=1, loss='squared_hinge', max_iter=1000, multi_class='ovr', penalty='l2', random_state=None, tol=0.0001, verbose=0)

# 初始化 KNeighborsClassifier 實例
knn = KNeighborsClassifier()

# 使用 fit 來建置模型,其參數接收 training data matrix, testing data array,所以進行 y_train.values.ravel() 轉換
knn.fit(X_train, y_train.values.ravel())

KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski', metric_params=None, n_jobs=1, n_neighbors=5, p=2, weights='uniform')

模型驗證 (Model Predict & Testing)

 如何使用 Python 學習機器學習(Machine Learning)

監督式學習的分類問題通常會分為訓練模型和驗證模型,這邊我們使用 predict 去產生對應的目標值,此時和正確答案(已經標籤好的目標值)比較可以知道模型預測的正確率。我們可以看到 KNeighborsClassifier 在正確率(accuracy)表現上相對比較好一點(0.98 比 0.93)。

# 使用 X_test 來預測結果
print(lin_clf.predict(X_test))

[1 1 0 2 1 2 0 1 1 2 2 1 0 2 0 0 2 1 2 0 0 1 2 0 2 1 2 0 0 0 1 0 2 1 1 0 0 0 1 0 1 2 2 1 1]

# 印出預測準確率
print(lin_clf.score(X_test, y_test))

0.933333333333

# 使用 X_test 來預測結果
print(knn.predict(X_test))

[1 1 0 1 1 2 0 1 1 2 2 1 0 2 0 0 2 1 2 0 0 1 2 0 2 1 2 0 0 0 1 0 1 1 1 0 0 0 1 0 1 2 2 1 1]

# 印出 testing data 預測標籤機率
print(knn.predict_proba(X_test))

[[ 0. 1. 0. ] [ 0. 1. 0. ] [ 1. 0. 0. ] [ 0. 0.8 0.2] [ 0. 1. 0. ] [ 0. 0. 1. ] [ 1. 0. 0. ] [ 0. 1. 0. ] [ 0. 1. 0. ] [ 0. 0. 1. ] [ 0. 0. 1. ] [ 0. 1. 0. ] [ 1. 0. 0. ] [ 0. 0. 1. ] [ 1. 0. 0. ] [ 1. 0. 0. ] [ 0. 0. 1. ] [ 0. 1. 0. ] [ 0. 0. 1. ] [ 1. 0. 0. ] [ 1. 0. 0. ] [ 0. 1. 0. ] [ 0. 0. 1. ] [ 1. 0. 0. ] [ 0. 0.2 0.8] [ 0. 1. 0. ] [ 0. 0. 1. ] [ 1. 0. 0. ] [ 1. 0. 0. ] [ 1. 0. 0. ] [ 0. 1. 0. ] [ 1. 0. 0. ] [ 0. 1. 0. ] [ 0. 1. 0. ] [ 0. 1. 0. ] [ 1. 0. 0. ] [ 1. 0. 0. ] [ 1. 0. 0. ] [ 0. 0.6 0.4] [ 1. 0. 0. ] [ 0. 1. 0. ] [ 0. 0. 1. ] [ 0. 0. 1. ] [ 0. 1. 0. ] [ 0. 1. 0. ]]

# 印出預測準確率
print(knn.score(X_test, y_test))

0.977777777778

模型優化 (Model Optimization)

由於本文是簡易範例,這邊就沒有示範如何進行模型優化(這邊可以嘗試使用 SVC 和 Ensemble 方法)。不過一般來說在分類模型優化上,讓模型預測表現的更好的方法大約有幾種:

  1. 特徵工程:選擇更適合特徵值或是更好的資料清理,某種程度上很需要專業知識的協助(domain konwledge)去發現和整合出更好的 feature
  2. 調整模型參數:調整模型的參數
  3. 模型融合:結合幾個弱分類器結果來變成強的分類器

上線運行 (Deploy Model)

當模型優化完畢就可以進行上線運行,其中 Python 比 R 更具優勢的地方,那就是 Python 很容易跟現有的系統進行整合,Python 也有許多好用的 Web 框架可以使用,也因為 Python 是膠水語言,若要進行效能優化也可以很容易呼叫 C/C++ 進行操作,提昇執行效能。

總結

以上用一個簡單的範例介紹了 Python 機器學習套件 Scikit Learn 的基本功能和機器學習整個基本 Workflow。由於是基礎範例所以省略一些比較繁瑣的資料處理部分,事實上,真實世界資料大多是非結構化資料的髒資料,而資料分析的過程往往需要花上許多時間進行資料預處理和資料清理上。接下來我們將介紹其他 Python 資料科學和機器學習生態系和相關工具。

延伸閱讀

  1. 机器学习实战 之 kNN 分类
  2. Machine Learning Workflow
  3. Kaggle机器学习之模型融合(stacking)心得
  4. Python 資料視覺化
  5. Train & Predict workflow
  6. Sample Classification Pipeline workflow
  7. 【机器学习】模型融合方法概述

(image via mediummaprsilvrbackcamoscipymirlabconcreteinteractivesndimg

用 Python 自學資料科學與機器學習入門實戰:Matplotlib 基礎入門

· 閱讀時間約 8 分鐘

 從零開始學資料科學:Numpy 基礎入門

本系列文章將透過系統介紹資料科學(Data Science)相關的知識,透過 Python 帶領讀者從零開始進入資料科學的世界。這邊我們將介紹 Matplotlib 這個 Python 資料視覺化的核心工具。

什麼是 Matplotlib?

Python 的視覺化套件有靜態的 MatplotlibSeabornggplot(借鏡於 Rggplot2)套件以及動態的 Bokeh 套件(類似於 D3.js)。其中 Matplotlib 是 Python 的一個重要模組(Python 是一個高階語言也是一種膠水語言,可以透過整合其他低階語言同時擁有效能和高效率的開發),主要用於資料視覺化上。一般來說使用 Matplotlib 有兩種主要方式:直接和 Matplotlib 的全域 pyplot 模組互動操作,第二種則是物件導向形式的操作方式。若是只有一張圖的話使用全域 pyplot 很方便,若是有多張圖的話用物件導向操作。一般來說 Matplotlib 預設值並不理想,但它的優點在於很容易在上面外包一層提供更好的預設值或是自己修改預設值。

第一張 Matplotlib 圖片

# 引入模組
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
x = pd.period_range(pd.datetime.now(), periods=200, freq='d')
x = x.to_timestamp().to_pydatetime()
# 產生三組,每組 200 個隨機常態分布元素
y = np.random.randn(200, 3).cumsum(0)
plt.plot(x, y)
plt.show()

 從零開始學資料科學:Matplotlib 基礎入門

常用屬性和參數調整

# Matplotlib 使用點 point 而非 pixel 為圖的尺寸測量單位,適合用於印刷出版。1 point = 1 / 72 英吋,但可以調整

import matplotlib as mpl
mpl.rcParams['lines.linewidth'] = 5
mpl.rcParams['lines.color'] = 'r'
mpl.rcParams['figure.figsize'] = (10, 10)
plt.gcf().set_size_inches(10, 10)

x = pd.period_range(pd.datetime.now(), periods=200, freq='d')
x = x.to_timestamp().to_pydatetime()
# 產生三組,每組 200 個隨機常態分布元素
y = np.random.randn(200, 3).cumsum(0)
plt.plot(x, y)
plt.show()

物件導向式 Matplotlib

 從零開始學資料科學:Matplotlib 基礎入門

# 設定標籤
plots = plt.plot(x, y)
plt.legend(plots, ('Apple', 'Facebook', 'Google'), loc='best', framealpha=0.5, prop={'size': 'large', 'family': 'monospace'})
plt.show()

 從零開始學資料科學:Matplotlib 基礎入門

# 標題與軸標籤
plt.title('Random Trends')
plt.xlabel('Date')
plt.ylabel('Cum. Sum')
plt.figtext(0.995, 0.01, 'CopyRight', ha='right', va='bottom')
# 避免被圖表元素被蓋住
plt.tight_layout()
plt.plot(x, y)
plt.show()

 從零開始學資料科學:Matplotlib 基礎入門

# 儲存圖表
plt.savefig('plt.svg')
# 使用物件導向方式控制圖表,透過控制 figure 和 axes 來操作。其中 figure 和全域 pyplot 部分屬性相同。例如: fig.text() 對應到 plt.fig_text()
fig = plt.figure(figsize=(8, 4), dpi=200, tight_layout=True, linewidth=1, edgecolor='r')
# 軸與子圖表
fig = plt.figure(figsize=(8, 4))

# 插入主要軸,可以透過 add_axes 控制軸在圖裡的位置。例如:[bottom*0.1, left*0.1, top*0.5, right*0.5],fig.add_axes([0.1, 0.1, 0.5, 0.5])
ax = fig.add_axes([0.1, 0.1, 0.8, 0.8])
ax.set_title('Main Axes with Insert Child Axes')
ax.plot(x, y[:, 0])
ax.set_xlabel('Date')
ax.set_ylabel('Cum. sum')

# 插入軸
ax = fig.add_axes([0.15, 0.15, 0.3, 0.3])
ax.plot(x, y[:, 1], color='g')
ax.set_xticks([])

 從零開始學資料科學:Matplotlib 基礎入門

# 單一圖與軸繪製(subplots 不帶參數回傳擁有一軸 figure 物件,幾乎等同於 matplotlib 全域物件)
# matplotlib 內建版面編排系統相對好用。圖表大小不一可以使用 gridspec 模組
figure, ax = plt.subplots()
plots = ax.plot(x, y, label='')
figure.set_size_inches(8, 4)
ax.legend(plots, ('Apple', 'Faceook', 'Google'), loc='best', framealpha=0.25, prop={'size': 'small', 'family': 'monospace'})

ax.set_title('Random trends')
ax.set_xlabel('Date')
ax.set_ylabel('Cum. sum')

ax.grid(True) # 使用格子
figure.text(0.995, 0.01, 'ACM 2015', ha='right', va='bottom')
figure.tight_layout()

 從零開始學資料科學:Matplotlib 基礎入門

# 使用子圖表
figure, ax = plt.subplots()
plots = ax.plot(x, y, label='')
figure.set_size_inches(8, 4)
ax.legend(plots, ('Apple', 'Faceook', 'Google'), loc='best', framealpha=0.25, prop={'size': 'small', 'family': 'monospace'})
ax.set_title('Random trends')
ax.set_xlabel('Date')
ax.set_ylabel('Cum. sum')
ax.grid(True)

figure.text(0.995, 0.01, 'Acm', ha='right', va='bottom')
figure.tight_layout()

 從零開始學資料科學:Matplotlib 基礎入門

# 使用子圖表產生多個圖表
fig, axes = plt.subplots(nrows=3, ncols=1, sharex=True, sharey=True, figsize=(8, 8))
labelled_data = zip(y.transpose(), ('Apple', 'Faceook', 'Google'), ('b', 'g', 'r'))
fig.suptitle('Three Random Trends', fontsize=16)

for i, ld in enumerate(labelled_data):
ax = axes[i]
ax.plot(x, ld[0], label=ld[1], color=ld[2])
ax.set_ylabel('Cum. sum')
ax.legend(loc='upper left', framealpha=0.5, prop={'size': 'small'})
axes[-1].set_xlabel('Date')

 從零開始學資料科學:Matplotlib 基礎入門

常見圖表

  1. 直方圖(Histogram)

    # 直方圖
    normal_samples = np.random.normal(size=100) # 生成 100 組標準常態分配(平均值為 0,標準差為 1 的常態分配)隨機變數
    plt.hist(normal_samples, width=0.1)
    plt.show()

     從零開始學資料科學:Matplotlib 基礎入門

  2. 散佈圖(Scatter plot)

    # 散佈圖
    num_points = 100
    gradient = 0.5
    x = np.array(range(num_points))
    y = np.random.randn(num_points) * 10 + x * gradient
    fig, ax = plt.subplots(figsize=(8, 4))
    ax.scatter(x, y)

    fig.suptitle('A Simple Scatter Plot')
    plt.show()

     從零開始學資料科學:Matplotlib 基礎入門

    # 散佈圖 + 迴歸
    num_points = 100
    gradient = 0.5
    x = np.array(range(num_points))
    y = np.random.randn(num_points) * 10 + x * gradient

    fig, ax = plt.subplots(figsize=(8, 4))

    ax.scatter(x, y)

    m, c = np.polyfit(x, y, 1) # 使用 Numpy 的 polyfit,參數 1 代表一維,算出 fit 直線斜率
    ax.plot(x, m * x + c) # 使用 y = m * x + c 斜率和常數匯出直線
    fig.suptitle('Scatter with regression')
    plt.show()
  3. 線圖(Line plot)

     從零開始學資料科學:Matplotlib 基礎入門

    # 線圖
    age = [4, 4, 17, 17, 18]
    points = [2, 20, 22, 24, 20]

    plt.plot(age, points)
    plt.show()
  4. 長條圖(Bar plot)

     從零開始學資料科學:Matplotlib 基礎入門

    # 長條圖
    labels = ['Physics', 'Chemistry', 'Literature', 'Peace']
    foo_data = [3, 6, 10, 4]
    bar_width = 0.5
    xlocations = np.array(range(len(foo_data))) + bar_width

    plt.bar(xlocations, foo_data, width=bar_width)

    plt.title('Stock Price')
    plt.show()

     從零開始學資料科學:Matplotlib 基礎入門

  5. 盒鬚圖(Box plot)

    # 盒鬚圖
    normal_examples = np.random.normal(size = 100) # 生成 100 組標準常態分配(平均值為 0,標準差為 1 的常態分配)隨機變數

    plt.boxplot(normal_examples)
    plt.show()

     從零開始學資料科學:Matplotlib 基礎入門

  6. 圓餅圖(Pie plot)

    # 圓餅圖
    data = np.random.randint(1, 11, 5) # 生成
    x = np.arange(len(data))

    plt.pie(data)

    plt.show()

 從零開始學資料科學:Matplotlib 基礎入門

Python 其他資料視覺化套件

  1. Seaborn

    # Seaborn
    import numpy as np
    import seaborn as sns
    import matplotlib.pyplot as plt
    sns.set(style="white", context="talk")
    rs = np.random.RandomState(7)


    # 準備 matplotlib 圖表
    f, (ax1, ax2, ax3) = plt.subplots(3, 1, figsize=(8, 6), sharex=True)

    # 產生連續資料
    x = np.array(list("ABCDEFGHI"))
    y1 = np.arange(1, 10)
    sns.barplot(x, y1, palette="BuGn_d", ax=ax1)
    ax1.set_ylabel("Sequential")

    # 調整成 diverging 資料
    y2 = y1 - 5
    sns.barplot(x, y2, palette="RdBu_r", ax=ax2)
    ax2.set_ylabel("Diverging")

    # 隨機資料
    y3 = rs.choice(y1, 9, replace=False)
    sns.barplot(x, y3, palette="Set3", ax=ax3)
    ax3.set_ylabel("Qualitative")

    # 秀出圖片
    sns.despine(bottom=True)
    plt.setp(f.axes, yticks=[])
    plt.tight_layout(h_pad=3)

     從零開始學資料科學:Matplotlib 基礎入門

  2. Bokeh

    # Bokeh
    from bokeh.plotting import figure, output_file, show

    # 準備資料
    x = [1, 2, 3, 4, 5]
    y = [6, 7, 2, 4, 5]

    # 輸出成靜態 HTML
    output_file("lines.html")

    # 創建新的標題和軸圖表
    p = figure(title="simple line example", x_axis_label='x', y_axis_label='y')

    # 繪製直線圖
    p.line(x, y, legend="Temp.", line_width=2)

    # 呈現結果
    show(p)

總結

以上介紹了 Matplotlib 的基礎知識和 api,同時也介紹了 Python 其他資料視覺化套件。一般來說 Matplotlib 預設值並不理想,但它的優點在於很容易在上面外包一層提供更好的預設值或是自己修改預設值。一般來說我們在進行資料科學和機器學習分析的過程中我們會先使用資訊視覺化工具來了解整個資料集的特色並針對資料進行後續的處理和特徵選取,所以說資料視覺化不僅能呈現資料分析的結果,對於資料分析的過程也十分重要。

延伸閱讀

  1. [python] numpy axis概念整理筆記
  2. [第 18 天] 資料視覺化 matplotlib
  3. 数据可视化(三)- Seaborn简易入门

(image via matplotlib

用 Python 自學資料科學與機器學習入門實戰:Pandas 基礎入門

· 閱讀時間約 12 分鐘
Python 資料科學系列教學

本文是 Python 資料科學與機器學習系列 的第三篇文章:

  1. Python 資料科學入門介紹
  2. NumPy 基礎教學
  3. Pandas 基礎入門 (本文)
  4. Matplotlib 資料視覺化
  5. Scikit-learn 機器學習

📚 查看完整系列

 如何使用 Python 學習機器學習(Machine Learning)

本系列文章將透過 Python 及其資料科學生態系(Numpy、Scipy、Pandas、Scikit-learn、Statsmodels、Matplotlib、Scrapy、Keras、TensorFlow 等)來系統性介紹資料科學和相關的知識,透過 Python 帶領讀者進入資料科學的世界和機器學習的世界。在這個單元中我們將介紹 Pandas 這個基於 Numpy 的資料處理和分析神兵利器。

事實上,真實世界並非如此美好,大部分資料分析的工作時間有很大一部分都是在處理髒資料,希望讓資料可以符合模型輸入的需求,而 Pandas 正是扮演這個資料預處理和資料清洗的核心角色,是 Python 在和 R 爭奪資料科學第一程式語言霸主時的生力軍,接下來我們將介紹 Pandas 核心功能和資料的操作方式。

 如何使用 Python 學習機器學習(Machine Learning)

Pandas 核心功能介紹

創建資料結構

在 Pandas 中主要有兩大資料結構:Series、DataFrame,與 Numpy 中的 ndarray 比較不同的是 Pandas DataFrame 可以存異質資料(不同資料型別)。

Series 類似於 Python 本身的 list 資料結構,不同的是每個元素有自己的 index(可以自己命名):

%matplotlib inline
# 引入 numpy 和 pandas 模組
import numpy as np
import pandas as pd
s1 = pd.Series([1, 3, 5, np.nan, 6, 8]) # 使用 Python lits 產生 Series,其中包含一個值為 NaN

print(s1)

0 1.0 1 3.0 2 5.0 3 NaN 4 6.0 5 8.0 dtype: float64

s2 = pd.Series(np.random.randint(2, size=[3])) # 使用 np.random.randint 產生 3 個 0-2(不含 2)的數組

print(s2)

0 1 1 1 2 1 dtype: int64

DataFrame 可以使用 np.random.randn 產生值來創建,也可以使用 Python dict 進行創建:

# 產生 20170101-20170106 的值,DatetimeIndex(['2017-01-01', '2017-01-02', '2017-01-03', '2017-01-04', '2017-01-05', '2017-01-06'], dtype='datetime64[ns]', freq='D')
dates = pd.date_range('20170101', periods=6)

# 產生 row6,column4 個 standard normal distribution 隨機值,使用 ABCD 當 columns,使用 dates 當 index
df0 = pd.DataFrame(np.random.randn(6,4), index=dates, columns=list('ABCD'))
print(df0)

A B C D 2017-01-01 1.112542 -0.142577 0.832830 -2.755133 2017-01-02 -0.218838 -0.304488 1.437599 -0.402454 2017-01-03 0.295245 -0.786898 -1.231896 -0.224959 2017-01-04 -0.346745 -1.582944 -0.464175 -0.410576 2017-01-05 0.163782 0.948795 -0.420505 -0.641032 2017-01-06 0.515806 -0.935421 -0.701349 -0.820109

# 使用 dict 來創建 DataFrame
teams = ['Web', 'Mobile', 'Data']
nums = [12, 14, 34]
rd_team_dict = {
'teams': teams,
'nums': nums
}
rd_team_df = pd.DataFrame(rd_team_dict)

print(rd_team_df)

nums teams 0 12 Web 1 14 Mobile 2 34 Data

觀察資料

# 觀察資料型態、結構、內容值
df = pd.DataFrame({ 'A' : 1.,
'B' : pd.Timestamp('20170102'),
'C' : pd.Series(1,index=list(range(4)),dtype='float32'),
'D' : np.array([3] * 4,dtype='int32'),
'E' : pd.Categorical(["test","train","test","train"]),
'F' : 'foo' })

# 印出內容值資料型別
print(df.dtypes)

A float64 B datetime64[ns] C float32 D int32 E category F object dtype: object

# 印出資料維度
print(df.shape)

(4, 6)

# 印出每行資料長度
print(len(df))

4

# 印出 DataFrame 資料概況
print(df.info())

<class 'pandas.core.frame.DataFrame'> Int64Index: 4 entries, 0 to 3 Data columns (total 6 columns): A 4 non-null float64 B 4 non-null datetime64[ns] C 4 non-null float32 D 4 non-null int32 E 4 non-null category F 4 non-null object dtypes: category(1), datetime64ns, float32(1), float64(1), int32(1), object(1) memory usage: 180.0+ bytes None

# 印出基本敘述統計數據
print(df.describe())

A C D count 4.0 4.0 4.0 mean 1.0 1.0 3.0 std 0.0 0.0 0.0 min 1.0 1.0 3.0 25% 1.0 1.0 3.0 50% 1.0 1.0 3.0 75% 1.0 1.0 3.0 max 1.0 1.0 3.0

# 印出首 i 個數據
print(df.head(2))

A B C D E F 0 1.0 2017-01-02 1.0 3 test foo 1 1.0 2017-01-02 1.0 3 train foo

# 印出尾 i 個數據
print(df.tail(2))

A B C D E F 2 1.0 2017-01-02 1.0 3 test foo 3 1.0 2017-01-02 1.0 3 train foo

# 印出 index 值
print(df.index)

Int64Index([0, 1, 2, 3], dtype='int64')

# 印出 columns 值
print(df.columns)

Index(['A', 'B', 'C', 'D', 'E', 'F'], dtype='object')

# 印出 values 值
print(df.values)

[[1.0 Timestamp('2017-01-02 00:00:00') 1.0 3 'test' 'foo'] [1.0 Timestamp('2017-01-02 00:00:00') 1.0 3 'train' 'foo'] [1.0 Timestamp('2017-01-02 00:00:00') 1.0 3 'test' 'foo'] [1.0 Timestamp('2017-01-02 00:00:00') 1.0 3 'train' 'foo']]

# 印出轉置 DataFrame
print(df.T)

0 1 2
A 1 1 1
B 2017-01-02 00:00:00 2017-01-02 00:00:00 2017-01-02 00:00:00
C 1 1 1
D 3 3 3
E test train test
F foo foo foo

3
A 1
B 2017-01-02 00:00:00
C 1
D 3
E train
F foo

# sort by the index labels。axis=0 使用 index 進行 sort,axis=1 使用 columns 進行 sort。ascending 決定是否由小到大
print(df.sort_index(axis=0, ascending=False))

A B C D E F 3 1.0 2017-01-02 1.0 3 train foo 2 1.0 2017-01-02 1.0 3 test foo 1 1.0 2017-01-02 1.0 3 train foo 0 1.0 2017-01-02 1.0 3 test foo

# sort by the values of columns
print(df.sort_values(by='E'))

A B C D E F 0 1.0 2017-01-02 1.0 3 test foo 2 1.0 2017-01-02 1.0 3 test foo 1 1.0 2017-01-02 1.0 3 train foo 3 1.0 2017-01-02 1.0 3 train foo

選取資料

# 選取值的方式一般建議使用 1. loc, 2. iloc, 3. ix
# label-location based 行列標籤值取值,以下取出 index=1 那一欄,[列, 行]
print(df.loc[0])

A 1 B 2017-01-02 00:00:00 C 1 D 3 E test F foo Name: 0, dtype: object

# iloc 則通過行列數字索引取值,[列,行]
print(df.iloc[0:3, 1:2])

B 0 2017-01-02 1 2017-01-02 2 2017-01-02

# 兼容 loc 和 iloc
print(df.ix[0, 'B'])

2017-01-02 00:00:00

# 兼容 loc 和 iloc
print(df.ix[1, 3])

3

# 布林取值,取出 A 行大於 0 的資料
print(df[df.A > 0])

A B C D E F 0 1.0 2017-01-02 1.0 3 test foo 1 1.0 2017-01-02 1.0 3 train foo 2 1.0 2017-01-02 1.0 3 test foo 3 1.0 2017-01-02 1.0 3 train foo

# 產生 Series 值
s1 = pd.Series([1,2,3,4,5,6], index=pd.date_range('20170102', periods=6))
print(s1)

2017-01-02 1 2017-01-03 2 2017-01-04 3 2017-01-05 4 2017-01-06 5 2017-01-07 6 Freq: D, dtype: int64

# 更新值
df.loc[:,'D'] = np.array([5] * len(df))
print(df)

A B C D E F 0 1.0 2017-01-02 1.0 5 test foo 1 1.0 2017-01-02 1.0 5 train foo 2 1.0 2017-01-02 1.0 5 test foo 3 1.0 2017-01-02 1.0 5 train foo

處理遺失資料

# 查缺補漏
df2 = pd.DataFrame(index=dates[0:4], columns=list(df.columns) + ['E'])

df2.loc[dates[0]:dates[1], :] = 1

# drop 掉 NaN 值
print(df2.dropna(how='any'))
# 補充 NaN 為 3
print(df2.fillna(value=3))
print(df2)

# 回傳 NaN 布林值
print(pd.isnull(df2))

# inplace 為 True 為直接操作資料,不是操作 copy 副本
df2.dropna(how='any', inplace=True)

A B C D E F E 2017-01-01 1 1 1 1 1 1 1 2017-01-02 1 1 1 1 1 1 1 A B C D E F E 2017-01-01 1 1 1 1 1 1 1 2017-01-02 1 1 1 1 1 1 1 2017-01-03 3 3 3 3 3 3 3 2017-01-04 3 3 3 3 3 3 3 A B C D E F E 2017-01-01 1 1 1 1 1 1 1 2017-01-02 1 1 1 1 1 1 1 2017-01-03 NaN NaN NaN NaN NaN NaN NaN 2017-01-04 NaN NaN NaN NaN NaN NaN NaN A B C D E F E 2017-01-01 False False False False False False False 2017-01-02 False False False False False False False 2017-01-03 True True True True True True True 2017-01-04 True True True True True True True

資料操作

# 針對每一個值進行操作
df.apply(lambda x: x.max() - x.min())

A 2.696944 B 5.285329 C 1.948946 D 2.615037 dtype: float64

串接資料

# 串接資料

df = pd.DataFrame(np.random.randn(10, 4))
print(df)
pieces = [df[:3], df[3:7], df[7:]]
print(pieces)
print(pd.concat(pieces))

0 1 2 3 0 -0.171208 2.200967 0.385574 -0.481588 1 1.447335 1.756239 0.083053 0.255434 2 -0.508576 0.818774 -0.438210 -0.819860 3 1.704828 -0.329642 -1.059202 -0.820319 4 -1.792491 -0.761873 -1.090574 -0.484552 5 0.166621 1.704577 -1.613185 -0.391985 6 0.806292 0.699608 -1.768223 -1.081318 7 -1.168532 0.768302 0.831701 0.422367 8 0.065940 -0.038649 -0.060712 -0.500365 9 0.623535 0.558461 -0.956861 1.229675 [ 0 1 2 3 0 -0.171208 2.200967 0.385574 -0.481588 1 1.447335 1.756239 0.083053 0.255434 2 -0.508576 0.818774 -0.438210 -0.819860, 0 1 2 3 3 1.704828 -0.329642 -1.059202 -0.820319 4 -1.792491 -0.761873 -1.090574 -0.484552 5 0.166621 1.704577 -1.613185 -0.391985 6 0.806292 0.699608 -1.768223 -1.081318, 0 1 2 3 7 -1.168532 0.768302 0.831701 0.422367 8 0.065940 -0.038649 -0.060712 -0.500365 9 0.623535 0.558461 -0.956861 1.229675] 0 1 2 3 0 -0.171208 2.200967 0.385574 -0.481588 1 1.447335 1.756239 0.083053 0.255434 2 -0.508576 0.818774 -0.438210 -0.819860 3 1.704828 -0.329642 -1.059202 -0.820319 4 -1.792491 -0.761873 -1.090574 -0.484552 5 0.166621 1.704577 -1.613185 -0.391985 6 0.806292 0.699608 -1.768223 -1.081318 7 -1.168532 0.768302 0.831701 0.422367 8 0.065940 -0.038649 -0.060712 -0.500365 9 0.623535 0.558461 -0.956861 1.229675

合併資料

# 合併資料
left = pd.DataFrame({'key': ['foo', 'foo'], 'lval': [1, 2]})
right = pd.DataFrame({'key': ['foo', 'foo'], 'rval': [4, 5]})

print(pd.merge(left, right, on='key'))

key lval rval 0 foo 1 4 1 foo 1 5 2 foo 2 4 3 foo 2 5

新增資料

# 新增資料於最後
df = pd.DataFrame(np.random.randn(8, 4), columns=['A','B','C','D'])
print(df)
s = df.iloc[3]
print(df.append(s, ignore_index=True))

A B C D 0 1.780499 1.207626 0.631475 -1.747506 1 -0.603999 -2.364099 1.153066 0.504784 2 0.721924 0.199784 -0.158318 -0.882946 3 -0.378070 -0.379311 0.478997 0.271056 4 0.620888 -0.366262 -0.738695 -0.380854 5 -0.587604 -1.728096 0.279645 -0.927843 6 -0.916445 2.921231 -0.795880 0.867531 7 -0.373190 1.526771 0.136712 0.015765 A B C D 0 1.780499 1.207626 0.631475 -1.747506 1 -0.603999 -2.364099 1.153066 0.504784 2 0.721924 0.199784 -0.158318 -0.882946 3 -0.378070 -0.379311 0.478997 0.271056 4 0.620888 -0.366262 -0.738695 -0.380854 5 -0.587604 -1.728096 0.279645 -0.927843 6 -0.916445 2.921231 -0.795880 0.867531 7 -0.373190 1.526771 0.136712 0.015765 8 -0.378070 -0.379311 0.478997 0.271056

群組操作

# 群組操作
print(df.groupby(['A','B']).sum())

C D A B
-1.232691 0.489020 0.436602 -1.439868 -0.259460 -0.269874 1.655001 0.530137 -0.256261 -0.743254 0.128837 1.050430 0.015723 0.596866 -0.232503 1.247810 0.049633 -0.093130 0.895723 1.049938 0.458667 0.348883 -0.681931 -0.517437 1.446492 0.007736 0.208870 0.211517 2.357912 -0.187805 -0.376578 -0.459085

繪圖

# 印出圖表
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
ts = ts.cumsum()
ts.plot()

png

輸入/輸出

# 讀取檔案/輸出檔案,支援 csv, h5, xlsx 檔案格式
df.to_csv('foo.csv')
pd.read_csv('foo.csv')
df.to_excel('foo.xlsx', sheet_name='Sheet1')
print(pd.read_excel('foo.xlsx', 'Sheet1', index_col=None, na_values=['NA']))

A B C D 0 1.446492 0.007736 0.208870 0.211517 1 0.049633 -0.093130 0.895723 1.049938 2 -1.232691 0.489020 0.436602 -1.439868 3 -0.259460 -0.269874 1.655001 0.530137 4 0.015723 0.596866 -0.232503 1.247810 5 0.458667 0.348883 -0.681931 -0.517437 6 2.357912 -0.187805 -0.376578 -0.459085 7 -0.256261 -0.743254 0.128837 1.050430

總結

以上整理了一些 Pandas 核心功能和如何操作資料,接下來我們將介紹其他 Python 資料科學和機器學習生態系和相關工具。

延伸閱讀

  1. 10 Minutes to pandas
  2. Pandas 使用教學 - 第一部分
  3. Python Pandas - Understanding inplace=True
  4. pandas学习笔记
  5. 【Python实战】Pandas:让你像写SQL一样做数据分析(一)

(image via pydatanbcnews

用 Python 自學資料科學與機器學習入門實戰:Numpy 基礎入門

· 閱讀時間約 4 分鐘

 從零開始學資料科學:Numpy 基礎入門

本系列文章將透過系統介紹資料科學(Data Science)相關的知識,透過 Python 帶領讀者從零開始進入資料科學的世界。這邊我們將介紹 Numpy 這個強大的 Python 函式庫。

什麼是 Numpy?

Numpy 是 Python 的一個重要模組(Python 是一個高階語言也是一種膠水語言,可以透過整合其他低階語言同時擁有效能和高效率的開發),主要用於資料處理上。Numpy 底層以 C 和 Fortran 語言實作,所以能快速操作多重維度的陣列。當 Python 處理龐大資料時,其原生 list 效能表現並不理想(但可以動態存異質資料),而 Numpy 具備平行處理的能力,可以將操作動作一次套用在大型陣列上。此外 Python 其餘重量級的資料科學相關套件(例如:Pandas、SciPy、Scikit-learn 等)都幾乎是奠基在 Numpy 的基礎上。因此學會 Numpy 對於往後學習其他資料科學相關套件打好堅實的基礎。

Numpy 基礎操作

 從零開始學資料科學:Numpy 基礎入門

  1. Numpy 陣列 Numpy 的重點在於陣列的操作,其所有功能特色都建築在同質且多重維度的 ndarray(N-dimensional array)上。ndarray 的關鍵屬性是維度(ndim)、形狀(shape)和數值類型(dtype)。 一般我們稱一維陣列為 vector 而二維陣列為 matrix。一開始我們會引入 numpy 模組,透過傳入 listnumpy.array() 創建陣列。

    # 引入 numpy 模組
    import numpy as np
    np1 = np.array([1, 2, 3])
    np2 = np.array([3, 4, 5])

    # 陣列相加
    print(np1 + np2) # [4 6 8]

    # 顯示相關資訊
    print(np1.ndim, np1.shape, np1.dtype) # 1 (3,) int64 => 一維陣列, 三個元素, 資料型別

    np3 = np.array([1, 2, 3, 4, 5, 6])

    從檔案取資料:

    npd = np.genfromtxt('data.csv', delimiter=',')

    改變陣列維度:

    np3 = np3.reshape([2, 3])
    print(np3.ndim, np3.shape, np3.dtype) # 2 (2, 3) int64

    改變陣列型別(bool、int、float、string):

    bool 可以包含 True、False,int 可以包含 int16、int32、int64。其中數字是指 bitsfloat 可以包含 16、32、64 表示小數點後幾位。string 可以是 string、unicode。nan 則表示遺失值。

    np3 = np3.astype('int64')
    np3.dtype
    # dtype('int64')
  2. 建立陣列 建立填滿 0 或 1 的陣列:

    np1 = np.zeros([2, 3]) # array([[ 0.,  0.,  0.], [ 0.,  0.,  0.]])
    np2 = np.ones([2, 3]) # array([[ 1., 1., 1.], [ 1., 1., 1.]])

 從零開始學資料科學:Numpy 基礎入門

  1. 陣列索引與切片 一維陣列操作和 Python 原生 list 類似:

    np3 = np.array([1, 2, 3, 4, 5, 6])
    print(np3[2]) # 3

    二維陣列:

    np3 = np3.reshape([2, 3])

    print(np3[1, 0]) # 4

 從零開始學資料科學:Numpy 基礎入門

  1. 基本操作 使用布林遮罩來取值:

    np3 = np.array([1, 2, 3, 4, 5, 6])
    print(np3 > 3) # [False False False True True True]
    print(np3[np3 > 3]) # [4 5 6]

    加總:

    np3 = np3.reshape([2, 3])
    print(np3.sum(axis=1)) # 將 axis=1 橫向加總 [6 15]

總結

以上介紹了 Numpy 的基礎知識,建立了基本的 array 和 ndarray 的觀念。相信在熟悉 Numpy 之後 Pandas 的學習將會比較容易 (Pandas 的資料容器 DataFrame、Series 事實上是奠基在 Numpy 的陣列上)

延伸閱讀

  1. 7 Steps to Mastering Machine Learning With Python
  2. [python] numpy axis概念整理筆記
  3. Python科学计算:numpy

(image via berkeleycodingeekcornellscipy-lectures

用 Python 自學資料科學與機器學習入門實戰:入門導論

· 閱讀時間約 9 分鐘
Python 資料科學系列教學

本文是 Python 資料科學與機器學習系列 的第一篇文章:

  1. Python 資料科學入門介紹 (本文)
  2. NumPy 基礎教學
  3. Pandas 基礎入門
  4. Matplotlib 資料視覺化
  5. Scikit-learn 機器學習

📚 查看完整系列

 如何使用 Python 學習機器學習(Machine Learning)

隨著資料科學(Data Science)技術的興起,人工智慧(Artificial Intelligence)機器學習(Machine Learning) 成為近幾年來電腦科學界十分熱門的研究領域,如今在實體和線上的學習機器學習的資源有很多,本文整理了一些好用學習資源希望幫助初學者能更容易使用 Python 入門機器學習的領域中,從零開始學習機器學習。若是對於資料科學不熟悉的讀者可以先參考適用於初學者的資料科學影片 ,讓自己對於資料科學有初步的認識。

 如何使用 Python 學習機器學習(Machine Learning)

「人工智慧」(Artificial Intelligence)這專有名稱正式出現在西元 1956 年,在美國達特茅斯學院 (Dartmouth College)召開的第一次人工智慧會議。根據維基百科的定義,人工智慧係指由機器所展現的智慧,一般而言人工智慧又分為「強人工智慧」(Strong AI)和「弱人工智慧」(Weak AI) 兩種不同的主張。所謂的強人工智慧指的是有自我意識、有知覺可以自己推理和解決問題的機器智慧,而「弱人工智慧」只能模擬人類的思維與行為表現,但缺乏真正的推理與解決問題的能力,也不具有自主意識。人工智慧在歷史上經歷了幾次熱潮和寒冬,從最早的邏輯推理到後來的專家系統,再到目前的機器學習/深度學習,機器學習可以視為人工智慧的一個實現方式或是發展的一個歷程。

事實上,人工智慧或是機器學習都是一門跨領域的學門,牽涉了電腦科學、數學、神經學、心理學、經濟學、統計學等層面,也有許多相關的學門:

 如何使用 Python 學習機器學習(Machine Learning)

隨著運算資源(雲端運算、GPU 等)、海量資料(目前還有許多資料還沒被創造,等待我們去發掘呢)以及機器學習/深度學習的發展,生活上許多產品已經可以看到人工智慧的應用。但人工智慧最美好的境界莫過於人機之間的互動以及相輔相成,以 AlphaGO 為例,雖然人類在圍棋領域輸給人機器,但也從機器的思考方式去重新思考了圍棋的真諦和有別於人類的思考方式。

「就因為某樣東西思考的方式跟你不一樣,就代表它沒在思考嗎?」 "Just because something thinks differently from you, does it mean it’s not thinking?" ---《模仿遊戲》《Imitation Game》(2015)

 如何使用 Python 學習機器學習(Machine Learning)

什麼是機器學習(Machine Learning)?

機器學習是一種資料科學的技術也是一種實現人工智慧的一種方式,協助電腦從現有的資料學習,以便預測未來的行為、結果和趨勢。根據學習的方式又可以分為需要解答的監督式學習(Supervised learning)非監督式學習(Unsupervised learning)增強學習(Reinforcement learning)等(還有一種混合式的半監督式學習)等子類別。機器學習技術可以應用的範圍十分廣泛,總的來說機器學習可以解決以下幾種問題:

  1. 分類問題:這是 A 類 或 B 類嗎?

  2. 異常值判斷:這很奇怪嗎?

  3. 預測性分析:有多少?

  4. 分群問題:這是如何組織的?

  5. 增強學習協助決策:我接下來該怎麼辦?

當我們蒐集到相關、精確、連貫、足夠資料就可以挑選合適的演算法進行模型的的建置。

為什麼選擇 Python?

在資料科學和機器學習領域最重要的兩大程式語言就是 Python 和 R,Python 簡潔易學、應用範圍廣(不限於數據分析)且學習曲線平緩,適合作為第一個入門的程式語言,透過 pandas、SciPy/NumPy、sckikit-learn、matplotlib 和 statsmodels 可以進行數據分析的工作,適合工程任務和需要和網路應用程式整合的專案。至於 R 由於是統計學家開發的程式語言,則是擅長於統計分析、圖表繪製,常用於學術研究領域,建議也要有一定程度的掌握。一般情況下 Python 和 R 並非互斥,而是互補,許多資料工程師、科學家往往是在 Python 和 R 兩個語言中轉換,小量模型驗證、統計分析和圖表繪製使用 R,當要撰寫演算法和資料庫、網路服務互動等情況時在移轉到 Python。為了降低學習成本。

此外 Python 本身是一種通用語言,除了資料科學外也可以廣泛使用在網路開發、網站建置、遊戲開發、網路爬蟲等領域,當你需要整合系統產品服務時,可以擔任一站式的開發語言,更重要的是 Python 也可以當成膠水語言非常輕易和 C/C++ 等效能較佳的語言整合。簡而言之,Python 是一種簡潔易學但功能強大,值得投資的程式語言,所以我們這邊先使用 Python 進行介紹。

若對於 Python 和 R 比較,這邊有兩篇文章可以參考 数据科学界华山论剑:R与Python巅峰对决Which is better for data analysis: R or Python?

如何開始入門機器學習?

事實上,資料科學是個跨領域學門,在學習如何使用 Python 進行機器學習過程中通常必須掌握以下知識:

  • 機器學習演算法
  • Python 程式語言和資料分析函式庫
  • 線性代數/統計學等相關學門
  • 專業領域的領域知識(Domain Knowledge)

為了掌握以上三大領域知識(我們先把焦點放在機器學習核心技法,暫時忽略資料科學中對於領域知識的掌握),具體來說我們可以有以下步驟可以參考:

  1. 掌握基礎 Python 程式語言知識

    線上學習資源:

  1. 了解基礎數學/統計學和機器學習基礎知識
  1. 知道如何使用 Python 科學計算函式庫和套件

    推薦安裝 Anaconda,支援跨平台多種版本 Python,預設將數據分析、科學計算的套件裝好,自帶 spyder 編輯器、Jupyter Notebook(IPython Notebook),可以提供一個網頁版介面,讓使用者可以透過瀏覽器進行 Julia、Python 或 R 程式的開發與維護。

  1. 使用 scikit-learn 學習 Python 機器學習應用
  1. 運用 Python 實作機器學習演算法
  • 感知器
  • 決策樹
  • 線性迴歸
  • k-means 分群
  1. 實作進階機器學習演算法
  • SVM
  • KNN
  • Random Forests
  • 降低維度
  • 驗證模型
  1. 了解深度學習(Deep Learning)在 Python 的實作和應用

總結

以上整理了一些機器學習網路學習資源,若你累積一些小小經驗後,不妨挑戰一下 Kaggle 或是 KDD 測試一下自己的實力並累積更多數據分析的經驗。

延伸閱讀

  1. 7 Steps to Mastering Machine Learning With Python
  2. 人人都可成為資料科學大師!一整年的網路自學清單就在這了
  3. Analytics Vidhya
  4. 台灣資料科學年會
  5. 「2016 台灣資料科學愛好者年會」精彩資料總整理(持續更新中)
  6. 大數據會消失,資料科學不會!你該知道的資料科學第一堂課
  7. 如何選擇 Microsoft Azure Machine Learning 的演算法
  8. Microsoft Azure Machine Learning 機器學習服務文件
  9. Kdnuggets
  10. Bigdatafinance
  11. Using Python and R together: 3 main approaches
  12. 机器学习最佳入门学习资源
  13. 机器学习(Machine Learning)&深度学习(Deep Learning)资料(Chapter 1)
  14. SIRAJ RAVAL'S DEEP LEARNING

(image via respondr

用 Python 自學程式設計:list、tuple、dict and set

· 閱讀時間約 6 分鐘

Python 自學程式設計:程式設計思維入門

Markdown 是一種輕量級的標記語言,最初為 John Gruber 所設計。Markdown 特色在於允許人們「使用易讀易寫的純文字格式編寫文件,然後轉換成有效的 HTML 文件」。簡而言之,Markdown 就是一種簡潔易懂的語法,讓我們可以專注在內容上,不用花時間思考外觀樣式,在透過轉換變成可以呈現在網頁上的 HTML 語法。目前在許多知名技術/開發者論壇或是開發者工具(例如:Github)、技術部落格工具都有支援 Markdown 語法。

什麼是 HTML?

在開始學習 Markdown 之前我們先來認識一下 HTML,畢竟 Markdown 最終還是要轉換成 HTML 這個網頁上內容結構的標準語法。HTML 中文稱作超文本標記語言(英文全名為 HyperText Markup Language,簡稱 HTML),是一種用於建立網頁的標準標記語言。

這樣講起來有點抽象,事實上我們每天在觀看瀏覽的網頁就是由一個個 HTML 所組成。所以我們可以透過瀏覽器的檢視原始碼功能去一窺目前網頁的 HTML 樣貌。

這邊我們使用 Google Chrome 瀏覽器當作範例,可以在畫面中點選右鍵 > 檢視原始碼(View Page Source):

就可以看到該網頁的 HTML 內容:

網頁來源:Wikipedia HTML 頁面

由於這個網頁已經有點複雜,因為它已經包含了 CSS 外觀樣式語法和 JavaScript 互動邏輯程式的部分,對於初學者來說比較難一眼理解。所以我們用一下範例來介紹 HTML 最基礎的部分:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>我是標題</h1>
<p>我是段落</p>
<a href="https://zh.wikipedia.org/zh-tw/Markdown">我是超連結</a>
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/HTML.svg/200px-HTML.svg.png" alt="">
</body>
</html>

若是使用瀏覽器打開這個 HTML 網頁會呈現:

HTML 標籤語法每個標籤皆有其意義且大部分成對出現,標籤元素內可以設定屬性值。網頁元素主要放置於 <body></body> 中,<head></head> 內主要放置 meta data 設定檔案和放置引入的外觀樣式檔案、程式邏輯等。元素內可以透過設定屬性值(attribute)來宣告元素功能,以下 href="https://zh.wikipedia.org/zh-tw/Markdown" 代表點擊該連結會到該 wikipedia 網址。

<!-- href 是屬性,決定連結點擊後目的地 -->
<a href="https://zh.wikipedia.org/zh-tw/Markdown">我是超連結</a>

<!-- src 是屬性,決定載入圖片位置-->
<img src="https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/HTML.svg/200px-HTML.svg.png">

元素包裹內容在內,代表標題元素:

<h1>我是標題</h1>

Markdown 常見語法教學

一般 Markdwon 段落以空白行分隔。若是序列則內容需要內縮(一個 tab)。

標題

是一级標題
=======

# 一級標題
## 二级標題

其 HTML 元素為:

<h1>是一级標題</h1>
<h1>一級標題</h1>
<h2>二级標題</h2>

效果如下:

是一级標題

一級標題

二级標題

文字

_斜體_
**粗體**
`等寬字型Monospace`

其 HTML 元素為:

<em>斜體</em>
<strong>粗體</strong>
<code>等寬字型Monospace</code>

效果如下:

斜體 粗體 等寬字型Monospace

多行程式碼

其 HTML 元素為:

<pre>
<code>
<span>print('hello world')</span>
</code>
</pre>

效果如下:

print('hello world code :)')

水平線

---

其 HTML 元素為:

<hr>

效果如下:


無序列表

* 張三
* 李四
* 王二

其 HTML 元素為:

<ul>
<li>張三</li>
<li>李四</li>
<li>王二</li>
</ul>

效果如下:

  • 張三
  • 李四
  • 王二

有序列表

1. 不論
2. 三七
3. 二十一

有序列表,其 HTML 元素為:

<ol>
<li>不論</li>
<li>三七</li>
<li>二十一</li>
</ol>

效果如下:

  1. 不論
  2. 三七
  3. 二十一

巢狀有序列表

1. 不論
- 第一
- 第二
- 第三
2. 三七
1. 第一
2. 第二
3. 第三
3. 二十一

有序列表,其 HTML 元素為:

<ol>
<li>不論
<ul>
<li>第一</li>
<li>第二</li>
<li>第三</li>
</ul>
</li>
<li>三七
<ol>
<li>第一</li>
<li>第二</li>
<li>第三</li>
</ol>
</li>
<li>二十一</li>
</ol>

效果如下:

  1. 不論
    • 第一
    • 第二
    • 第三
  2. 三七
    1. 第一
    2. 第二
    3. 第三
  3. 二十一

超連結

[連結文字](連結網址)

其 HTML 元素為:

<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/8/84/HTML.svg/200px-HTML.svg.png">連結文字</a>

效果如下:

連結文字

圖片

![文字屬性](Icon-pictures.png "文字標題")

其 HTML 元素為(少數沒有成對出現的元素標籤):

<img src="連結網址" alt="文字屬性" title="文字標題" />

效果如下:

圖片文字

注釋引用

> Markdown使用電郵用字元「>」來引用。

其 HTML 元素為:

<a href="連結網址">連結文字</a>

效果如下:

Markdown 使用電郵用字元「>」來引用。

表格

| Column 1 | Column 2 | Column 3 |
| -------- | -------- | -------- |
| Text | Text | Text |

其 HTML 元素為:

<table>
<thead>
<tr>
<th>Column 1</th>
<th>Column 2</th>
<th>Column 3</th>
</tr>
</thead>
<tbody>
<tr>
<td>Text</td>
<td>Text</td>
<td>Text</td>
</tr>
</tbody>
</table>

效果如下:

Column 1Column 2Column 3
TextTextText

總結

以上簡單介紹了:

  1. 什麼是 HTML?
  2. Markdown 常見語法教學

以上介紹了 HTML 和 Markdown 基礎語法的教學,透過 Markdown 這一種簡潔易懂的語法,我們可以更專注在內容創作上。對於一個自學程式設計新手而言,培養撰寫文章的習慣(例如:建立自己的技術部落格)是很重要的環節,不但可以累計自己經歷也可以強化記憶並幫助到需要的人。若是需要完整語法介紹可以參考markdown.tw,當然,只要多加練習就可以慢慢掌握 Markdown 語法的訣竅,進而喜歡這種簡潔的書寫方式。

參考文件

  1. Github Basic writing and formatting syntax
  2. markdown.tw
  3. markdown wiki

用 Python 自學程式設計:list、tuple、dict and set

· 閱讀時間約 5 分鐘

Python 自學程式設計:程式設計思維入門

在前一單元中我們了解了變數和 Python 世界物件的重要性,也介紹了簡單的資料型別,我們也有提到簡單資料型別(布林、整數、浮點數和字串)就像是原子一樣,而複雜資料型別就像是分子一樣,在這一單元中我們將更進一步了解 Python 複雜的資料型別以及如何操作它們。

串列 list 與元組 tuple

在程式語言中通常可以利用序列式方式去記錄資料,在 Python 中,我們使用 list 串列和 tuple 元組來儲存序列式資料。兩者最大的不同在於 tuple 是不可以改變的。

  1. 串列 list 串列是一連串順序性的元素組成,我們可以新增、讀取、刪除和修改串列,串列中可以有重複的元素。

    • 建立串列

    串列可以透過中括號或是使用 list 關鍵字來創建,裡面元素由逗號分隔

    my_list0 = []
    my_list1 = list()
    my_list2 = ['python', 'js', 'SQL']

    list('js')
    # ['j', 's']
    • 使用 index offset 和範圍來取得元素

    在電腦科學世界,index 通常是從 0 開始,-1 從結尾數回來:

    languages = ['python', 'js', 'go']
    languages[0] # python
    languages[1] # js
    languages[-1] # go

    範圍取值 [開始:結束(不含):間隔(default 1)]:

    languages = ['python', 'js', 'go']
    my_list2[0:1] # ['python']
    • append 元素到串列最後
    languages = ['python', 'js', 'go']
    languages.append('java')
    • extend 串連串列
    languages = ['python', 'js', 'go']

    languages.extend('c++') # ['python', 'js', 'go', 'c++']

    languages += ['ruby', 'c'] # ['python', 'js', 'go', 'c++', 'ruby', 'c']
    • insert 插入元素到位置上
    languages = ['python', 'js', 'go']
    languages.insert(0, 'java') # ['java', 'python', 'js', 'go']
    • del 刪除特定 index 值
    languages = ['python', 'js', 'go']

    del languages[-1] # ['python', 'js']

    • len() 元素長度
    len(['python', 'js', 'go']) # 3
    • in 檢查元素是否在串列
    'java' in ['python', 'js', 'go'] # False

    還有更多好用的方法,讀者可以進一步查詢使用: remove()index()count()join()、sort()、copy()

  2. 元組 tuple 元組可以視為不可改變的串列,使用方式如下:

    languages = python', 'js', 'go' # (python', 'js', 'go')
    tuple(['python', 'js', 'go'])

    元組比起串列好處:

    • 佔用空間較少
    • 可以當做字典的 key(因不可變)
    • 具名 tuple 可當做物件替代
    • 當做函式引數

字典 dict 和集合 set

  1. dict 在其他程式語言可能稱 {'key':'value'} 字典為關聯式陣列或是雜湊表,其用獨一無二不可變的鍵(布林、整數、浮點數、字串和串列)去對應值,字典通常是可變的,可以新增刪除、修改鍵值。

    • 創建 dict
    languages = {
    'name': 'python',
    'version': '3.5'
    }

    dict([('name', 'python'), ('version', '3.5')])
    • 新增和取值
    languages = {}

    languages['name'] = 'python'

    print(languages['name']) # python
    • 合併
    languages = {
    'name': 'python',
    'version': '3.5'
    }

    languages2 = {
    'name': 'js',
    'version': '6'
    }

    languages.update(languages2)
    • keys() 取得所有鍵、values() 取得所有值、items() 取得所有鍵值對
    languages = {
    'name': 'python',
    'version': '3.5'
    }

    languages.keys() # ['name', 'version']
    languages.values() # ['python', '3.5']
    languages.items() # [('name', 'python'), ('version', '3.5')]
    • 使用 in 判斷 key 是否存在 dict
    languages = {
    'name': 'python',
    'version': '3.5'
    }

    'name' in languages # True
  2. set 類似小學時候學習的數學集合,可以想成就是留下鍵值的 dict。由於 set 存不重複值。當你只想知道值是否存在就是使用 set 的時機,例如使用 in 來判斷值是否存在。

    • 建立 set
    languages = set()

    languages = {'python', 'js', 'python', 'go'}
    # {'python', 'js', 'go'}
    • 轉換成 set
    set('python') # {'p', 'y', 't', 'h', 'o', 'n'}
    set(['python', 'js']) # {'python', 'js'}
    set(('python', 'js')) # {'python', 'js'}
    • 使用 intersection 取交集,union 取聯集,difference 取差集
    languages1 = {'js', 'python', 'go'}
    languages2 = {'python', 'go', 'java'}
    languages1.intersection(languages2) # {'python', 'go'}
    languages1.union(languages2) # {'js', 'python', 'java', 'go'}
    languages1.difference(languages2) # {'js'}

整合在一起

回想一下,我們可以使用 [] 建立 list 串列,用 , 來創立 tuple 元組,使用 來建立字典。雖然建立方式不盡相同,但相同的是你都可以透過中括號來存取內容值:

languages0 = ['python', 'js'] # languages0[0]
languages1 = ('python', 'js') # languages1[0]
languages2 = {
'name': 'python',
'version': '3.5'
} # languages2['name']

總結

以上就是程式設計思維入門簡介,透過了解什麼是程式設計思維和不同語言的特性,我們將對於自學程式設計有更正確的認識。接下來我們將透過 Python 介紹程式設計的內涵和不同的應用情境。當然,網路上也有許多學習資源可以當做參考。

(image via mshcdn

延伸閱讀

  1. Python 官網
  2. JavaScript 程式設計新手村
  3. Python Web 程式設計入門實戰
  4. 非本科生,我想半路出家學寫程式,該如何開始?
  5. 自學程式設計學習資源懶人包

用 Python 自學程式設計:變數(variable)與資料型別(type)

· 閱讀時間約 7 分鐘

Python 自學程式設計:程式設計思維入門

在前一單元中我們了解了程式設計思維的概念和建立了 Python 的開發環境,在這一單元中我們將了解 Python 變數與資料型別以及如何操作字串。

電腦最初的用途就是一台超大台計算機

資料的儲存以及操作在程式設計中扮演非常重要的角色,因為最早的電腦程式就是一種大型的計算機(最早的電腦就稱為計算機),即便現在學校教授電腦科學概論往往都會把課程稱為計算機概論呢!在操作資料的過程中如何儲存資料就是非常重要的事情,一般而言資料儲存有分為暫時儲存的揮發性資料(儲存在記憶體中的變數資料)和持久性儲存的資料(例如:資料庫、檔案等),在這邊我們討論的是變數的資料。

在 Python 世界,所有東西都是物件

在 Python 世界中,所有東西都是物件,物件可以視為透明的箱子,裡面存了一些資料。物件會有自己的資料型別,決定它做什麼樣的操作。另外,又依據箱子內的值可否改變而分為不可變物件可變物件

在前面我們有提到資料可以儲存在記憶體中的變數,在 Python 中變數只是一種名稱,當給定值時不會將值複製,而是將名稱貼到給定的物件上(注意 Python 程式語言中的 = 是給定值,== 才是相等的意思)

談到資料,就不得不談一下資料型別(type),雖然在 Python 不用像 C 語言之類程式語言需要在變數前面定義資料型別(在 Python 中 class 類別和 type 類型幾乎代表同一件事情,class 類別則是定義物件的基礎),但物件的資料型別會影響資料操作,所以值得我們好好認識。在 Python 世界裡,可以分為以下幾種簡單資料型別(可以想像成化學課中的原子):

  1. bool 布林,分為 TrueFalse 通常用於條件判斷
  2. int 整數,例如: 10999999
  3. float 浮點數,係指有小數點的整數:1.2221.0e7 等同於 10 的 7 次方
  4. string 字串,一串文字字元

我們可以透過 type(物件) 去確認該物件的型別:

print(True)
print(101)
print(3.14)
print('happy coding')

另外一種是複雜資料型別(可以想像成是化學課中的分子),這個我們會在下一個單元做討論:

  1. list 串列,用於儲存一系列序列資料(可以儲存不同資料型別),類似於其他程式語言的陣列但更為強大
  2. tuple 元組,類似於 list 串列,但不同的是 tuple 給定元素後不能改變
  3. dict 字典,和串列很像但不在乎元素順序,而且不會使用 0,1,...等的序列 index 來選擇項目,反之我們必須宣告唯一的 key 鍵值來對應想儲存的 value 值
  4. set 集合,集合就像是被移除 value 值的字典,只有保留 key 鍵值,也就是說 set 的內容元素都必須是獨一無二的

物件又分可變和不可變物件

  1. 不可變物件(int, string, float, tuple),亦即若資料改變,會複製一份資料到新的記憶體空間然後資料更新,下面是一個簡單範例:

    i = 101 # 宣告一個變數將 i 便條紙貼到 101 物件
    j = 101 # 宣告一個變數將 j 便條紙貼到 101 物件
    print(id(101)) # 印出 101 物件 id,可以想成是記憶體位置
    print('i id:' + str(id(i))) # 印出 i 指向的 id,和 101 物件值相同
    print('j id:' + str(id(j))) # 印出 j 指向的 id,和 101 物件值相同
    print(i is j) # 因為兩者會貼到同一個物件所以會顯示相等,True
    j = j + 1 # 若資料改變,會複製一份資料到新的記憶體空間然後資料更新
    print('new i id:' + str(id(i))) # 印出一樣的 id
    print('new j id:' + str(id(j))) # 印出新的 id
    print(i is j) # 兩者指到不同的記憶體位置,False

    執行結果:

    140181136769920
    i id:140181136769920
    j id:140181136769920
    True
    new i id:140181136769920
    new j id:140181136769952
    False
  2. 可變物件(list, dict, set),亦即若資料改變則直接在指向的記憶體空間改變資料,下面是一個簡單範例:

    a = {} # 宣告一個變數指到一個空字典 dict
    b = a # 將 b 變數指到 a 同樣記憶體位置
    print(id(a)) # 印出 a 的 id
    print(a is b) # 兩者指到相同的記憶體位置,True
    a['a'] = 'python' # 改變 a 的鍵值
    print('id a:' + str(id(a))) # 印出 a id
    print('a:' + str(a)) # 印出內容值
    print('id b:' + str(id(b))) # 印出 b id,dict 為可變物件,印出 id 會和 a 一樣
    print('b:' + str(b)) # dict 為可變物件,印出內容值會和 a 一樣
    print(a is b) # 兩者指到相同的記憶體位置,True

    執行結果:

    140181112792336
    id a:140181112792336
    a:{'a': 'python'}
    True
    id b:140181112792336
    b:{'a': 'python'}
    True

另外,Python 支援強制轉換資料型別: 可以透過 int()、float()、str() 進行資料型別轉換

int(1.2)
float('1.3')
str('1')

字串操作好好玩

在程式設計的世界中,操作字串基本上是家常便飯,接著我們來談談在 Python 中如何進行字串的操作:

在 Python 中若要宣告字串,可以使用單引號或雙引號,會有兩種方式是因為讓開發者可以產生有 '" 內容的字串。

my_str = 'This is a "good" language!'

但要特別留意的是在 Python3 和 Python2 對於字串的支援不盡相同,在 Python 中支援 Unicode 標準。與其他程式語言不同的是 Python 字元是不可變的,不能直接改變字串,但可以將一部分字串複製到其他字串。

以下是常見字串操作方式:

  1. 宣告字串

    language = 'python'
  2. 串連字串 +

    language = 'python'
    word = 'I love'
    word + language
  3. 複製字串 *

    language = 'python'
    language * 3
  4. 選取字串 [開始:結束:間隔]

    language = 'python'
    language[0:1] # p
    language[0:-1] # pytho
    language[0:4:2] # ph
  5. len、split、join、replace 字串操作

    language = 'python'
    print(len(language)) # 印出字串長度 6
    print(language.split(3)) # 切割字串長度
    print(language.join(3)) # 切割字串長度
    print(language.replace(3)) # 切割字串長度

總結

以上我們介紹了在 Python 世界中物件是基本元素,也介紹了變數以及字串的操作,接下來我們將透過 Python 介紹程式設計的內涵和不同的應用情境以及複雜資料型別的使用。

(image via mshcdn

延伸閱讀

  1. Python 官網
  2. JavaScript 程式設計新手村
  3. Python Web 程式設計入門實戰
  4. 非本科生,我想半路出家學寫程式,該如何開始?
  5. 自學程式設計學習資源懶人包
  6. python可变和不可变对象