2019年4月30日 星期二

機器學習 百日馬拉松 - Day 5. EDA 資料分佈

Day5 作業:可參考 my Github - Day_005_HW.ipynb
Day 5 主要是練習數據的可視化,在大數據中,不可能一筆一筆資料去讀,可以的話,將資料畫成有用圖表,對分析資料結構會有更快的了解,看圖說故事也是我們最擅長的(竊笑)。
python 常用的數據可視化工具 : matplotlib & seaborn
# Import 需要的套件 import os import numpy as np import pandas as pd import seaborn as sns import matplotlib.pyplot as plt %matplotlib inline # 設定 data_path dir_data = './data/' f_app_train = os.path.join(dir_data, 'application_train.csv') app_train = pd.read_csv(f_app_train)
這次作業主要是要練習 Pandas 的 數值計算 ex. max(),min(),mean(),median()…等等,所以我們挑出資料中 float64 的資料型態的資料來練習數值計算的操作,最後把圖畫出來看看。
#挑出 datatype 為 float 的資料 app_train.select_dtypes(['float']).columns
Index(['AMT_INCOME_TOTAL', 'AMT_CREDIT', 'AMT_ANNUITY', 'AMT_GOODS_PRICE',
       'REGION_POPULATION_RELATIVE', 'DAYS_REGISTRATION', 'OWN_CAR_AGE',
       'CNT_FAM_MEMBERS', 'EXT_SOURCE_1', 'EXT_SOURCE_2', 'EXT_SOURCE_3',
       'APARTMENTS_AVG', 'BASEMENTAREA_AVG', 'YEARS_BEGINEXPLUATATION_AVG',
       'YEARS_BUILD_AVG', 'COMMONAREA_AVG', 'ELEVATORS_AVG', 'ENTRANCES_AVG',
       'FLOORSMAX_AVG', 'FLOORSMIN_AVG', 'LANDAREA_AVG',
       'LIVINGAPARTMENTS_AVG', 'LIVINGAREA_AVG', 'NONLIVINGAPARTMENTS_AVG',
       'NONLIVINGAREA_AVG', 'APARTMENTS_MODE', 'BASEMENTAREA_MODE',
       'YEARS_BEGINEXPLUATATION_MODE', 'YEARS_BUILD_MODE', 'COMMONAREA_MODE',
       'ELEVATORS_MODE', 'ENTRANCES_MODE', 'FLOORSMAX_MODE', 'FLOORSMIN_MODE',
       'LANDAREA_MODE', 'LIVINGAPARTMENTS_MODE', 'LIVINGAREA_MODE',
       'NONLIVINGAPARTMENTS_MODE', 'NONLIVINGAREA_MODE', 'APARTMENTS_MEDI',
       'BASEMENTAREA_MEDI', 'YEARS_BEGINEXPLUATATION_MEDI', 'YEARS_BUILD_MEDI',
       'COMMONAREA_MEDI', 'ELEVATORS_MEDI', 'ENTRANCES_MEDI', 'FLOORSMAX_MEDI',
       'FLOORSMIN_MEDI', 'LANDAREA_MEDI', 'LIVINGAPARTMENTS_MEDI',
       'LIVINGAREA_MEDI', 'NONLIVINGAPARTMENTS_MEDI', 'NONLIVINGAREA_MEDI',
       'TOTALAREA_MODE', 'OBS_30_CNT_SOCIAL_CIRCLE',
       'DEF_30_CNT_SOCIAL_CIRCLE', 'OBS_60_CNT_SOCIAL_CIRCLE',
       'DEF_60_CNT_SOCIAL_CIRCLE', 'DAYS_LAST_PHONE_CHANGE',
       'AMT_REQ_CREDIT_BUREAU_HOUR', 'AMT_REQ_CREDIT_BUREAU_DAY',
       'AMT_REQ_CREDIT_BUREAU_WEEK', 'AMT_REQ_CREDIT_BUREAU_MON',
       'AMT_REQ_CREDIT_BUREAU_QRT', 'AMT_REQ_CREDIT_BUREAU_YEAR'],
      dtype='object')
將這些資料逐個打印出來看看,挑選覺得有興趣的資料來做計算。
app_train[app_train.columns[0:20]].select_dtypes(['float']).head()
app_train[app_train.columns[20:50]].select_dtypes(['float']).head()
app_train[app_train.columns[50:70]].select_dtypes(['float']).head()
將覺得有趣的 columns 挑出,建立新的 df,有下列三種方法,參考 Pandas user guide
#方法一 cap_data = [] cap_data.append(app_train['TARGET']) cap_data.append(app_train['AMT_INCOME_TOTAL']) cap_data.append(app_train['AMT_CREDIT']) cap_data.append(app_train['AMT_ANNUITY']) cap_data.append(app_train['AMT_GOODS_PRICE']) cap_data.append(app_train['REGION_POPULATION_RELATIVE']) cap_data.append(app_train['DAYS_REGISTRATION']) new_app_train=pd.DataFrame(cap_data).T
#方法二 new_app_train_ = pd.concat([app_train['TARGET'], app_train['AMT_INCOME_TOTAL'], app_train['AMT_CREDIT'], app_train['AMT_ANNUITY'], app_train['AMT_GOODS_PRICE'], app_train['REGION_POPULATION_RELATIVE'], app_train['DAYS_REGISTRATION']],axis=1)
#方法三 new_app_train__ = pd.DataFrame(app_train['TARGET']).join(app_train['AMT_INCOME_TOTAL']) new_app_train__ = new_app_train__.join(app_train['AMT_CREDIT']) new_app_train__ = new_app_train__.join(app_train['AMT_ANNUITY']) new_app_train__ = new_app_train__.join(app_train['AMT_GOODS_PRICE']) new_app_train__ = new_app_train__.join(app_train['REGION_POPULATION_RELATIVE']) new_app_train__ = new_app_train__.join(app_train['DAYS_REGISTRATION'])
建立新的 df 後,挑其中一項看一下內容前五列:
new_app_train__['AMT_INCOME_TOTAL'].head()
0    202500.0
1    270000.0
2     67500.0
3    135000.0
4    121500.0
Name: AMT_INCOME_TOTAL, dtype: float64
計算挑出欄位的平均數及標準差
for column in new_app_train__.columns: print("mean of "+str(column)+" : ",new_app_train[column].mean()) for column in new_app_train__.columns: print("standard deviation of "+str(column)+" : ",new_app_train[column].std())
mean of TARGET :  0.08072881945686496
mean of AMT_INCOME_TOTAL :  168797.9192969845
mean of AMT_CREDIT :  599025.9997057016
mean of AMT_ANNUITY :  27108.573909183444
mean of AMT_GOODS_PRICE :  538396.2074288895
mean of REGION_POPULATION_RELATIVE :  0.020868112057780042
mean of DAYS_REGISTRATION :  -4986.120327538419
standard deviation of  TARGET :  0.27241864564839396
standard deviation of  AMT_INCOME_TOTAL :  237123.14627885626
standard deviation of  AMT_CREDIT :  402490.77699585486
standard deviation of  AMT_ANNUITY :  14493.737315118333
standard deviation of  AMT_GOODS_PRICE :  369446.46054005757
standard deviation of  REGION_POPULATION_RELATIVE :  0.0138312801227047
standard deviation of  DAYS_REGISTRATION :  3522.8863209630713
將這些欄位畫出直方圖:
for column in new_app_train__.columns: plt.figure(figsize=(10,6)) new_app_train__[column].hist(bins=40,) plt.title(column) plt.show()






會畫圖之後,接著就是要練習分析圖片,今天的作業到這邊告一段落。

2019年4月24日 星期三

機器學習 百日馬拉松 - Day 4. EDA: 欄位的資料類型介紹及處理

Day 4 開始 pandas 的稍為進階操作,還有練習 pandas 的 one-hot-encodiing。
Day4 作業:可參考 my Github - Day_004_HW.ipynb ,內容算是輕鬆的一天!!
以下練習 Pandas 對於 data type 的類型操作:
同 Day 2 Kaggle 上的題目 Home Credit Default Risk 來練習資料的操作。
import os import numpy as np import pandas as pd
# 設定 data_path dir_data = './data/' f_app_train = os.path.join(dir_data, 'application_train.csv') f_app_test = os.path.join(dir_data, 'application_test.csv') app_train = pd.read_csv(f_app_train) app_test = pd.read_csv(f_app_test)
檢視資料中各個欄位類型的數量,透過 pd.info()
app_train.info(memory_usage='deep')
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 307511 entries, 0 to 307510
Columns: 122 entries, SK_ID_CURR to AMT_REQ_CREDIT_BUREAU_YEAR
dtypes: float64(65), int64(41), object(16)
memory usage: 540.2 MB
float64 型態的資料有 65 個,int64 型態的資料有 41 個,object 型態的資料有 16 個
記憶體用量為 540.2 MB 。
接著可以透過 value_counts() 可以對 Series 裡面的每個值進行計數並且排序。
app_train.dtypes.value_counts()
float64    65
int64      41
object     16
dtype: int64
可以透過 select_dtypes() 將 DateFrame 裡面有的 dtype 挑出來處理,比如我們現在想針對 “object” 型態的資料處理,如下:
app_train.select_dtypes(include=["object"]).apply(pd.Series.nunique, axis = 0)
NAME_CONTRACT_TYPE             2
CODE_GENDER                    3
FLAG_OWN_CAR                   2
FLAG_OWN_REALTY                2
NAME_TYPE_SUITE                7
NAME_INCOME_TYPE               8
NAME_EDUCATION_TYPE            5
NAME_FAMILY_STATUS             6
NAME_HOUSING_TYPE              6
OCCUPATION_TYPE               18
WEEKDAY_APPR_PROCESS_START     7
ORGANIZATION_TYPE             58
FONDKAPREMONT_MODE             4
HOUSETYPE_MODE                 3
WALLSMATERIAL_MODE             7
EMERGENCYSTATE_MODE            2
dtype: int64
代碼其中的 apply() 可以說是 Pandas 最好用的函數之一,雖然我還不太會用,但是可以看出其自由度很高。
DataFrame.apply(func, axis=0, broadcast=None, raw=False, reduce=None, result_type=None, args=(), **kwds)
該函數最有用的是第一個參數,這個參數是函數,相當於 C/C++ 的函數指針。
這個函數需要自己實現,函數的傳入參數根據軸來定,比如軸=0 or ‘index’,就是將函數應用於每個column。軸=1 or ‘columns’,就會將函數應用於每一row。
作業 4 :
練習將 sub_train 做 One-Hot encoding:
sub_train = pd.DataFrame(app_train['WEEKDAY_APPR_PROCESS_START']) print(sub_train.shape) sub_train.head()
(307511, 1)
 WEEKDAY_APPR_PROCESS_START
0 WEDNESDAY
1 MONDAY
2 MONDAY
3 WEDNESDAY
4 THURSDAY
其資料是由星期一到星期日,七個日期組成,如果要表示成one-hot encoding 的話,
星期日:[1,0,0,0,0,0,0];星期一:[0,1,0,0,0,0,0]…類似這樣的概念。
在pandas中,透過 get_dummies() 一行代碼即可做到:
sub_train = pd.get_dummies(sub_train['WEEKDAY_APPR_PROCESS_START']) print(sub_train.shape) sub_train.head()
(307511, 7)
可以看到shape 從 (307511, 1) 變成了 (307511, 7)
one-hot encoding 在 ML&DL 可以說是非常常用到的代碼,之前練習 Deep Learning - Reuters 路透社數據練習 - 多分類問題 就有實際操作練習過!!

2019年4月23日 星期二

機器學習 百日馬拉松 - Day 3. 3-1如何新建一個 dataframe? 3-2 如何讀取其他資料? (非 csv 的資料)

Day3 延續 Day2 的 Pandas 操作,為此我還去 Kaggle learn 研讀了一番 Pandas 基礎教學。
建議想了解 Pandas 的初學者可以到 Kaggle Learn 練習一下,我個人覺得蠻有幫助的!
作業3-1&3-2(連結 my GitHub) 統一在一個檔案了。以下來記錄一下習題的內容實作。
Day 3 用到的lib.
import pandas as pd import numpy as np from PIL import Image from io import BytesIO import matplotlib.pyplot as plt import requests

作業3-1 練習操作如何產生下圖這類的 pd.DataFrame

有練習過 kaggle learn 後,kaggle 的練習
animals = pd.DataFrame({'Cows': [12, 20], 'Goats': [22, 19]}, index=['Year 1', 'Year 2'])
照著格式試著將作業寫出,因為人口數是隨機的,會用到 np.random.randint
先建立"國家與人口"的 dict()
country=['Taiwan','United States','Thailand'] population=np.random.randint(1, 10, size=3) * (10**np.random.randint(6, 8, size=3)) data = {'國家': country, '人口':population }
接著將 data 丟進 pd.DataFrame ,這邊 index 不需要指定,就從0開始。
data = pd.DataFrame(data) print(data)
              國家        人口
0         Taiwan   9000000
1  United States   5000000
2       Thailand  70000000
隨手練習一下 max()idmax() 等操作,統計一下人口數。
population_max_country = data['國家'][data['人口'].idxmax()] population_min_country = data['國家'][data['人口'].idxmin()] population_max = data['人口'].max() population_min = data['人口'].min() print('人口最多的國家:', population_max_country ,',總共有 ' + str(population_max) + "人") print('人口最少的國家:', population_min_country ,',總共有 ' + str(population_min) + "人")
人口最多的國家: Thailand ,總共有 70000000人
人口最少的國家: United States ,總共有 5000000人

作業3-2 練習讀取txt檔,與其檔案內容,

其內容大概是一堆圖片的連結,如下:
我們要練習逐筆讀取將圖片 plt 出來。
首先讀取txt檔案。
target_url = 'https://raw.githubusercontent.com/vashineyu/slides_and_others/master/tutorial/examples/imagenet_urls_examples.txt'
要抓取HTTP 上的檔案,需要使用 requests 模塊:
response = requests.get(target_url) data = response.text # 用 request 傳送回來的資料不會認得斷行符號 print(len(data)) data[0:100]
784594
'n00015388_157\thttp://farm1.static.flickr.com/145/430300483_21e993670c.jpg\nn00015388_238\thttp://farm2'
因為資料讀取下來不會分辨空行(’\t’)與換行(’\n’)的符號,所以每個字都算一個位元,我們接著要來處理空行與換行的分割。
先將逐行當作一個data: 透過 split('\n')
split_tag = '\n' data = data.split(split_tag) print(len(data)) data[1]
9996
'n00015388_238\thttp://farm2.static.flickr.com/1005/3352960681_37b9c1d27b.jpg'
可以看到完整的一行即一個data ,n00015388_238\thttp://farm2.static.flickr.com/1005/3352960681_37b9c1d27b.jpg
n00015388_238 為該圖片命名,後面是圖片連結。
接著要將這命名與連結分開: 透過 split('\t') 並將分開後的data存進 list() 中保存,再建立一個 dict() 才能將資料轉成 pd.DataFrame
def split_data(data): name=[] url=[] for i in data: name.append(i.split("\t")[0]) try: url.append(i.split("\t")[1]) except : url.append("") data_dict = {'name': name, 'url':url} return data_dict
寫成函數,將data丟進分割後轉成 pd.DataFrame
data=split_data(data) df_data = pd.DataFrame(data) df_data.head()
 name        url
0 n00015388_157 http://farm1.static.flickr.com/145/430300483_2...
1 n00015388_238 http://farm2.static.flickr.com/1005/3352960681...
2 n00015388_304 http://farm1.static.flickr.com/27/51009336_a96...
3 n00015388_327 http://farm4.static.flickr.com/3025/2444687979...
4 n00015388_355 http://img100.imageshack.us/img100/3253/forres...
建立好 pd 格式的 data 後,透過 df 的操作將第一個連結抓到的圖片畫出來看看。
first_link = df_data.loc[0][1] response = requests.get(first_link) img = Image.open(BytesIO(response.content)) # Convert img to numpy array plt.imshow(img) plt.show()
最後作業要求使用 pd 操作將 data 的前五個連結畫出,其中還藏了小陷阱,有些網頁連結是壞掉的,所以可以使用 try & except 跳過 error 的連結。
def img2arr_fromURLs(url_list, resize = False): img_list=[] for url in url_list: response = requests.get(url) try: img=Image.open(BytesIO(response.content)) except : pass else: img_list.append(img) return img_list
result = img2arr_fromURLs(df_data['url'][0:5]) print("Total images that we got: %i " % len(result)) # 如果不等於 5, 代表有些連結失效囉 for im_get in result: plt.imshow(im_get) plt.show()



大功告成,作業3練習到很多東西,統整一下:
  1. pd.DataFrame 的建立
  2. HTTP 網頁資料的讀取 requests
  3. txt 檔案內的資料分割 split
  4. try , except 的例外操作 (這很久沒寫,但實際在 Kaggle 的資料下載,還真的會遇到error的問題!!)