相信許多人初學 Python 時,常會在範例程式內看到類似的段落:

if __name__ == '__main__':
    main()  # 或是任何你想執行的函式

對於 __name__ == '__main__' 到底是什麼意思,一直存有疑問;在我的爬蟲課程的問題討論區中,也不時看到同樣的問題。如果你上網搜尋之後還是似懂非懂,這篇文章會嘗試用初學者的角度再說明一次。

首先,如果你永遠都只執行一個 Python 檔,而不引用別的 Python 檔案的話,那你完全不需要了解這是什麼。例如你寫了一個很棒的函式 cool.py

# cool.py

def cool_func():
    print('cool_func(): Super Cool!')

print('Call it locally')
cool_func()

然後你永遠都是直接執行它,像這樣:

>> python cool.py

Call it locally
cool_func(): Super Cool!

這完全沒有問題。問題會出在當你想要在別的檔案中使用你在 cool.py 中定義的函式時,例如你在相同目錄下有一個 other.py

# other.py

from cool import cool_func

print('Call it remotely')
cool_func()

當你執行 other.py 時,你應該預期只會看到 Call it remotelycool_func(): Super Cool! 兩段輸出,但實際上你看到的是:

>> python other.py

Call it locally
cool_func(): Super Cool!
Call it remotely
cool_func(): Super Cool!

看到問題了嗎?cool.py 中的主程式在被引用的時候也被執行了,原因在於:

  1. 當 Python 檔案(模組、module)被引用的時候,檔案內的每一行都會被 Python 直譯器讀取並執行(所以 cool.py內的程式碼會被執行)
  2. Python 直譯器執行程式碼時,有一些內建、隱含的變數,__name__就是其中之一,其意義是「模組名稱」。如果該檔案是被引用,其值會是模組名稱;但若該檔案是(透過命令列)直接執行,其值會是 __main__;。

所以如果我們在 cool.py 內加上一行顯示以上訊息:

# cool.py

def cool_func():
    print('cool_func(): Super Cool!')

print('__name__:', __name__)
print('Call it locally')
cool_func()

再分別執行 cool.pyother.py,結果會是:

>> python cool.py

__name__: __main__
Call it locally
cool_func(): Super Cool!

>> python other.py

__name__: cool
Call it locally
cool_func(): Super Cool!
Call it remotely
cool_func(): Super Cool!

你就可以看到 __name__ 的值在檔案被直接執行時與被引用時是不同的。所以回到上面的問題:要怎麼讓檔案在被引用時,不該執行的程式碼不被執行?當然就是靠 __name__ == '__main__'做判斷!

# cool.py

def cool_func():
    print('cool_func(): Super Cool!')

if __name__ == '__main__':
    print('Call it locally')
    cool_func()

執行結果是:

>> python cool.py

Call it locally
cool_func(): Super Cool!

>> python other.py

Call it remotely
cool_func(): Super Cool!

問題就完美解決了!最後一點要說明的是,之所以常看見這樣的寫法,是因為該程式可能有「單獨執行」(例如執行一些本身的單元測試)與「被引用」兩種情況,因此用上述判斷就可以將這兩種情況區分出來。希望這篇文章有解答到你的疑問。

參考資料: https://docs.python.org/3/library/__main__.html https://stackoverflow.com/questions/419163/what-does-if-name-main-do


有聽過 HTTP 跟 RESTful API 嗎?你知道 HTTP 協定的主要設計者及 REST 架構的發明人是哪裡畢業的博士嗎?UC Irvine

有聽過 DNS 嗎?你知道 DNS 的共同發明人是哪裡畢業的博士嗎?UC Irvine

你知道 Kobe Bryant 曾經被目擊到在那間學校的體育館自主練習?你知道全美唯一校內附設網咖的大學是哪一家? UC Irvine

你知道 Blizzard, Broadcom, WD 這些公司的總部,以及 BenQ 跟 Toshiba 的北美總部在哪裡嗎?Irvine (好啦 BenQ 其實在隔壁的 Costa Mesa)

你知道哪個城市連續 11 年蟬聯全美最安全城市?哪個城市總是在全美最宜居城市最適合養小孩城市最佳戶外活動城市榜上有名?當然還是 Irvine

所以來 UCI 還需要什麼理由嗎 :)

好啦,正題開始,這篇文章是給打算出國唸書的人,為什麼要到 UCI 念 CS/CE/HCI,尤其是作軟體工程研究的理由。當然如果你已經錄取了大家都叫得出名字的傳統名校,我不認為這篇文章能夠說服你 (或是當初的我自己) 來 UCI,但如果你的落點在這附近,或你申請時沒有考慮過 UCI,這篇文章可以提供一些資訊。由於我是 Informatics Dept. 下的 Software Engineering program 博士生, 我會對自己的 program 著墨最多,也會提及其他 CS 相關領域的情況。

硬指標:研究發表

博士生的主要工作就是做研究及發 paper, 在 CS 領域, 發 top conference paper 又比 journal paper 重要 (或至少一樣重要)。當然許多大師說過 Paper is cheap, 我們應該專注在改變世界、影響人類生活的 idea. 我完全贊同,但是我們不是大師,身為學術圈浮游生物的我們,還是只能功利點多發幾篇 paper, 才能畢業跟找到工作,因此選擇一個 productive 的環境就很重要。如果你已經確定有興趣的研究領域,我推薦要選校的人直接看 csrankings.org 的排名跟教授名單。大學排名百百種,csrankings.org 的特色就是它是依照完全的硬指標:在頂級會議的發表篇數,比如說 AI 各領域的頂級會議: ICML, CVPR, AAAI 等,發表多的學校就排名前面,完全跟其他因素如學校名聲,師生比,校園規模無關。在這邊你會看到 UCI 的 overall ranking in the US 是 23,應該比其他機構排出來的名次還前面一些;更令人驚訝的是,在軟體工程領域,UCI 是全美第 2!代表這邊的教授非常積極在軟工的頂級會議 (ICSE/FSE) 發 paper,相對地對你畢業也會較有幫助,這是一般的綜合排名看不到的資訊;另外,UCI Informatics Dept. 除了一小群軟體工程的教授之外,我感覺整個系都在做人機互動/人機介面的研究,所以你會看到 UCI 在 HCI 領域的發表也高居全美第 4。除了 SE 與 HCI,我們 ICS school 在其他 CS 相關領域例如 Machine learning 或 Bioinformatics 的研究也都是有名氣的。不管你對哪個 CS 相關領域有興趣,選校時都可以參考這個網站。

Software Engineering program/faculty at UCI

UCI 的軟體工程 program,不管是在台灣或美國都相對少見,能夠把軟體工程獨立成一個 program, 代表這裡不管是相關課程的廣度,或 faculty 的數量及研究深度都超過其他學校。舉例來說,軟體工程在台灣大多就是一堂大學部的選修課,當然有少數學校像是中央軟工所可能會有比較多課程,但 UCI SE program 的 curriculum 可是洋洋灑灑將近 30 堂課(當然有許多是與 CS 合開),很多課都是我在台灣的資工系沒看過的。再者,這邊軟工研究群的五個教授, 就有兩個是 ICSE 2018 Technical paper 的 program committee,加上前一段提過的頂級會議發表量,都證明了這邊 faculty 的研究影響力,如果你需要發 paper,來這邊抱大腿是個好選擇,常言道:站在浪頭上,豬也能飛上天。

找 intern 及就業情況

出國唸書的人以碩士生為大宗,因為我是博士生,並沒有第一個暑假就要急著找 intern 的壓力,加上我又是系邊 (i.e., 系上邊緣人),對於碩士生找 intern 及就業情況了解得不多,但還是能夠提供一些我周遭朋友的個案:

SE program 的博士生方面,我們 lab 今年要畢業的博士生去過兩次 Google intern, 已拿到 return offer; 明年要畢業的博士生去過 Intel intern;J 教授今年畢業的學生去過 MS intern, 畢業後要回 MS, 另一個博士生這個暑假去 Google intern; R 教授的博士生今年去了 Uber intern; L 教授的學生今年去了一間 startup 做 intern,他太太也是 UCI CS 的碩士畢業生,在學時有做過 intern,現在在 startup 工作;其他 CS 博士生方面,一個做 embedded system 的朋友連續兩年暑假在 startup intern,也拿到了 return offer,另一個做 deep learning 的朋友也在 MS, 百度做過 intern. 碩士生方面,一個韓國朋友今年在 Amazon intern,一個台灣朋友在 Sandisk intern,以上的個案至少有一半以上是拿學生簽證,沒有身份的。當然,我已經說過我是系邊,所以找到 intern/工作的人數絕對比我知道的多得多,但是我也認為找工作是個人造化,就算我提供再多個案,跟你/我能不能找到工作也不會有太多關聯,因為找 CS 相關工作的 SOP 都已經很制式化了(刷題/修履歷/找內推/海投),也跟你是否有身份,業界景氣,還有運氣有很大的關係,但至少 UCI 的學位是有能見度的,我們的 career fair 規模頗大,Google, Facebook 也都有來辦 info session.

結語

軟體工程不是個熱門的研究領域,如果你也對軟體工程研究有興趣,希望這篇文章能提供你多一個選擇;如果你是要出國念 CS/CE/HCI,UCI 不管是在生活機能、研究環境或就業機會,都不會讓你失望。


170827

之前的文章已經提過,我對於這邊的資格考筆試非常苦惱,因為它不是考你數學或演算法等專業科目,反倒像作文比賽,考你建立答題框架與論述的能力。簡單來說,我們有一份 reading list,裡面有約 50 篇軟體工程各領域的經典文獻,你必須先讀完(可以透過修兩個 quarter 的討論課來讀及與同學教授討論),然後在考試時回答一些大哉問的問題,表現出你有架構問題及引用文獻的能力。考試分成早上下午各 3 小時,早上回答兩題必答題,下午回答兩題 8 選 2 的選答。考試結果有 PhD Pass, Master Pass 及 Fail 三種 (沒錯,UCI 的 Software Engineering program 碩士畢業也要考這個筆試,或是選擇寫論文)。今年我回答的題目如下:

  1. 敏捷式開發流程已經征服了全世界,為什麼?既然我們崇尚「快速產出雛型再根據反饋修改」的流程,那幾十年來在軟體開發流程,分析,架構,測試等子領域上的軟體工程研究,究竟有什麼意義?有哪些研究為實務打下了基礎?又有哪些研究是「沒用」的?
  2. 不同的軟體工程研究方法 (質化與量化的各種方法,如問卷、數據分析、理論推導、訪談、個案研究等),各有什麼優缺點?舉出幾個例子說明哪些研究子領域特別適合哪些研究方法 (例如 Usability 的研究特別適合用訪談或問卷,Formal verification 特別適合用理論推導等);舉出一個在文獻上很少搭配在一起的研究領域及研究方法,但你覺得應該要搭配的理由。
  3. 有許多的軟體架構框架 (e.g., Spring, Django, Android) 被提出用來增加工程師的生產力,但同時也引入了新的問題,例如框架的 bug, 安全漏洞,及誤用等,你覺得這些問題的原因何在?有哪些研究領域能夠幫助 framework 的設計者與使用者緩解這些問題?
  4. 研究者對於什麼是好的研究方法 (或說什麼才叫做知識) 有不同的立場。有些人認為:根據可觀察及量測的事實現象推演而來的,才叫做知識,推演過程及結果不因人而異;有些人認為:知識形成的過程不能抽離應用該知識的人與環境,什麼叫做「有用」是見仁見智的。討論這兩種看法的哲學立場,並舉出一個可以同時應用這兩種立場的研究領域。

每個問題有一個半小時,如果是你,會怎麼回答這些問題?光是第一題就要你質疑自己作研究的意義,其他題目則是研究方法與哲學立場的探討。坦白說,對於 Native speaker 且有許多實務經驗的人來說,可能不太需要熟讀文獻就能行雲流水的寫出想法,但我只能戰戰兢兢的準備。

讀這些東西有用嗎?這剛好呼應了考試的題目:什麼叫做「有用」?怎麼定義有沒有用? 一方面來說,我之前有講過這個考試對自己的研究領域不一定有幫助,而且早期的文獻 (8, 90 年代) 多半還在爭論「軟體工程」作為一門 engineering discipline 的正當性,當時的爭論在今天答案已經很明顯。但另一方面,這樣的考試對於非英文母語的我來說,是練習讀寫及思考的大好機會,這也是研究的基礎能力;再者有些文獻是我的研究領域一輩子也不會讀到的,讀這些 paper 目前看來沒用,但總是增加了知識廣度,哪一天可能會派上用場。因此我還是很高興有機會準備這個考試。


本文範例程式, hahow_courses.json

本文講解兩件事:

  1. 如何爬取 hahow 所有已開課課程資料
  2. 計算募資價/上線價/課程長度/學生數的統計資料 (平均值),及前三者與學生數的相關性 (是否定價越低/長度越長則學生數越多?)

Pycone 松果城市 (網站, 粉絲頁) 是致力於對初學者友善的 Python 教學團隊,除了已經開的初心者課程爬蟲課程外,陸續還有新課程在籌備中。而一門課的定價該怎麼定,大家往往有不同的意見,有人認為技術有價,不能破壞行情,且越少見的課應該越貴;有人認為較低定價可以吸引更多學生。與其靠經驗或直覺,不如讓數據說話!我們何不直接分析 hahow 上程式類課程的平均價格及各項係數與學生數的相關性?

爬取 hahow 所有已開課課程資料

身為一個懶人,寫爬蟲前第一件事當然是看 hahow 有沒有提供打包下載的課程資料或可存取的公開 API,簡單搜尋之後沒有收穫,只好從 hahow 的課程列表下手。在課程列表的網頁你會發現,這個網頁並不會一次回傳所有課程,而是隨著瀏覽器捲軸下拉,逐漸顯示更多課程。通常這種網頁多是透過 AJAX 與網站主機做非同步的溝通與資料傳輸,打開開發者工具瀏覽一下之後,很快找到了可能的 API

2017-07-25-1

2017-07-25-2

把該網址的 response 貼到 online JSON parser 驗證,果然就是課程資料

2017-07-25-3

接著繼續觀察畫面捲動時是透過什麼 API 取得更多課程資訊,最後確定了:

  1. 一開始先透過 GET https://api.hahow.in/api/courses?limit=12&status=PUBLISHED 取得最初的 12 筆資料 (經測試一次最多可以取 30 筆)
  2. 接著一樣透過 GET 回傳目前最後一筆課程的 id 與募資時間,取得接下來 12 筆課程資料,直到沒有資料為止

不得不說 hahow 工程師的 API 寫得滿好的,很簡單易用 (雖然他們並沒有要給大家用 XD),因此對應的爬蟲程式邏輯也很簡單

def crawl():
    # 初始 API: https://api.hahow.in/api/courses?limit=12&status=PUBLISHED
    # 接續 API: https://api.hahow.in/api/courses?latestId=54d5a117065a7e0e00725ac0&latestValue=2015-03-27T15:38:27.187Z&limit=30&status=PUBLISHED
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
                             'AppleWebKit/537.36 (KHTML, like Gecko) '
                             'Chrome/59.0.3071.115 Safari/537.36'}
    url = 'https://api.hahow.in/api/courses'
    courses = list()
    resp_courses = requests.get(url + '?limit=30&status=PUBLISHED', headers=headers).json()
    while resp_courses:  # 有回傳資料則繼續下一輪擷取
        time.sleep(3)  # 放慢爬蟲速度
        courses += resp_courses
        param = '?latestId={0}&latestValue={1}&limit=30&status=PUBLISHED'.format(
            courses[-1]['_id'], courses[-1]['incubateTime'])
        resp_courses = requests.get(url + param, headers=headers).json()
	# 將課程資料存下來後續分析使用
    with open('hahow_courses.json', 'w', encoding='utf-8') as f:
        json.dump(courses, f, indent=2, sort_keys=True, ensure_ascii=False)
    return courses

將所有課程擷取下來後,我們看到每一筆課程資料內容如下:

{
    "_id": "58744feda8aae907000d06c0",
    "categories": [
      "55de81ac9d1fa51000f94770",
      "55de81929d1fa51000f94769"
    ],
    "coverImage": {
      "_id": "588421e46ecf3a0700b7a31d",
      "url": "https://hahow.in/images/588421e46ecf3a0700b7a31d"
    },
    "incubateTime": "2017-02-09T05:45:14.673Z",
    "metaDescription": "你想自動擷取網站上的資料嗎?你學了 Python 卻不知道該從什麼程式開始練習嗎?這堂課就是為你準備的!本課程會循序漸進地說明如何撰寫 Python 網頁爬蟲,從環境設定開始,涵蓋網頁解構、資料擷取與儲存,及多項實戰演練,讓你在學習過程中及對於學習成果都有滿滿的成就感。",
    "numSoldTickets": 514,
    "owner": {
      "_id": "58744a86a8aae907000d0684",
      "name": "Jun-Wei Lin",
      "profileImageUrl": "https://hahow.in/images/58744c3ca8aae907000d0697",
      "username": "junwei"
    },
    "preOrderedPrice": 990,
    "price": 1890,
    "proposalDueTime": "2017-03-11T00:00:00.000Z",
    "reviewing": false,
    "status": "PUBLISHED",
    "successCriteria": {
      "numSoldTickets": 50
    },
    "title": "Python 網頁爬蟲入門實戰",
    "totalVideoLengthInSeconds": 15290,
    "type": "COURSE",
    "uniquename": "python-web-crawler"
}

各欄位的名稱都很直覺,唯一就是課程的分類 (categories) 代碼意義不明,此時只要觀察一下各類課程的連結就可以知道代碼

2017-07-25-4

計算各項係數之統計資料與相關性

收集資料是為了分析資料並進一步回答問題。我們的問題是:程式類課程的平均價格、課程長度及學生數為多少?各項係數是否與學生數有相關性?相較於之前的文章中直接寫程式計算數據,這邊我們改用 numpy 來計算,只要將感興趣的資料分別存成 list,就能夠用 numpy 直接計算統計資料

with open('hahow_courses.json', 'r', encoding='utf-8') as f:
    courses = json.load(f)
	
# 取出程式類課程的募資價/上線價/學生數,並顯示統計資料
pre_order_prices = list()
prices = list()
tickets = list()
lengths = list()
for c in courses:
    if '55de81ac9d1fa51000f94770' in c['categories']:
        pre_order_prices.append(c['preOrderedPrice'])
        prices.append(c['price'])
        tickets.append(c['numSoldTickets'])
        lengths.append(c['totalVideoLengthInSeconds'])
		
print('程式類課程共有 %d 堂' % len(prices))  # 23
print('平均募資價:', np.mean(pre_order_prices))  # 719.09
print('平均上線價:', np.mean(prices))  # 1322.57
print('平均學生數:', np.mean(tickets))  # 483.22
print('平均課程分鐘:', np.mean(lengths)/60)  # 515.12

corrcoef = np.corrcoef([tickets, pre_order_prices, prices, lengths])
print('募資價與學生數之相關係數: ', corrcoef[0, 1])  # 0.18
print('上線價與學生數之相關係數: ', corrcoef[0, 2])  # 0.36
print('課程長度與學生數之相關係數: ', corrcoef[0, 3])  # 0.65

我們可以看到目前 23 堂程式類課程的平均募資價 (720) 與上線價 (1320),而令人意外的是募資價與學生數並沒有太大的相關性 (不是募資價越低學生就越多),反倒是課程長度與學生數呈現滿強的正相關。而我們在之前的文章已經提過,相關性並不代表因果關係,同時很明顯地,其他非數據的因素如講師名氣、文案內容、影片生動度等對於吸引學生也非常重要,因此這些數據只是幫助決策的參考資訊。


本文範例程式, example.json

這篇文章會示範簡單的統計分析 (平均值與相關係數) 與資料視覺化 (histogram 與 scatter plot),最後會淺談資料科學的三個面向作為本系列文章總結。

藉由之前的範例程式,我們已經有了今天 PTT Beauty 板所有貼文的一些資訊。假設我們想進一步認識或分析手上的數據,或對資料維度的相關性作些假設,就需要統計分析與視覺化的幫助。例如我們對貼圖數與推文數有興趣,且假設「文章內有越多貼圖會得到越多推」,第一步先將資料從 example.json 讀入之後,馬上就能得知它們的極值:

with open('example.json', 'r', encoding='utf-8') as f:
    data_list = json.load(f)
    images = []
    pushes = []
    for d in data_list:
        images.append(d['num_image'])
        pushes.append(d['push_count'])

print('圖片數:', images, 'Max:', max(images), 'Min:', min(images))
print('推文數:', pushes, 'Max:', max(pushes), 'Min:', min(pushes))

# 圖片數: [3, 7, 1, 12, 9, 1, 2, 13, 0, 5, 27, 5, 1, 8, 0, 1, 14, 2, 3, 2, 1, 25, 3, 14, 27, 2] Max: 27 Min: 0
# 推文數: [18, 20, 0, 0, 3, 6, 2, 12, 1, 13, 11, 5, 0, 20, 1, 7, 6, 2, 2, 0, 0, 32, 10, 13, 9, 2] Max: 32 Min: 0

平均值與相關係數

有了原始資料的 list, 平均值的計算也很容易,

def mean(x):
    return sum(x) / len(x)

print('平均圖片數:', mean(images), '平均推文數:', mean(pushes))

# 平均圖片數: 7.230769230769231 平均推文數: 7.5

接著我們想知道是否「文章內有越多貼圖會得到越多推」,一個方式是計算相關係數,相關係數是共變異數 (covariance) 除以標準差 (standard deviation) 的乘積,公式可參考此處。因此,除了平均值之外,我們還需要計算偏差值 (deviation), 變異數 (variance) 與內積 (dot) 的函式

def de_mean(x):
    x_bar = mean(x)
    return [x_i - x_bar for x_i in x]


def variance(x):
    deviations = de_mean(x)
    variance_x = 0
    for d in deviations:
        variance_x += d**2
    variance_x /= len(x)
    return variance_x


def dot(x, y):
    dot_product = sum(v_i * w_i for v_i, w_i in zip(x, y))
    dot_product /= (len(x))
    return dot_product

有了相關函式後,相關係數可依公式計算

def correlation(x, y):
    variance_x = variance(x)
    variance_y = variance(y)
    sd_x = math.sqrt(variance_x)
    sd_y = math.sqrt(variance_y)
    dot_xy = dot(de_mean(x), de_mean(y))
    return dot_xy/(sd_x*sd_y)

print('相關係數:', correlation(images, pushes))

# 相關係數: 0.5258449106844523

相關係數是 -1 到 1 之間的值,越接近 1 代表兩個維度越接近線性正相關,反之則為線性負相關。這個例子中的 0.5258 代表一定程度的正相關,看到這邊你一定有疑問:推文數怎麼可能被貼圖數決定?難道我貼一堆海綿寶寶圖也會被推爆嗎?當然不可能,而這個例子也引出了你可能聽過的說法:相關不代表因果 (correlation is not causation)。事實上,我們解讀相關係數時必須多方考慮,如果 x 與 y 高度正相關,可能代表:

  • x 導致 y
  • y 導致 x
  • x, y 互為因果
  • 另有他因 z 導致 x, y (例如高 GDP 同時導致高平均壽命與高基礎網路頻寬,平均壽命與基礎網路頻寬並沒有因果關係)
  • x, y 根本無關,只是巧合 (例如一個地區的手機銷售量與律師人數?)

資料視覺化

除了直接計算統計數據,將資料視覺化也是幫助我們認識資料的好辦法,例如我想知道推文數的分布,可以試著畫出 histogram, 把小於 10 推, 20 推, 30 推的文章數量以條狀圖顯示

def decile(num):  # 將數字十分位化
    return (num // 10) * 10

from collections import Counter
histogram = Counter(decile(push) for push in pushes)
print(histogram)
# Counter({0: 17, 10: 6, 20: 2, 30: 1})

# 畫出 histogram
from matplotlib import pyplot as plt

plt.bar([x-4 for x in histogram.keys()], histogram.values(), 8)
plt.axis([-5, 35, 0, 20])
plt.title('Pushes')
plt.xlabel('# of pushes')
plt.ylabel('# of posts')
plt.xticks([10 * i for i in range(4)])
plt.show()

2016-12-31-1

另外,也可以考慮直接畫出資料的散佈圖 (scatter plot),觀察相關性

plt.scatter(images, pushes)
plt.title('# of image v.s. push')
plt.xlabel('# of image')
plt.ylabel('# of push')
plt.axis('equal')
plt.show()

2016-12-31-2

從 scatter plot 我們可以稍微看出圖片數與推文數的正相關性

結語:資料科學的三個面向

從這系列的文章,相信你已經看出所謂的資料科學與資料分析,其實可概分為三個面向:

  • 資料處理,寫程式,架系統,對應資料的來源、儲存、處理、查詢等,
  • 統計分析,數學,各種機器學習模型與技巧
  • Domain knowledge,也就是到底要對著資料問什麼問題

所以如果你對資料科學有興趣,你可能是對架構系統有興趣(提供乾淨資料),或對於玩資料有興趣(喜歡統計分析,精通機器學習,或是有足夠的領域知識發掘好問題),也可以思考以你的背景從哪一塊切入會比較適合。