트위터 데이터 수집 with R

1줄 요약

  • R을 활용하여 트위터 데이터를 수집하는 방법 및 절차에 대해 배우도록 한다.

트위터 API 인증

  • https://apps.twitter.com에 접속한다.

    • 회원가입을 진행한다.
  • create an app 버튼을 클릭한다.

  • 필자는 Hobbysit-Exploring the API를 선택했다.

    • 그 후에 개인 정보 등을 입력해야 한다.
    • 휴대폰, 이메일 인증 등
  • 인증 메일이 오기전까지는 조금 시일이 걸린다.

rtweet 패키지

  • 별도의 인증 절차 없이 사용 가능한 패키지

  • 우선 설치 후, 사용해보도록 한다.

    • 본 코드는 Github 예제로 있는 코드를 가져온 것임
# install.packages("rtweet")
library(rtweet)
library(dplyr)
library(ggplot2)

Search Tweets

  • search_tweets() 함수를 활용하면 매우 쉽게 데이터를 가져올 수 있다.
rstats <- search_tweets("#테슬라", n = 1000, include_rts = FALSE) %>% 
  select(name, location, description)
  • 앱 인증 절차만 진행이 되면 데이터를 가져올 수 있다.
glimpse(rstats)
## Rows: 132
## Columns: 3
## $ name        <chr> "얼리어답터", "얼리어답터", "허프포스트코리아", "뉴스핌", "뉴스핌", "disclosure", ~
## $ location    <chr> "", "", "SEOUL", "Korea", "Korea", "", "", "", "", "", "",~
## $ description <chr> "2001년부터 전세계의 테크 트랜드를 한국에 소개했던 얼리어답터가 완전히 새롭게 다시 시작합니다. 더 ~
  • 텍스트 데이터를 수집할 수 있었다.

그 외 패키지와의 비교

  • Github에는 rtweet 패키지가 어떤 Task를 수행하는 비교하는 표가 있다.

disk.frame 패키지 소개

공지

  • 주석은 가급적 원어를 남겨 놓으니 잘 번역하기를 바란다.

설치

  • 설치 방법은 기존과 마찬가지로 간단하게 작성할 수 있다.
install.packages("disk.frame")
suppressPackageStartupMessages(library(disk.frame))
library(nycflights13)

패키지 주요 아이디어

  • 메모리보다 많은 데이터를 각각의 chunks로 분해하여 하나의 폴더 안에 저장한다. (HDD 디스크 사용)
  • 자세한 셜명은 Giuhub를 참고 (https://github.com/xiaodaigh/disk.frame)

Setup

  • 실습 환경을 구성한다.
setup_disk.frame()
## The number of workers available for disk.frame is 1
# this allows large datasets to be transferred between sessions
options(future.globals.maxSize = Inf)

빠른 시작

disk.frame으로 변환

  • 데이터 객체를 disk.frame으로 변환한다.
# convert the flights data.frame to a disk.frame
# optionally, you may specify an outdir, otherwise, the 
flights.df <- as.disk.frame(nycflights13::flights, overwrite = TRUE)
class(flights.df)
## [1] "disk.frame"        "disk.frame.folder"
flights.df
## path: "/var/folders/zq/ch7gky6n3rzgjf1pd0w2l35w0000gn/T//Rtmp3ymGwx/file61302e8c8834.df"
## nchunks: 1
## nrow (at source): 336776
## ncol (at source): 19
## nrow (post operations): ???
## ncol (post operations): ???
  • 객체가 disk.frame으로 변환된 것을 확인할 수 있다.

Linux 기본 명령어

개요

  • 기본 문법을 다뤄봅니다. (추가적으로 올리고 싶을 때마다 정리해서 올릴 예정입니다.)

unzip

  • 만약에 여러개의 zip 파일을 받는다면 어떻게 해야할까?
  • 다음과 같이 할 수도 있다.
$ unzip a.zip b.zip c.zip d.zip
  • 코드가 조금 길어지는 것 같다. 간단하게 하면 다음과 같이 할 수도 있다.
  • 캐글 대회 데이터를 직접 응용하도록 한다.
$ kaggle competitions download -c sf-crime
Warning: Looks like you're using an outdated API Version, please consider updating (server 1.5.10 / client 1.5.4)
Downloading test.csv.zip to /content
 48% 9.00M/18.7M [00:00<00:00, 52.3MB/s]
100% 18.7M/18.7M [00:00<00:00, 74.0MB/s]
Downloading sampleSubmission.csv.zip to /content
  0% 0.00/2.35M [00:00<?, ?B/s]
100% 2.35M/2.35M [00:00<00:00, 157MB/s]
Downloading train.csv.zip to /content
 41% 9.00M/22.1M [00:00<00:00, 33.6MB/s]
100% 22.1M/22.1M [00:00<00:00, 63.4MB/s]
  • 이번에는 목록을 확인한다.
$ ls
sampleSubmission.csv.zip  test.csv.zip  train.csv.zip
  • 이제 .zip 파일을 해제하도록 한다.
$ unzip '*.zip'
Archive:  train.csv.zip
  inflating: train.csv               

Archive:  test.csv.zip
  inflating: test.csv                

Archive:  sampleSubmission.csv.zip
  inflating: sampleSubmission.csv    

3 archives were successfully processed.
  • 실제 파이썬 코드를 확인해서 데이터 크기를 확인한다.
import os 
DATA_PATH = "./"
for file in os.listdir(DATA_PATH):
  if 'csv' in file and 'zip' not in file:
    print(file.ljust(30) + str(round(os.path.getsize(file) / 1000000, 2)) + 'MB')
test.csv                      91.0MB
sampleSubmission.csv          75.05MB
train.csv                     127.43MB

pwd

  • pwd는 Print Working Directory의 약자로써, 현재 작업중인 경로의 정보를 출력하는 명령어이다.
$ pwd
/Users/username

Reference

Chris Jean, Unzip Multiple Files from Linux Command Line Retrieved from https://chrisjean.com/unzip-multiple-files-from-linux-command-line/

CI CD Pipeline for Data Science

개요

  • 최근 밑바닥부터 시작하는 딥러닝 3로 수업을 수강생들과 진행하며 배포에 관한 내용이 있었습니다. (p 98).
  • 구체적인 방법은 소개하지 않아서, 보충 자료로 작성하였다. 전
  • 단계별로 진행하는데, 깃허브에 관한 기본적인 내용 및 코드는 알고 있다는 전제하에 작성하였다.

필요한 것

Steps - Travis Logins

  • Travis에 깃허브로 로그인 한다. 아래와 같은 화면이 나오면 로그인이 잘 된 것이다.

  • 영문 내용을 잘 읽어본다.

(1) Activate your GitHub repositories

Once you’re signed in, go to your profile page where you’ll see all the organizations you’re a member of. You can install the GitHub App integration by clicking the Activate button for each organization you would like to use with Travis CI.

Pandas read_csv skiprows 활용

강의 홍보

문제 개요

  • Kaggle 데이터 New York City Taxi Fare Prediction 데이터를 구글 코랩에서 Loading 하는 중 메모리 문제가 발생함
  • 계통추출(Systematic Sampling)을 통해 데이터를 불러오기로 함

예제 실습

  • 아래 예제를 통해서 실제로 데이터가 줄어드는지 확인을 해본다.
  • 핵심 코드는 skip_logic 함수이며, skiprows = skiprows=lambda x: skip_logic(x, 3) 형태로 작성할 수 있다.
  • IRIS 데이터는 https://www.kaggle.com/saurabh00007/iriscsv 에서 다운로드 받았다.
    • iris 데이터외에도 각자 데이터를 가지고 실습을 해도 좋다.
import pandas as pd 

def skip_logic(index, skip_num):
    if index % skip_num == 0:
        return False
    return True

def main():
    print('**** skiprows 기본 옵션 ****')
    iris = pd.read_csv('iris.csv')
    print(iris.shape)

    print('**** skiprows 인덱스 0, 2, 5만 제외 ****')
    iris = pd.read_csv('iris.csv', skiprows=[0, 2, 5])
    print(iris.shape)
    
    print('**** skiprows 인덱스 range(3, 20)만 제외 ****')
    iris = pd.read_csv('iris.csv', skiprows=[i for i in range(3, 20)])
    print(iris.shape)
    
    print('**** skiprows 입력값의 배수에 해당하는 값만 Load ****')
    iris = pd.read_csv('iris.csv', skiprows=lambda x: skip_logic(x, 3))
    print(iris.shape)
    
if __name__ == '__main__':
    main()
**** skiprows 기본 옵션 ****
(150, 6)
**** skiprows 인덱스 0, 2, 5만 제외 ****
(147, 6)
**** skiprows 인덱스 range(3, 20)만 제외 ****
(133, 6)
**** skiprows 입력값의 배수에 해당하는 값만 Load ****
(50, 6)

실전 적용

  • 이제 배운 것을 적용해보자.

데이터 크기

  • train.csv 데이터의 크기를 확인해보자.
import os

def convert_bytes(file_path, unit=None):
  size = os.path.getsize(file_path)
  if unit == "KB":
    return print('File size: ' + str(round(size / 1024, 3)) + ' Kilobytes')
  elif unit == "MB":
    return print('File size: ' + str(round(size / (1024 * 1024), 3)) + ' Megabytes')
  elif unit == "GB":
    return print('File size: ' + str(round(size / (1024 * 1024 * 1024), 3)) + ' Gigabytes')
  else:
    return print('File size: ' + str(size) + ' bytes')

file_list = ['train.csv', 'test.csv', 'sample_submission.csv']
for file in file_list:
  print("The {file} size: ".format(file=file))
  convert_bytes(file)
  convert_bytes(file, 'KB')
  convert_bytes(file, 'MB')
  convert_bytes(file, 'GB')
  print("--" * 5)
The train.csv size: 
File size: 5697178298 bytes
File size: 5563650.682 Kilobytes
File size: 5433.253 Megabytes
File size: 5.306 Gigabytes
----------
The test.csv size: 
File size: 983020 bytes
File size: 959.98 Kilobytes
File size: 0.937 Megabytes
File size: 0.001 Gigabytes
----------
The sample_submission.csv size: 
File size: 343271 bytes
File size: 335.226 Kilobytes
File size: 0.327 Megabytes
File size: 0.0 Gigabytes
----------

실전 적용

  • 이제 실전 적용을 해본다.
import numpy as np
import pandas as pd
import seaborn as sns 
import matplotlib.pyplot as plt

def skip_logic(index, skip_num):
    if index % skip_num == 0:
        return False
    return True

train = pd.read_csv('./train.csv', skiprows=lambda x: skip_logic(x, 4))
print(train.shape)
test = pd.read_csv('./test.csv')
submission = pd.read_csv('./sample_submission.csv')
(13855964, 8)

결론

  • 대용량 데이터를 다루는 것은 쉽지 않지만, skiprows 파라미터를 적절히 활용하여 메모리 이슈를 피하자.

ACEA Water, Intro to Time Series Forecasting

강의 홍보

Overview

Can you build a model to predict the amount of water in each waterbody to help preserve this natural resource? This is an Analytics competition where your task is to create a Notebook that best addresses the Evaluation criteria below. Submissions should be shared directly with host and will be judged by the Acea Group based on how well they addrss:

Tutorial of Ranzcr EDA

강의 홍보

Competition

Intro

import os

import pandas as pd

from matplotlib import pyplot as plt
import seaborn as sns

Check File Size

  • Check Each Size of Dataset Folder in this competition
    • train_records = 4.5GB
    • test_tfrecords = 0.5MB
    • train (image data) = 6.5GB
    • test (image data) = 0.8MB
import os

def get_folder_size(file_directory):
  # file_list = os.listdir(file_directory)
  dir_sizes = {}
  for r, d, f in os.walk(file_directory, False):
      size = sum(os.path.getsize(os.path.join(r,f)) for f in f+d)
      size += sum(dir_sizes[os.path.join(r,d)] for d in d)
      dir_sizes[r] = size
      print("{} is {} MB".format(r, round(size/2**20), 2))      
  
base_dir = '../input/ranzcr-clip-catheter-line-classification'
get_folder_size(base_dir)
../input/ranzcr-clip-catheter-line-classification/test is 805 MB
../input/ranzcr-clip-catheter-line-classification/test_tfrecords is 555 MB
../input/ranzcr-clip-catheter-line-classification/train_tfrecords is 4563 MB
../input/ranzcr-clip-catheter-line-classification/train is 6592 MB
../input/ranzcr-clip-catheter-line-classification is 12524 MB

Check train file

  • Let’s descirbe train
train = pd.read_csv('../input/ranzcr-clip-catheter-line-classification/train.csv', index_col = 0)
test = pd.read_csv('../input/ranzcr-clip-catheter-line-classification/sample_submission.csv', index_col = 0)
display(train.head())
display(test.head())
ETT - AbnormalETT - BorderlineETT - NormalNGT - AbnormalNGT - BorderlineNGT - Incompletely ImagedNGT - NormalCVC - AbnormalCVC - BorderlineCVC - NormalSwan Ganz Catheter PresentPatientID
StudyInstanceUID
1.2.826.0.1.3680043.8.498.2669762895327322818937555779958242056100000010000ec89415d1
1.2.826.0.1.3680043.8.498.4630289159739875875981862867536515772900100100010bf4c6da3c
1.2.826.0.1.3680043.8.498.23819260719748494858948050424870692577000000001003fc1c97e5
1.2.826.0.1.3680043.8.498.6828664320232321280128351836714435874400000001000c31019814
1.2.826.0.1.3680043.8.498.1005020300922593825911900052881476217500000000010207685cd1
ETT - AbnormalETT - BorderlineETT - NormalNGT - AbnormalNGT - BorderlineNGT - Incompletely ImagedNGT - NormalCVC - AbnormalCVC - BorderlineCVC - NormalSwan Ganz Catheter Present
StudyInstanceUID
1.2.826.0.1.3680043.8.498.4692314557909600261710656729713516093200000000000
1.2.826.0.1.3680043.8.498.8400687018261108009182410976756156488700000000000
1.2.826.0.1.3680043.8.498.1221903329441311994751549472068754167200000000000
1.2.826.0.1.3680043.8.498.8499447438023596810990684554070609267100000000000
1.2.826.0.1.3680043.8.498.3579898779380566966257210888174520137200000000000

Definitions of Variables

  • What’s inside data?
    • StudyInstanceUID - unique ID for each image
    • ETT - Abnormal - endotracheal tube placement abnormal
    • ETT - Borderline - endotracheal tube placement borderline abnormal
    • ETT - Normal - endotracheal tube placement normal
    • NGT - Abnormal - nasogastric tube placement abnormal
    • NGT - Borderline - nasogastric tube placement borderline abnormal
    • NGT - Incompletely Imaged - nasogastric tube placement inconclusive due to imaging
    • NGT - Normal - nasogastric tube placement borderline normal
    • CVC - Abnormal - central venous catheter placement abnormal
    • CVC - Borderline - central venous catheter placement borderline abnormal
    • CVC - Normal - central venous catheter placement normal
    • Swan Ganz Catheter Present(??)
    • PatientID - unique ID for each patient in the dataset

Kaggle API on Mac/Linux

강의 홍보

개요

  • 새로운 학생들과 Kaggle 경진대회를 나가게 되었다.
  • 참여 경진대회
  • 기존에는 주로 Google Colab에서 했지만, 대용량 데이터부터 터미널로 다운로드 받아야 한다.

핵심 문장

kaggle.json 파일을 각 OS에 맞게 옮긴다.

Kaggle API 다운로드

  • 계정 [Profile]-[My Account]를 클릭 후, 아래 화면에서 Kaggle API를 다운로드 받는다.

파일 이동

  • 다운로드 파일을 적절한 위치에 옮긴다.
$ mv kaggle.json ~/.kaggle/
$ chmod 600 ~/.kaggle/kaggle.json

Python 파일 만들기

  • class를 활용하여 파일을 다운로드 받는다.
    • (사실, 터미널에서 해도 되기는 하다.)
from kaggle.api.kaggle_api_extended import KaggleApi

class KAGGLE:
    def __init__(self):
        self.api = KaggleApi()
        self.api.authenticate()

    def search(self, category):
        competitions = self.api.competitions_list(category = category)
        for comp in competitions:
            print(comp.ref, comp.reward, comp.userRank, sep=',')

    def download(self, name):
        files = self.api.competition_download_files(name)
        return files

if __name__ == '__main__':
    kaggle = KAGGLE()
    kaggle.search('all')
    kaggle.download('titanic')
  • 파일을 만든 후, 위 소스코드를 붙여 넣고, 실행한다.
$ python3 yourpython.py
contradictory-my-dear-watson,Prizes,None
gan-getting-started,Prizes,None
tpu-getting-started,Knowledge,None
digit-recognizer,Knowledge,None
titanic,Knowledge,None
house-prices-advanced-regression-techniques,Knowledge,1286
connectx,Knowledge,None
nlp-getting-started,Knowledge,1071
competitive-data-science-predict-future-sales,Kudos,None
hungry-geese,Prizes,None
indoor-location-navigation,$10,000,None
hpa-single-cell-image-classification,$25,000,None
vinbigdata-chest-xray-abnormalities-detection,$50,000,None
hubmap-kidney-segmentation,$60,000,None
ranzcr-clip-catheter-line-classification,$50,000,None
tabular-playground-series-feb-2021,Swag,None
rock-paper-scissors,Prizes,None
jane-street-market-prediction,$100,000,None
santa-2020,Prizes,None
cassava-leaf-disease-classification,$18,000,3059
  • 만약 상태 진행 표시가 필요하다면, 차라리 캐글 명령어를 직접 입력하도록 한다.
$ kaggle competitions download -c vinbigdata-chest-xray-abnormalities-detection

Kaggle House Price ML

강의 홍보

공지

  • 현재 책 출판 준비 중입니다.
  • 구체적인 설명은 책이 출판된 이후에 요약해서 올리도록 합니다.

이전 글

머신러닝 모형 학습 및 평가

데이터셋 분리 및 교차 검증

X = all_df.iloc[:len(y), :]
X_test = all_df.iloc[len(y):, :]
X.shape, y.shape, X_test.shape
((1458, 258), (1458,), (1459, 258))
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.25, random_state = 0)
X_train.shape, X_test.shape, y_train.shape, y_test.shape
((1093, 258), (365, 258), (1093,), (365,))

평가지표

MAE

import numpy as np

def mean_absolute_error(y_true, y_pred):

  error = 0
  for yt, yp in zip(y_true, y_pred):
    error = error + np.abs(yt-yp)
  
  mae = error / len(y_true)
  return mae

MSE

import numpy as np

def mean_squared_error(y_true, y_pred):

  error = 0
  for yt, yp in zip(y_true, y_pred):
    error = error + (yt - yp) ** 2
  
  mse = error / len(y_true)
  return mse

RMSE

import numpy as np

def root_rmse_squared_error(y_true, ypred):
  error = 0
  
  for yt, yp in zip(y_true, y_pred):
    error = error + (yt - yp) ** 2
  
  mse = error / len(y_true)
  rmse = np.round(np.sqrt(mse), 3)
  return rmse

Test1

y_true = [400, 300, 800]
y_pred = [380, 320, 777]

print("MAE:", mean_absolute_error(y_true, y_pred))
print("MSE:", mean_squared_error(y_true, y_pred))
print("RMSE:", root_rmse_squared_error(y_true, y_pred))
MAE: 21.0
MSE: 443.0
RMSE: 21.048

Test2

y_true = [400, 300, 800, 900]
y_pred = [380, 320, 777, 600]

print("MAE:", mean_absolute_error(y_true, y_pred))
print("MSE:", mean_squared_error(y_true, y_pred))
print("RMSE:", root_rmse_squared_error(y_true, y_pred))
MAE: 90.75
MSE: 22832.25
RMSE: 151.103

RMSE with Sklean

from sklearn.metrics import mean_squared_error

def rmsle(y_true, y_pred):
    return np.sqrt(mean_squared_error(y_true, y_pred))

모형 정의 및 검증 평가

from sklearn.metrics import mean_squared_error
from sklearn.model_selection import KFold, cross_val_score
from sklearn.linear_model import LinearRegression

def cv_rmse(model, n_folds=5):
    cv = KFold(n_splits=n_folds, random_state=42, shuffle=True)
    rmse_list = np.sqrt(-cross_val_score(model, X, y, scoring='neg_mean_squared_error', cv=cv))
    print('CV RMSE value list:', np.round(rmse_list, 4))
    print('CV RMSE mean value:', np.round(np.mean(rmse_list), 4))
    return (rmse_list)

n_folds = 5
rmse_scores = {}
lr_model = LinearRegression()
score = cv_rmse(lr_model, n_folds)
print("linear regression - mean: {:.4f} (std: {:.4f})".format(score.mean(), score.std()))
rmse_scores['linear regression'] = (score.mean(), score.std())
CV RMSE value list: [0.139  0.1749 0.1489 0.1102 0.1064]
CV RMSE mean value: 0.1359
linear regression - mean: 0.1359 (std: 0.0254)

첫번째 최종 예측 값 제출

from sklearn.model_selection import cross_val_predict

X = all_df.iloc[:len(y), :]
X_test = all_df.iloc[len(y):, :]
X.shape, y.shape, X_test.shape

lr_model_fit = lr_model.fit(X, y)
final_preds = np.floor(np.expm1(lr_model_fit.predict(X_test)))
print(final_preds)
[117164. 158072. 187662. ... 173438. 115451. 219376.]
submission = pd.read_csv("sample_submission.csv")
submission.iloc[:,1] = final_preds
print(submission.head())
submission.to_csv("The_first_regression.csv", index=False)
     Id  SalePrice
0  1461   117164.0
1  1462   158072.0
2  1463   187662.0
3  1464   197265.0
4  1465   199692.0

Kaggle 업데이트

  • 먼저 경진대회 Submission 파일을 클릭한 후, 파일을 업르도 한다.

Kaggle Feature Engineering - House Price

강의 홍보

공지

  • 현재 책 출판 준비 중입니다.
  • 구체적인 설명은 책이 출판된 이후에 요약해서 올리도록 합니다.

Kaggle API

Kaggle API를 활용한 데이터를 수집하는 예제는 Feature Engineering with Housing Price Prediction - Numerical Features 에서도 확인할 수 있기 때문에 생략 합니다.