딥러닝 모델을 훈련할 때 사용하는 GPU 장치가 무엇인지, GPU Driver version, CUDA version 등의 정보를 확인하고 싶을 때, 또 모델 훈련 중에 GPU의 총 메모리 중에서 현재 활용되고 있는 메모리는 어느정도 인지, 총 사용 가능한 전력 사용량 중에서 현재 사용하고 있는 전력량은 어느정도 인지 등을 모니터링 하고 싶을 때 nvidia-smi 유틸리티를 사용합니다. 

 

NVIDIA 시스템 관리 인터페이스(nvidia-smi, NVIDIA System Management Interface)는 NVIDIA GPU 장치의 관리 및 모니터링을 지원하기 위한 NVML (NVIDIA Management Library)을 기반으로 하는 command line utility입니다.

 

nvidia-smi, NVIDIA System Management Interface

 


이 유틸리티를 사용하면 관리자가 GPU 장치 상태를 쿼리할 수 있으며 적절한 권한으로 관리자가 GPU 장치 상태를 수정할 수 있습니다. TeslaTM, GRIDTM, QuadroTM 및 Titan X 제품을 대상으로 하지만 다른 NVIDIA GPU에서도 제한된 지원이 가능합니다.

NVIDIA-smi는 Linux의 NVIDIA GPU 디스플레이 드라이버와 64비트 Windows Server 2008 R2 및 Windows 7과 함께 제공됩니다. Nvidia-smi는 쿼리 정보를 XML 또는 사람이 읽을 수 있는 일반 텍스트로 표준 출력이나 파일에 보고할 수 있습니다. 

 

 

command line 창에서  $ nvidia-smi -q   (또는  $ nvidia-smi -query ) 명령어를 실행하면 아래와 같이 NVIDIA GUP 장치에 대한 정보와 현재 사용 중인 GPU 상태에 대한 모니터링 정보를 한꺼번에 알 수 있습니다. 

(Jupyter Notebook cell에서는 느낌표를 먼저 써주고,   ! nvidia-smi -q  를 입력해주면 됩니다.)

 

(Jupyter Notebook 에서 실행 시)
! nvidia-smi -q

(출력)

==============NVSMI LOG==============

Timestamp                                 : Sun Jan  9 12:55:56 2022
Driver Version                            : 460.32.03
CUDA Version                              : 11.2

Attached GPUs                             : 1
GPU 00000000:00:04.0
    Product Name                          : Tesla K80
    Product Brand                         : Tesla
    Product Architecture                  : Kepler
    Display Mode                          : Disabled
    Display Active                        : Disabled
    Persistence Mode                      : Disabled
    MIG Mode
        Current                           : N/A
        Pending                           : N/A
    Accounting Mode                       : Disabled
    Accounting Mode Buffer Size           : 4000
    Driver Model
        Current                           : N/A
        Pending                           : N/A
    Serial Number                         : 0320617086266
    GPU UUID                              : GPU-ed69a555-6186-feff-25f8-615b2ac9859f
    Minor Number                          : 0
    VBIOS Version                         : 80.21.25.00.02
    MultiGPU Board                        : No
    Board ID                              : 0x4
    GPU Part Number                       : 900-22080-6300-001
    Module ID                             : Uninitialized
    Inforom Version
        Image Version                     : 2080.0200.00.04
        OEM Object                        : 1.1
        ECC Object                        : 3.0
        Power Management Object           : N/A
    GPU Operation Mode
        Current                           : N/A
        Pending                           : N/A
    GSP Firmware Version                  : Uninitialized
    GPU Virtualization Mode
        Virtualization Mode               : Pass-Through
        Host VGPU Mode                    : N/A
    IBMNPU
        Relaxed Ordering Mode             : N/A
    PCI
        Bus                               : 0x00
        Device                            : 0x04
        Domain                            : 0x0000
        Device Id                         : 0x102D10DE
        Bus Id                            : 00000000:00:04.0
        Sub System Id                     : 0x106C10DE
        GPU Link Info
            PCIe Generation
                Max                       : 3
                Current                   : 1
            Link Width
                Max                       : 16x
                Current                   : 16x
        Bridge Chip
            Type                          : N/A
            Firmware                      : N/A
        Replays Since Reset               : 0
        Replay Number Rollovers           : 0
        Tx Throughput                     : N/A
        Rx Throughput                     : N/A
    Fan Speed                             : N/A
    Performance State                     : P8
    Clocks Throttle Reasons
        Idle                              : Active
        Applications Clocks Setting       : Not Active
        SW Power Cap                      : Not Active
        HW Slowdown                       : Not Active
            HW Thermal Slowdown           : N/A
            HW Power Brake Slowdown       : N/A
        Sync Boost                        : Not Active
        SW Thermal Slowdown               : Not Active
        Display Clock Setting             : Not Active
    FB Memory Usage
        Total                             : 11441 MiB
        Used                              : 0 MiB
        Free                              : 11441 MiB
    BAR1 Memory Usage
        Total                             : 16384 MiB
        Used                              : 2 MiB
        Free                              : 16382 MiB
    Compute Mode                          : Default
    Utilization
        Gpu                               : 0 %
        Memory                            : 0 %
        Encoder                           : 0 %
        Decoder                           : 0 %
    Encoder Stats
        Active Sessions                   : 0
        Average FPS                       : 0
        Average Latency                   : 0
    FBC Stats
        Active Sessions                   : 0
        Average FPS                       : 0
        Average Latency                   : 0
    Ecc Mode
        Current                           : Enabled
        Pending                           : Enabled
    ECC Errors
        Volatile
            Single Bit            
                Device Memory             : 0
                Register File             : 0
                L1 Cache                  : 0
                L2 Cache                  : 0
                Texture Memory            : 0
                Texture Shared            : N/A
                CBU                       : N/A
                Total                     : 0
            Double Bit            
                Device Memory             : 0
                Register File             : 0
                L1 Cache                  : 0
                L2 Cache                  : 0
                Texture Memory            : 0
                Texture Shared            : N/A
                CBU                       : N/A
                Total                     : 0
        Aggregate
            Single Bit            
                Device Memory             : 2
                Register File             : 0
                L1 Cache                  : 0
                L2 Cache                  : 0
                Texture Memory            : 0
                Texture Shared            : N/A
                CBU                       : N/A
                Total                     : 2
            Double Bit            
                Device Memory             : 4
                Register File             : 0
                L1 Cache                  : 0
                L2 Cache                  : 0
                Texture Memory            : 0
                Texture Shared            : N/A
                CBU                       : N/A
                Total                     : 4
    Retired Pages
        Single Bit ECC                    : 0
        Double Bit ECC                    : 2
        Pending Page Blacklist            : No
    Remapped Rows                         : N/A
    Temperature
        GPU Current Temp                  : 52 C
        GPU Shutdown Temp                 : 93 C
        GPU Slowdown Temp                 : 88 C
        GPU Max Operating Temp            : N/A
        GPU Target Temperature            : N/A
        Memory Current Temp               : N/A
        Memory Max Operating Temp         : N/A
    Power Readings
        Power Management                  : Supported
        Power Draw                        : 31.51 W
        Power Limit                       : 149.00 W
        Default Power Limit               : 149.00 W
        Enforced Power Limit              : 149.00 W
        Min Power Limit                   : 100.00 W
        Max Power Limit                   : 175.00 W
    Clocks
        Graphics                          : 324 MHz
        SM                                : 324 MHz
        Memory                            : 324 MHz
        Video                             : 405 MHz
    Applications Clocks
        Graphics                          : 562 MHz
        Memory                            : 2505 MHz
    Default Applications Clocks
        Graphics                          : 562 MHz
        Memory                            : 2505 MHz
    Max Clocks
        Graphics                          : 875 MHz
        SM                                : 875 MHz
        Memory                            : 2505 MHz
        Video                             : 540 MHz
    Max Customer Boost Clocks
        Graphics                          : N/A
    Clock Policy
        Auto Boost                        : On
        Auto Boost Default                : On
    Voltage
        Graphics                          : Uninitialized
    Processes                             : None

 

 

 

위의 실행 결과에 NVIDIA GPU 의 장치 및 실행 모니터링의 모든 정보가 출력이 되다보니 양이 너무나 많습니다. 만약 간단하게 시스템에 연결된 NVIDIA GPU 의 장치 리스트의 이름 (Product Name)과 UUID 정보만 알고 싶으면 command line 에서  $ nvidia-smi -L  (혹은  $ nvidia-smi --list-gups ) 를 실행시켜주면 됩니다. 

 

(Jupyter Notebook에서 실행 시)
! nvidia-smi -L

(출력)

GPU 0: Tesla K80 (UUID: GPU-ed69a555-6186-feff-25f8-615b2ac9859f)

 

 

만약 시스템에 연결된 NVIDIA GPU 의 메모리의 상태에 대해서 알고 싶으면 command line 창에서  $ nvidia-smi -q -d memory  를 입력해주면 됩니다. 

 

(Jupyter Notebook에서 실행 시)
! nvidia-smi -q -d memory

(출력)

[Out]
==============NVSMI LOG==============

Timestamp                                 : Sun Jan  9 12:59:09 2022
Driver Version                            : 460.32.03
CUDA Version                              : 11.2

Attached GPUs                             : 1
GPU 00000000:00:04.0
    FB Memory Usage
        Total                             : 11441 MiB
        Used                              : 0 MiB
        Free                              : 11441 MiB
    BAR1 Memory Usage
        Total                             : 16384 MiB
        Used                              : 2 MiB
        Free                              : 16382 MiB

 

 

 

[ Reference ]

(1) NVIDIA System Management Interface (NVIDIA-smi)
    : https://developer.nvidia.com/nvidia-system-management-interface

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python의 pandas DataFrame을 대사응로 matplotlib 그래프를 그렸을 때, X축 범주형 항목의 순서(changing the order of x-axis ticks in python matplotlib plot)를 변경하는 방법을 소개하겠습니다. 

 

(1) pandas DataFrame의 x 축으로 사용되는 범주형 값을 loc 를 사용해 재정렬하기

(2) index 가 재정렬된 pandas.DataFrame에 대해서 matplotlib 으로 그래프 그리기

 

changing the order of x-axis ticks in matplotlib plot

 

먼저, 예제로 사용할 간단한 pandas DataFrame을 만들어 보겠습니다. 요일(weekday dates) 별 값(value) 으로 구성된 DataFrame에 대해서 groupby() 연산자를 사용해서 요일별 값의 합을 집계(aggregation by weekday) 한 DataFrame을 만들었습니다. 

 

import pandas as pd
import matplotlib.pyplot as plt

## making a sample pandas DataFrmae
df = pd.DataFrame({
    'weekday': ['Monday', 'Saturday', 'Tuesday', 'Sunday', 'Wednesday', 'Thursday', 
                'Friday', 'Saturday', 'Sunday', 'Friday', 'Tuesday'], 
    'value': [2, 3, 4, 2, 6, 7, 5, 2, 1, 6, 4]
})

print(df)
#       weekday  value
# 0      Monday      2
# 1    Saturday      3
# 2     Tuesday      4
# 3      Sunday      2
# 4   Wednesday      6
# 5    Thursday      7
# 6      Friday      5
# 7    Saturday      2
# 8      Sunday      1
# 9      Friday      6
# 10    Tuesday      4


## aggregation of value by weekday --> this will be used for visualization
df_agg = df.groupby('weekday').sum('value')
print(df_agg)
#            value
# weekday         
# Friday        11
# Monday         2
# Saturday       5
# Sunday         3
# Thursday       7
# Tuesday        8
# Wednesday      6

 

 

 

(1) pandas DataFrame의 x 축으로 사용되는 범주형 값을 loc 를 사용해 재정렬하기

 

위에서 df.groupby('weekday').sum('value') 로 집계한 df_agg DataFrame의 결과를 보면, 알파벳(alphabet) 순서대로 요일의 순서("Friday", "Monday", "Satruday", "Sunday", "Thursday", "Tuesday", "Wednesday")가 정해져서 집계가 되었습니다. 이 DataFrame에 대해 matplotlib 으로 막대그래프를 그리면 아래와 같이 요일이 알파벳 순서대로 정렬이 된 상태에서 그래프가 그려집니다. 

 

plt.figure(figsize=(12, 8))
plt.bar(df_agg.index, df_agg.value)
plt.title("Bar plot without reordering x-axis label", fontsize=20)
plt.xlabel("Weekday", fontsize=18)
plt.xticks(fontsize=16)
plt.show()

matplotlib: before changing the order of x-axis label

 

 

(2) index 가 재정렬된 pandas.DataFrame에 대해서 matplotlib 으로 그래프 그리기
       (matplotlib 그래프의 x-axis 의 ticks 순서 바꾸기)

 

요일의 순서가 우리가 일상적으로 사용하는 순서와는 다르기 때문에 눈에 잘 안들어오고 거슬립니다. 이럴 때는 pandas DataFrame의 index 순서를 먼저 바꾸어주고, 순서가 재정렬된 후의 DataFrame에 대해서 matplotlib 으로 그래프를 그려주면 됩니다.

 

아래 예제에서는 요일(weekday)을 알파벳 순서가 아니라, 우리가 일상적으로 사용하는 ("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday") 의 순서로 DataFrame의  index 를 loc 를 사용해서 바꾸어 준후에, matplotlib 막대그래프(bar graph)를 그려보았습니다. 

 

matplotlib의 X 축 레이블의 크기 

## changing the order of x-axis label using loc
weekday_order = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday']
df_agg = df_agg.loc[weekday_order]

print(df_agg)
#            value
# weekday         
# Monday         2
# Tuesday        8
# Wednesday      6
# Thursday       7
# Friday        11
# Saturday       5
# Sunday         3


## box-plot after changing the order of x-axis ticks
plt.figure(figsize=(12, 8))
plt.bar(df_agg.index, df_agg.value)
plt.title("Bar plot after reordering x-axis label", fontsize=20)
plt.xlabel("Weekday", fontsize=18)
plt.xticks(fontsize=16)
plt.show()

matplotlib: after changing the order of x-axis label

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Amazon AWS 의 SageMaker 에서 Python 객체(예: scikit-learn 으로 학습한 로지스틱 회귀모형)를 직렬화(serialization)하여 AWS S3에 저장하는 사용자 정의함수 코드를 소개하겠습니다. 

 

아래 예제 코드에서는 Python 객체를 직렬화하는데 six 모듈의 six.moves.cPickle 메소드를 사용하였으며, protocol 매개변수는 Python 버전에 따라서 Python 3.x 는 protocol=3, Python 2.x 는 protocol=2 를 입력해주면 됩니다. 

 

boto3 모듈로 특정 계정의 AWS S3에 접근해서 put_object() 메소드로 파일을 저장하는데요, 이때 put_object() 메소드에 Bucket (S3 내 버킷 이름), Key (폴더 이름, 키), Body (직렬화한 Python 객체) 매개변수 값을 지정해주면 됩니다.  

 

serialize a Python object using six module and save it to AWS S3 using boto3 module

 

Python 객체의 직렬화(serialization), 역직렬화(de-serialization)는 https://rfriend.tistory.com/525 를 참고하세요. 

 

 

[ Python object를 직렬화해서 AWS S3에 저장하는 사용자 지정 함수 ]

 

def store_object_to_S3(bucket_nm, folder_nm, key_nm, object_nm):
    import boto3
    
    # connect to specific account
    region = boto3.Session().region_name
    session = boto3.Session(region_name=region)
    s3 = session.client('s3')
    
    # serialization using pickle
    import six
    pickle = six.moves.cPickle
    
    try:
        serialized_obj = pickle.dumps(object_nm, protocol=3) # protocol=3 for Python 3.x
    except:
        serialized_obj = pickle.dumps(object_nm, protocol=2) # protocol=3 for Python 2.x
    
    print('[STATUS] serialized')
    
    # store a serialized object to S3 bucket
    key = "{}/{}".format(folder_nm, key_nm)
    s3.put_object(Bucket=bucket_nm, 
                  Key=key, 
                  Body=serialized_obj)
    
    print('[STATUS] saved to S3')

 

 

위에서 정의한 사용자 정의함수에 bucket_nm, folder_nm, key_nm, object_nm (직렬화하고자 하는 Python 객체, 예: 학습된 모델 객체) 을 순서대로 입력해주면 됩니다. 

 

# store the serialized best model to S3 bucket
store_object_to_S3(bucket_nm='my-bucket', 
                   folder_nm='best_model', 
                   key_nm='logitreg_model',
                   object_nm=logitreg_model)

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요! :-)

 

728x90
반응형
Posted by Rfriend
,

탐색적 데이터 분석 및 데이터 전처리를 할 때 특정 행과 열을 기준으로 데이터를 선택(selection), 인덱싱(indexing), 슬라이싱(slicing)하는 하는 처리가 필요합니다. 이때 pandas 에서 사용할 수 있는 게 loc, iloc 인데요, 비슷해서 좀 헷갈리는 면이 있습니다. 

 

이번 포스팅에서는 Python pandas 의 DataFrame에서 데이터를 선택(selection), 인덱싱(indexing), 슬라이싱(slicing)할 때 사용하는 loc vs. iloc 를 비교해보겠습니다. 

 

- loc 는 레이블 기반 (label-based) 또는 블리언 배열(boolean array) 기반으로 데이터를 선택 

- iloc 는 정수 기반의 위치 (integer-based position) 또는 블리언 배열(boolean array) 기반으로 데이터를 선택

 

아래의 순서대로 loc vs. iloc 를 간단한 예를 들어 비교하면서 소개하겠습니다. 

(1) A Value

(2) A List or Array

(3) A Slice Object

(4) Conditions or Boolean Array

(5) A Callable Function

 

 

[ Pandas DataFrame의 데이터를 선택할 때 사용하는 loc vs. iloc ]

selecting data in pandas DataFrame using loc vs. iloc

 

 

먼저, index를 수기 입력해주고, 숫자형과 범주형 변수를 모두 가지는 간단한 예제 pandas DataFrame을 만들어보겠습니다. 

 

## creating a sample pandas DataFrame
import pandas as pd

df = pd.DataFrame({
    'name': ['park', 'choi', 'lee', 'kim', 'lim', 'yang'], 
    'gender': ['M', 'F', 'F', 'M', 'F', 'F'], 
    'age': [25, 29, 25, 31, 38, 30], 
    'grade': ['S', 'B', 'C', 'A', 'D', 'S'], 
    'tot_amt': [500, 210, 110, 430, 60, 680]}, 
    index=['c100', 'c101', 'c102', 'c103', 'c104', 'c105'])


print(df)
#       name gender  age grade  tot_amt
# c100  park      M   25     S      500
# c101  choi      F   29     B      210
# c102   lee      F   25     C      110
# c103   kim      M   31     A      430
# c104   lim      F   38     D       60
# c105  yang      F   30     S      680

 

 

아래부터는 loc vs. iloc 코드 예시인데요, 모두 데이터를 선택하는 굉장히 간단한 코드들 이므로 설명은 생략합니다. 특이사항에 대해서만 간략히 부연설명 남겨요. 

 

(1) loc vs. iloc: A Value

 

한 개의 행 레이블(a single row label)로 loc 를 사용해서 값을 가져오면 pandas Series 를 반환하는 반면에, 리스트(list, [ ]) 안에 1개 행 레이블을 넣어서 loc 를 사용하면 pandas DataFrame을 반환합니다. 이것은 iloc 에 정수 위치를 넣어서 값을 가져올 때도 동일합니다. 

 

## (1) pandas.DataFrame.loc[]
## : Access a group of rows and colmns by label(s) or a boolean array

## (1-1) using a row label --> returns a pandas Series
df.loc['c100']
# name       park
# gender        M
# age          25
# grade         S
# tot_amt     500
# Name: c100, dtype: object



## (1-2) using a list of row label --> returns a pandas DataFrame
df.loc[['c100']]
#       name gender  age grade  tot_amt
# c100  park      M   25     S      500




## (2) pandas.DataFrame.iloc[]
## : Purely integer-location based indexing for selection by position.

## (2-1) A scalar of integer --> returns pandas Series
df.iloc[0]
# name       park
# gender        M
# age          25
# grade         S
# tot_amt     500
# Name: c100, dtype: object


## (2-2) A list of integer --> returns pandas DataFrame
df.iloc[[0]]
#       name gender  age grade  tot_amt
# c100  park      M   25     S      500

 

 

 

(2) loc vs. iloc: A List or Array

 

df.loc[['c100', 'c105']] 처럼 loc 에 레이블 리스트를 사용하면 해당 행의 다수의 열의 값을 가져오며, df.loc['c100', 'name'] 처럼 사용하면 레이블 기반의 해당 행(row)과 열(column)의 값을 가져옵니다. 

 

## (1) pandas.DataFrame.loc[]
## : Access a group of rows and colmns by label(s) or a boolean array

## (1-2) using multiple row labels
df.loc[['c100', 'c105']]
#       name gender  age grade  tot_amt
# c100  park      M   25     S      500
# c105  yang      F   30     S      680


## using row and column label
df.loc['c100', 'name']
# 'park'



## (2) pandas.DataFrame.iloc[]
## : Purely integer-location based indexing for selection by position.

## (2-2) A list or array of integers
df.iloc[[0, 1, 3, 5]]
#       name gender  age grade  tot_amt
# c100  park      M   25     S      500
# c101  choi      F   29     B      210
# c103   kim      M   31     A      430
# c105  yang      F   30     S      680

 

 

 

(3) loc vs. iloc: A Slice Object

 

loc 로 레이블 기반 슬라이싱을 하면 처음과 끝 레이블 값이 포함된 채로 값을 가져옵니다. 예를 들어, 아래의 df.loc['c100':'c103'] 은 'c100'과 'c103' 행도 모두 포함된 값을 가져왔습니다. 반면에 iloc 로 정수 위치 기반으로 슬라이싱을 하면 처음 정수 위치의 행은 가져오지만 마지막의 정수 위치의 행은 가져오지 않습니다. 

 

## (1) pandas.DataFrame.loc[]
## : Access a group of rows and colmns by label(s) or a boolean array

## (1-3) Slice with labels for row and single label for column.
df.loc['c100':'c103', 'name']
# c100    park
# c101    choi
# c102     lee
# c103     kim
# Name: name, dtype: object



## (2) pandas.DataFrame.iloc[]
## : Purely integer-location based indexing for selection by position.

## (2-3) slicing using integer
df.iloc[1:4]
#       name gender  age grade  tot_amt
# c101  choi      F   29     B      210
# c102   lee      F   25     C      110
# c103   kim      M   31     A      430

 

 

 

(4) loc vs. iloc: Conditions or Boolean Array

 

loc 의 레이블 기반 데이터 선택에는 조건문과 블리언 배열을 모두 사용할 수 있습니다. iloc 의 정수 기반 데이터 선택에는 블리언 배열을 사용할 수 있습니다. 

 

## (1) pandas.DataFrame.loc[]
## : Access a group of rows and colmns by label(s) or a boolean array

## (1-4-1) Conditional that returns a boolean Series

## Boolean list with the same length as the row axis
df['tot_amt'] > 400
# c100     True
# c101    False
# c102    False
# c103     True
# c104    False
# c105     True
# Name: tot_amt, dtype: bool


## Conditional that returns a boolean Series
df.loc[df['tot_amt'] > 400]
#       name gender  age grade  tot_amt
# c100  park      M   25     S      500
# c103   kim      M   31     A      430
# c105  yang      F   30     S      680


## Conditional that returns a boolean Series with column labels specified
df.loc[df['tot_amt'] > 400, ['name']]
#       name
# c100  park
# c103   kim
# c105  yang


## (1-4-2) A boolean array
df.loc[[True, False, False, True, False, True]]
#       name gender  age grade  tot_amt
# c100  park      M   25     S      500
# c103   kim      M   31     A      430
# c105  yang      F   30     S      680




## (2) pandas.DataFrame.iloc[]
## : Purely integer-location based indexing for selection by position.

## (2-4) With a boolean mask the same length as the index. 
## loc and iloc are interchangeable when labels are 0-based integers.
df.iloc[[True, False, False, True, False, True]]
#       name gender  age grade  tot_amt
# c100  park      M   25     S      500
# c103   kim      M   31     A      430
# c105  yang      F   30     S      680

 

 

 

(5) loc vs. iloc: A Callable Function

 

lambda 익명함수를 사용하여 호출 가능한 함수를 loc, iloc 에 사용해서 값을 선택할 수 있습니다. 

(df.iloc[lambda df: df['tot_amt'] > 400] 은 왜그런지 모르겠는데 에러가 나네요. -_-;)

 

## (1) pandas.DataFrame.loc[]
## : Access a group of rows and colmns by label(s) or a boolean array

## (1-5) Callable that returns a boolean Series
df.loc[lambda df: df['tot_amt'] > 400]
#       name gender  age grade  tot_amt
# c100  park      M   25     S      500
# c103   kim      M   31     A      430
# c105  yang      F   30     S      680



## (2) pandas.DataFrame.iloc[]
## : Purely integer-location based indexing for selection by position.

## (2-7) Callable that returns a boolean Series
df.iloc[lambda x: x.index == 'c100']
#       name gender  age grade  tot_amt
# c100  park      M   25     S      500

 

 

 

 

[ Reference ]

* pandas DataFrame에서 행, 열 데이터 선택: https://rfriend.tistory.com/282 
* pandas loc: https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.loc.html   
* pandas iloc: https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.iloc.html   

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 TensorFlow Keras의 손실함수 중에서 다중분류 문제(multiclass classification problem) 에 대한 딥러닝 모델을 훈련할 때 사용하는 손실함수에 대해서 소개하겠습니다. 

 

(1) 손실함수란 무엇인가? 

(2) 문제 유형별 Keras의 손실함수는 무엇이 있나? 

(3) 교차 엔트로피(Cross Entropy) 란 무엇인가?

(4) sparse_categorical_crossentropy() vs. categorical_crossentropy() 비교

 

 

 

(1) 손실함수란 무엇인가? 

 

 기계학습(Machine Learning), 딥러닝(Deep Learning) 은 손실함수(Loss Function)을 통해서 학습합니다. 손실함수는 다른 이름으로 비용함수(Cost Function)라고도 합니다. 

 

 손실함수는 특정 알고리즘이 주어진 데이터를 얼마나 잘 모델링하는지를 측정하는 방법입니다. 만약 학습모델을 사용해 예측한 값(predicted value)이 참 값(true value, actual value)과 차이가 많이 날 경우 손실함수의 값은 매우 커지게 되며, 손실함수 값이 작을 수록 알고리즘이 주어진 데이터를 잘 모델링했다고 평가할 수 있습니다. 

 

 기계학습, 딥러닝에서는 손실함수의 손실값(loss value)을 점점 작게 해서 최소의 손실 값을 찾아가는 최적화 함수(optimization function)을 사용해서 데이터로 부터 모델을 학습하게 됩니다. 최적화 함수에 대해서는 별도의 포스팅을 통해서 나중에 소개하도록 하겠습니다. 

 

 

 

(2) 문제 유형별 Keras의 손실함수는 무엇이 있나? 

 

 모든 문제에 공통으로 적용할 수 있는 만능의 손실함수는 없습니다. 각 문제 유형(예: 회귀, 분류)과 데이터 형태(y label 이 정수, onehot encoded), 미분 계산의 용이성, 이상치(outliers)의 포함 정도 등에 따라서 사용하는 손실함수는 달라집니다. 

 아래의 표는 TensorFlow Keras의 문제 유형(problem types) 별로 마지막층의 활성화 함수(last layer's activation function)와 손실함수/클래스를 표로 정리한 것입니다.

 

이번 포스팅에서 다루고자 하는 TensorFlow Keras의  sparse_categorical_crossentropy()와 categorical_crossentropy() 손실함수는 다중분류 문제(multiclass classification problem)에 사용하는 손실함수입니다. 

 

 

[ TensorFlow Keras의 손실 함수, 손실 클래스 (Loss Functions, Loss Classes) ]

TensorFlow Keras Loss Functions, Loss Classes

 

 

 

(3) 교차 엔트로피(Cross Entropy) 란 무엇인가?

 

교차 엔트로피 개념은 정보이론(information theroy)에서 나왔습니다. 교차 엔트로피(Cross Entropy)는 동일한 근간의 사건의 집합(over the same underlying events set)에서 뽑은 두 개의 확률 분포 p와 q에서 만약 집합에 사용된 코딩 체계가 실제 확률분포 p보다 추정 확률 분포 q에 최적화되어 있는 경우 집합으로 부터 뽑힌 사건을 식별하는데 필요한 평균 비트 수를 측정합니다.

 

위의 정의는 위키피디아(https://en.wikipedia.org/wiki/Cross_entropy) 에서 인용한 것인데요, 무슨 말인지 잘 이해하기 힘들지요? 아래의 유튜브 링크는 "Hands-on Machine Learning with Scikitlearn, Keras & TensorFlow" 책의 저자인 Aurelien Geron 님께서 "Entropy, Cross Entropy, KL Divergence"에 대해서 소개해주고 있는 영상인데요, 이걸 참고하시면 이해하는데 훨씬 쉬울거예요. 

 

 

이 정의는 다시 확률분포 q로 부터의 p의 차이인 Kullback-Leibler Divergence  Dkl(p||q) 로 공식화(be formulated)될 수 있습니다. 이산형 확률분포와 연속형 확률분포일 경우별로 교차엔트로피를 구하는 수식은 아래의 내용을 참고하세요. 

 

 

교차 엔트로피는 기계학습과 최적화에서 손실 함수를 정의하는 데 사용될 수 있습니다. 참 확률 p(i)는 정답 레이블이고, 주어진 분포 q(i)는 현재 모델의 예측 값입니다. 언어 모델을 예로 들면, 훈련 데이터셋을 기반으로 언어모델을 생성한 다음, 교차 엔트로피를 테스트 세트에서 측정하여 모델이 테스트 데이터를 예측하는 데 얼마나 정확한지 평가합니다. 이 언어모델 예에서 p는 모든 말뭉치에서 단어의 실제 분포이고, q는 모델에 의해 예측된 단어의 분포입니다. 

 

y(i) 를 실제의 참 값(actual true value), y_hat(i)를 모델이 예측한 값(predicted value)라고 했을 때, 분류 문제의 교차 엔트로피는 아래와 같은 수식으로 표현할 수 있습니다. (이진분류의 경우 y(i)가 0 또는 1 의 값을 가짐). 아래 수식을 보면 알 수 있듯이, 이진분류문제의 교차 엔트로피 손실함수는 실제 값이 0이면 아래 수식의 왼쪽 부분이 없어지고, 실제 값이 1이면 아래 수식의 오른쪽이 없어집니다. 따라서 만약 이진분류 모델이 실제 값을 틀리게 예측하고 또 예측확률값이 높을 수록 교차 엔트로피 손실함수 값이 더 커지게끔 설계되어 있습니다. (틀렸으면 벌을 주는데, 더 확신을 가지고 틀렸으면 더 큰 벌을 주는 개념). 

Cross Entropy Loss for Classification Problem

 

 

 

(4) sparse_categorical_crossentropy() vs. categorical_crossentropy() 비교

 

(4-1) 다중분류 문제(multiclass classification problem) 에 사용하는 함수 중에서 y label 의 형태에 따라서, 

 - tf.keras.losses.sparse_categorical_crossentropy(): y label 이 정수 (integer) 

 - tf.keras.losses.categorical_crossentropy(): y label 이 one-hot encoded 

를 선택해서 사용하면 됩니다.

아래의 화면캡쳐한 코드 예시를 보면 y label의 형태가 어떻게 다른지 금방 알 수 있을 거예요. 

 

(4-2) 또 하나 차이점이 있다면, 문제의 유형(problem types)에 따라서, 

 - tf.keras.losses.sparse_categorical_crossentropy(): multiclass single-label classification 만 가능

 - tf.keras.losses.categorical_crossentropy(): multiclass single-label classification, multiclass multilabel classification 둘다 사용 가능

하다는 차이점이 있습니다.  

multiclass single-label classification 문제는 다중 클래스 중에서 관측치는 단 한개의 클래스에만 속하는 문제(예: MNIST의 이미지 숫자 분류)를 말하며, multiclass multilabel classification 문제는 관측치가 여러개의 클래스에 속할 수 있는 문제(예: 음악 장류 분류, 영화 장르 분류 등)를 말합니다. 

 

Keras: sparse_categorical_crossentropy vs. categorical crossentropy

 

 

 

[ Reference ]

* TensorFlow 손실함수 (Loss Functions/ Classes)
   : https://www.tensorflow.org/api_docs/python/tf/keras/losses

* Keras 손실함수 (Loss Functions/ Classes): https://keras.io/api/losses/

* Cross Entropy: https://en.wikipedia.org/wiki/Cross_entropy

* Keras sparse_categorical_crossentropy()
   : https://www.tensorflow.org/api_docs/python/tf/keras/metrics/sparse_categorical_crossentropy

* Keras categorical_crossentropy()
   : https://www.tensorflow.org/api_docs/python/tf/keras/metrics/categorical_crossentropy

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

지난번 포스팅에서는 TensorFlow 의 tf.constant() 로 텐서를 만드는 방법(https://rfriend.tistory.com/718)을 소개하였습니다. 이번 포스팅에서는 TensorFlow 의 변수 (Variable) 에 대해서 소개하겠습니다. 

 

(1) TensorFlow 변수(tf.Variable)는 무엇이고, 상수(tf.constant)는 무엇이 다른가? 

(2) TensorFlow 변수를 만들고(tf.Variable), 값을 변경하는 방법 (assign)

(3) TensorFlow 변수 연산 (operations)

(4) TensorFlow 변수 속성 정보 (attributes)

(5) 변수를 상수로 변환하기 (converting tf.Variable to tf.constant)

 

 

(1) TensorFlow 변수(tf.Variable)는 무엇이고, 상수(tf.constant)와는 무엇이 다른가? 

 

 텐서플로의 튜토리얼의 소개를 보면 "변수는 프로그램 연산에서 공유되고 유지되는 상태를 표현하는데 사용을 권장("A TensorFlow variable is the recommended way to represent shared, persistent state your program manipulates.") 한다고 합니다. 말이 좀 어려운데요, 변수와 상수를 비교해보면 금방 이해가 갈 것입니다. 

 

 텐서플로 변수(Variable)는 값의 변경이 가능(mutable value)한 반면에, 상수(constant)는 값의 변경이 불가능(immutable value)합니다. 변수는 값의 변경이 가능하고 공유되고 유지되는 특성 때문에 딥러닝 모델을 훈련할 때 자동 미분 값의 back-propagations 에서 가중치를 업데이트한 값을 저장하는데 사용이 됩니다. 변수는 초기화(initialization)가 필요합니다. 

 

TensorFlow Variable, 변수

 

 

 

(2) TensorFlow 변수를 만들고(tf.Variable), 값을 변경하는 방법 (assign)

 

TensorFlow 변수는 tf.Variable(value, name, dtype, shape) 의 메소드를 사용해서 만들 수 있습니다. 

 

import tensorflow as tf
print(tf.__version__)
#2.7.0


## After construction, the type and shape of the variable are fixed.
v = tf.Variable([1, 2])
print(v)
#<tf.Variable 'Variable:0' shape=(2,) dtype=int32, numpy=array([1, 2], dtype=int32)>

 

 

변수의 값을 변경할 때는 assign() 메소드를 사용합니다.  assign_add(), assign_sub() 를 사용해서 덧셈이나 뺄셈 연산을 수행한 후의 결과로 변수의 값을 업데이트 할 수도 있습니다. 

 

## The value can be changed using one of the assign methods.
v.assign([3, 4])

print(v)
#<tf.Variable 'Variable:0' shape=(2,) dtype=int32, numpy=array([3, 4], dtype=int32)>


## The value can be changed using one of the assign methods.
v.assign_add([10, 20])

print(v)
#<tf.Variable 'Variable:0' shape=(2,) dtype=int32, numpy=array([13, 24], dtype=int32)>

 

 

 

tf.Variable(value, shape=tf.TensorShape(None)) 처럼 shape 매개변수를 사용하면 형태(shape)를 정의하지 않은 상태에서 변수를 정의할 수도 있습니다. 

 

## The shape argument to Variable's constructor allows you to 
## construct a variable with a less defined shape than its initial-value
v = tf.Variable(1., shape=tf.TensorShape(None))

print(v)
#<tf.Variable 'Variable:0' shape=<unknown> dtype=float32, numpy=1.0>


v.assign([[1.]])
#<tf.Variable 'UnreadVariable' shape=<unknown> dtype=float32, 
#numpy=array([[1.]], dtype=float32)>

 

 

 

(3) TensorFlow 변수 연산 (operations)

 

변수는 텐서 연산의 인풋(inputs to operations)으로 사용될 수 있습니다. 아래 예에서는 변수와 상수간 원소 간 곱과 합을 구해보았습니다. 

 

## Variable created with Variable() can be used as inputs to operations. 
## Additionally, all the operators overloaded for the Tensor class are carried over to variables. 
w = tf.Variable([1., 2.])
x = tf.constant([3., 4.])

## element-wise product
tf.math.multiply(w, x)
# <tf.Tensor: shape=(2,), dtype=float32, numpy=array([3., 8.], dtype=float32)>



## element-wise addition
w + x
# <tf.Tensor: shape=(2,), dtype=float32, numpy=array([4., 6.], dtype=float32)>

 

 

 

(4) TensorFlow 변수 속성 정보 (attributes)

 

텐서플로의 변수에서 이름(name), 형태(shape), 데이터 유형(dtype), 연산에 이용되는 디바이스(device) 속성정보를 조회할 수 있습니다. 

 

## Attributes
v = tf.Variable([1., 2.], name='MyTensor')
print('name:', v.name)
print('shape:', v.shape)
print('dtype:', v.dtype)
print('device:', v.device)

# name: MyTensor:0
# shape: (2,)
# dtype: <dtype: 'float32'>
# device: /job:localhost/replica:0/task:0/device:CPU:0

 

 

 

(5) 변수를 상수로 변환하기 (converting tf.Variable to tf.constant)

 

변수를 상수로 변환하려면 tf.convert_to_tensor(Variable) 메소드를 사용합니다. 

 

## converting tf.Variable to Tensor
c = tf.convert_to_tensor(v)

print(c)
# tf.Tensor([1. 2.], shape=(2,), dtype=float32)

 

 

 

[ Reference ]

* TensorFlow Variable: https://www.tensorflow.org/api_docs/python/tf/Variable

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

데이터 전처리를 하다보면 필요에 맞게 데이터 형태, 구조를 변경하는 일이 빈번하게 생깁니다. 이번 포스팅에서는 텐서의 형태를 변환, 재구조화, 전치하는 방법을 소개하겠습니다. 

이미 numpy (https://rfriend.tistory.com/345 , https://rfriend.tistory.com/289)에 익숙한 분이라면, 사용법이 비슷하기 때문에 그리 어렵지 않게 금방 이해할 수 있을 거예요. 

 

(1) tf.reshape(): 텐서의 형태 변환 

(2) tf.transpose(): 텐서의 행과 열 전치

 

 

TensorFlow reshape, transpose

 

 

(1) tf.reshape(): 텐서의 형태 변환

 

먼저, 0~11까지 12개의 원소를 가지는 벡터(vector) 로 텐서를 만들어보겠습니다. 

 

t1 = tf.constant(range(12))

print(t1)
# tf.Tensor([ 0  1  2  3  4  5  6  7  8  9 10 11], 
#.          shape=(12,), dtype=int32)


tf.rank(t1) # rank 1
# <tf.Tensor: shape=(), dtype=int32, numpy=1>

 

 

 

위의 벡터 (12,) 형태를 가지는 텐서 t1을, 행렬 (3, 4) 형태를 가지는 텐서로 tf.reshape(tensor, shape, name=None) 메소드를 사용해서 변환(reshape)해보겠습니다. 

 

## reshaping a shape of Tensor from (12,) to (3, 4)
t2 = tf.reshape(t1, [3, 4]) 

print(t2)
# tf.Tensor(
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]], shape=(3, 4), dtype=int32)


tf.rank(t2) # rank 2
# <tf.Tensor: shape=(), dtype=int32, numpy=2>

 

 

 

tf.reshape(tensor, shape) 의 shape 란에 원하는 형태를 [ ] 안에 콤마로 구분해서 넣어주면 됩니다. 이번에는 rank 3 을 가지는 (2, 2, 3) 형태의 텐서로 형태를 변환해보겠습니다. 

 

## reshaping a Tensor with a shape of (12,) to (2,2,3)
t3 = tf.reshape(t1, [2, 2, 3])

print(t3)
# tf.Tensor(
# [[[ 0  1  2]
#   [ 3  4  5]]
#  [[ 6  7  8]
#   [ 9 10 11]]], shape=(2, 2, 3), dtype=int32)


tf.rank(t3) # rank 3
# <tf.Tensor: shape=(), dtype=int32, numpy=3>

 

 

tf.reshape(tensor, shape) 의 shape 에 '-1' 이 들어있으면, 숫자가 기입된 부분의 축을 변환하고 난 후에, "남은 축의 형태는 원래 텐서의 총 크기와 같도록 알아서 추정"해준다는 뜻입니다. 

 

아래 예에서는 원래 텐서 t1 이 (12,) 형태였으며, tf.reshape(t1, [-1, 3]) 으로 재구조화시켰더니 (4, 3) 형태의 텐서로 변환되었네요. 

 

## If one component of shape is the special value -1, 
## the size of that dimension is computed 
## so that the total size remains constant.
t4 = tf.reshape(t1, [-1, 3])


print(t4)
# tf.Tensor(
# [[ 0  1  2]
#  [ 3  4  5]
#  [ 6  7  8]
#  [ 9 10 11]], shape=(4, 3), dtype=int32)


tf.rank(t4) # rank 2
# <tf.Tensor: shape=(), dtype=int32, numpy=2>

 

 

특히, tf.reshape(tensor, [-1]) 처럼 shape 에 [-1] 은 1차원의 벡터인 1-D 텐서로 변환을 한다는 뜻입니다. 

아래 예에서 텐서 t4 는 (4, 3) 형태를 가지는 행렬이었는데요, tf.reshape(t4, [-1]) 해주었더니 (12,) 의 형태를 가지는 1차원의 벡터로 변환이 되었습니다. 

 

## In particular, a shape of [-1] flattens into 1-D. 
## At most one component of shape can be -1.
t5 = tf.reshape(t4, [-1])

print(t5)
# tf.Tensor([ 0  1  2  3  4  5  6  7  8  9 10 11], 
#           shape=(12,), dtype=int32)


tf.rank(t5) # rank 1
# <tf.Tensor: shape=(), dtype=int32, numpy=1>

 

 

 

tf.reshape(tensor, []) 의 [ ] 는 텐서를 1개의 원소를 가지는 스칼라(scalar) 로 변환합니다. 

 

## tf.reshape(t, []) reshapes a tensor t with one element to a scalar.
t6 = tf.constant([5])

print(t6) # rank 1, vector
# tf.Tensor([5], shape=(1,), dtype=int32)


t7 = tf.reshape(t6, [])
print(t7) # rank 0, scalar
# tf.Tensor(5, shape=(), dtype=int32)


tf.rank(t7) # rank 0
# <tf.Tensor: shape=(), dtype=int32, numpy=0>

 

 

 

(2) tf.transpose(): 텐서의 행과 열 전치

 

tf.transpose(tensor)는 텐서의 행과 열의 위치를 전치(transpose) 시켜 줍니다. 

아래의 예에서는 shape=(3,4) 의 텐서를 shape=(4,3)의 텐서로 행과 열을 전치시켜주었습니다. 행과 열이 전치를 시키기 전과 후에 어떻게 바뀌었는지 살펴보면 금방 이해하실 수 있을 거예요. 

 

print(t2)
# tf.Tensor(
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]], shape=(3, 4), dtype=int32)


t8 = tf.transpose(t2)

print(t8)
# tf.Tensor(
# [[ 0  4  8]
#  [ 1  5  9]
#  [ 2  6 10]
#  [ 3  7 11]], shape=(4, 3), dtype=int32)

 

[ Reference ]

- tf.reshape(): https://www.tensorflow.org/api_docs/python/tf/reshape

- tf.transpose(): https://www.tensorflow.org/api_docs/python/tf/transpose

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

딥러닝 모델을 훈련하고 예측하는데 사용하는 TensorFlow 프레임웍의 이름은 Tensor + Flow (텐서를 흘려보냄) 에서 유래했습니다. 텐서(Tensor)는 텐서플로의 가장 기본이 되는 자료 구조인 만큼 만드는 방법과 속성정보 조회하는 방법을 알아둘 필요가 있겠습니다. 

 

이번 포스팅에서는 

 

(1) 텐서의 정의

(2) 텐서 만들기

     - (2-1) tf.constant([mat1, mat2, mat3])

     - (2-2) tf.stack([mat1, mat2, mat3])

     - (2-3) tf.convert_to_tensor([mat1, mat2, mat3])

(3) 텐서의 속성정보 조회하기

     - (3-1) Tensor.dtype : 텐서 데이터 유형

     - (3-2) Tensor.shape : 텐서 형태

     - (3-3) Tensor.rank : 텐서 차수(rank), 텐서를 구성하는 벡터의 개수, 랭크

     - (3-4) Tensor.device : 텐서 생성 디바이스 (CPU, GPU)

 

하는 방법에 대해서 소개하겠습니다. 

 

 

 

(1) 텐서의 정의

 

 TensorFlow의 자료 구조에는 0차원의 스칼라(scalar), 1차원의 벡터(vector), 2차원의 행렬(matrix), 3차원 이상의 텐서(tensor) 가 있습니다. 텐서플로에서 텐서는 벡터와 행렬, 그리고 3차원 이상의 고차원의 배열을 모두 아우르는 일반화된 데이터 구조를 말합니다.

 텐서플로는 파이썬 객체를 텐서(Tensor)로 변환해서 행렬 연산을 수행합니다. 텐서플로는 먼저 tf.Tensor 객체의 그래프(graph) 를 생성하는 것에서 시작하여, 각 텐서가 어떻게 계산되는지를 구체화하고, 이 그래프의 부분들을 실행하여 원하는 최종 결과를 도출합니다. 

 텐서는 데이터 유형(a data type, 예: float32, int32, string) 과 데이터 형태 (shape) 의 속성을 가집니다. 

 

TensorFlow data types: scalar, vector, matrix, tensor

 

 

(2) 텐서 만들기

 

그럼, (2, 3) 의 shape 을 가지는 3개의 배열을 가지고, 3차원인 (3, 2, 3) 형태의 텐서를 만들어보겠습니다. 

 

     - (2-1) tf.constant([mat1, mat2, mat3])

     - (2-2) tf.stack([mat1, mat2, mat3])

     - (2-3) tf.convert_to_tensor([mat1, mat2, mat3])

 

import tensorflow as tf
tf.__version__
#2.7.0


## input matrix (list of list)
mat1 = [[1, 2, 3], [4, 5,  6]]
mat2 = [[7, 8, 9], [10, 11, 12]]
mat3 = [[13, 14, 15], [16, 17, 18]]

 

 

(2-1) tf.constant([mat1, mat2, mat3])

 

## A tf.Tensor represents a multidimensional array of elements.

## (1) tf.constant(): Creates a constant tensor from a tensor-like object.
tensor1 = tf.constant([mat1, mat2, mat3])

tensor1
# <tf.Tensor: shape=(3, 2, 3), dtype=int32, numpy=
# array([[[ 1,  2,  3],
#         [ 4,  5,  6]],

#        [[ 7,  8,  9],
#         [10, 11, 12]],

#        [[13, 14, 15],
#         [16, 17, 18]]], dtype=int32)>

 

 

 

(2-2) tf.stack([mat1, mat2, mat3])

 

## tf.stack(): Stacks a list of rank-R tensors into one rank-(R+1) tensor.
tensor2 = tf.stack([mat1, mat2, mat3])

 

 

 

(2-3) tf.convert_to_tensor([mat1, mat2, mat3])

 

텐서를 만들 때 데이터 유형(dtype), 텐서 이름(name)의 속성정보를 설정할 수 있습니다. 

 

## tf.convert_to_tensor(): Converts the given value to a Tensor.
tensor3 = tf.convert_to_tensor([mat1, mat2, mat3])

# tensor3 = tf.convert_to_tensor([mat1, mat2, mat3], 
#                                dtype=tf.int64, 
#                                name='my_first_tensor')

 

 

 

(3) 텐서의 속성정보 조회하기

 

     - (3-1) Tensor.dtype : 텐서 데이터 유형

     - (3-2) Tensor.shape : 텐서 형태

     - (3-3) Tensor.rank : 텐서 차수(rank), 텐서를 구성하는 벡터의 개수, 랭크

     - (3-4) Tensor.device : 텐서 생성 디바이스 (CPU, GPU)

 

# A tf.Tensor has the following properties:
# - a single data type (float32, int32, or string, for example)
# - a shape

## The DType of elements in this tensor.
tensor3.dtype
# tf.int64


## Returns a tf.TensorShape that represents the shape of this tensor.
tensor3.shape
# TensorShape([3, 2, 3])


## rank of this tensor.
tf.rank(tensor3)
# <tf.Tensor: shape=(), dtype=int32, numpy=3>


## The name of the device on which this tensor will be produced, or None.
tensor3.device
# /job:localhost/replica:0/task:0/device:GPU:0

 

 

[ Referece ]

- tf.Tensor(): https://www.tensorflow.org/api_docs/python/tf/Tensor

- tf.constant(): https://www.tensorflow.org/api_docs/python/tf/constant

- tf.stack(): https://www.tensorflow.org/api_docs/python/tf/stack

- tf.convert_to_tensor(): https://www.tensorflow.org/api_docs/python/tf/convert_to_tensor

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

이번 포스팅에서는 Python Tensorflow와 numpy 모듈을 사용하여 

  (1) 행렬 원소 간 곱 (matrix element-wise product)

  (2) 행렬 곱 (matrix multiplication) 

하는 방법과 연산 방법을 소개하겠습니다. 

얼핏보면 둘이 비슷해보이지만, 전혀 다른 연산으로서 주의가 필요합니다. 

 

 

tensorflow, numpy, element-wise product, matrix multiplication

 

 

 

먼저, TensorFlow와 numpy  모듈을 불러오고, 예제로 사용할 2차원 행렬(matrix)을 만들어보겠습니다. 

 

import numpy as np
import tensorflow as tf
print(tf.__version__)
#2.7.0


## matrix
x = tf.constant([[1, 2], [3, 4]])

print(x)
# tf.Tensor(
# [[1 2]
#  [3 4]], shape=(2, 2), dtype=int32)


y = tf.constant([[0, 10], [20, 30]])

print(y)
# tf.Tensor(
# [[ 0 10]
#  [20 30]], shape=(2, 2), dtype=int32)

 

 

 

(1) 행렬 원소 간 곱 (matrix element-wise product)

 

## [TensorFlow] matrix element-wise product
tf.math.multiply(x, y)

# <tf.Tensor: shape=(2, 2), dtype=int32, numpy=
# array([[  0,  20],
#        [ 60, 120]], dtype=int32)>

 

## [numpy] matrix element-wise produce
np.array(x) * np.array(y)

# array([[  0,  20],
#        [ 60, 120]], dtype=int32)

 

 

 

(2) 행렬 곱 (matrix multiplication) 

 

## matrix multiplication using tf.matmul()
tf.matmul(x, y)

# <tf.Tensor: shape=(2, 2), dtype=int32, numpy=
# array([[ 40,  70],
#        [ 80, 150]], dtype=int32)>

 

## [numpy] matrix multiplication using np.dot()
np.dot(x, y)

# array([[ 40,  70],
#        [ 80, 150]], dtype=int32)



## [numpy] matrix multiplication using np.matmul()
np.matmul(x, y)

# array([[ 40,  70],
#        [ 80, 150]], dtype=int32)

 

 

 

참고로, TensorFlow 의 텐서를 numpy의 array 로 변환하려면 numpy() 메소드를 사용하면 됩니다. 

 

## casting tensor to numpy's array
tf.matmul(x, y).numpy()

# array([[ 40,  70],
#        [ 80, 150]], dtype=int32)

 

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!  :-)

 

728x90
반응형
Posted by Rfriend
,

데이터셋에 이상치가 있으면 모델을 훈련시킬 때 적합된 모수에 큰 영향을 줍니다. 따라서 탐색적 데이터 분석을 할 때 이상치(outlier)를 찾고 제거하는 작업이 필요합니다. 

 

이번 포스팅에서는 PostgreSQL, Greenplum DB에서 SQL의 PERCENTILE_DISC() WITHIN GROUP (ORDER BY) 함수를 사용해서, 사분위수와 IQR 에 기반하여 이상치를 찾고 제거하는 방법(Identifying and removing Outliers by the upper and lower limit based on Quartiles and IQR(Interquartile Range))을 소개하겠습니다. 

 

요약통계량의 평균과 표준편차는 이상치에 매우 민감합니다. 따라서 정규분포가 아니라 이상치가 존재하여 한쪽으로 치우친 분포에서는 (average +-3 * standard deviation) 범위 밖의 값을 이상치로 간주하는 방법은 적합하지 않을 수 있습니다. 반면, 이상치에 덜 민감한 사분위수와 IQR 를 이용하여 이상치를 찾고 제거하는 방법은 간단하게 구현하여 사용할 수 있습니다. 

 

 

identifying outliers by upper and lower limit based on quartiles and IQR using SQL

 

 

먼저, 예제로 사용할 데이터셋 테이블을 만들어보겠습니다. 부산과 서울의 지역(region) 그룹별로 seller_id 별 판매금액(amt) 을 칼럼으로 가지며, 판매금액에 이상치(outliler)를 포함시켰습니다. 

 

---------------------------------------------------------------------------------
-- Removing Outliers based on Quartiles and IQR using SQL 
---------------------------------------------------------------------------------

-- creating a sample dataset with outliers
DROP TABLE IF EXISTS reg_sales;
CREATE TABLE reg_sales (
	region text NOT NULL
	, seller_id int NOT NULL
	, amt int
);

INSERT INTO reg_sales VALUES 
('Busan', 1, 10) -- outlier
, ('Busan', 2, 310)
, ('Busan', 3, 350)
, ('Busan', 4, 380)
, ('Busan', 5, 390)
, ('Busan', 6, 430)
, ('Busan', 7, 450)
, ('Busan', 8, 450)
, ('Busan', 9, 3200) -- outlier
, ('Busan', 10, 4600) -- outlier
, ('Seoul', 1, 20) -- outlier
, ('Seoul', 2, 300)
, ('Seoul', 3, 350)
, ('Seoul', 4, 370)
, ('Seoul', 5, 380)
, ('Seoul', 6, 400)
, ('Seoul', 7, 410)
, ('Seoul', 8, 440)
, ('Seoul', 9, 460)
, ('Seoul', 10, 2500) -- outlier
;

SELECT * FROM reg_sales ORDER BY region, amt;

--region|seller_id|amt |
--------+---------+----+
--Busan |        1|  10|
--Busan |        2| 310|
--Busan |        3| 350|
--Busan |        4| 380|
--Busan |        5| 390|
--Busan |        6| 430|
--Busan |        8| 450|
--Busan |        7| 450|
--Busan |        9|3200|
--Busan |       10|4600|
--Seoul |        1|  20|
--Seoul |        2| 300|
--Seoul |        3| 350|
--Seoul |        4| 370|
--Seoul |        5| 380|
--Seoul |        6| 400|
--Seoul |        7| 410|
--Seoul |        8| 440|
--Seoul |        9| 460|
--Seoul |       10|2500|

 

 

PostgreSQL, Greenplum 에서 PERCENTILE_DISC() 함수를 사용하여 사분위수(quartiles)와 IQR(Interquartile Range)를 구할 수 있습니다.  아래 예에서는 지역(region) 별로 1사분위수(Q1), 중앙값(median), 3사분위수(Q3), IQR (Interquartile Range) 를 구해보았습니다. 

 

IQR (Interquartile Range) = Q3 - Q1

 

-- Quartiles by region groups
-- Interquartile Range (IQR) = Q3-Q1 
-- : relatively robust statistic compared to range and std dev for the measure of spread.
SELECT 
	region
	, PERCENTILE_DISC(0.25) WITHIN GROUP (ORDER BY amt) AS q1
	, PERCENTILE_DISC(0.50) WITHIN GROUP (ORDER BY amt) AS median
	, PERCENTILE_DISC(0.75) WITHIN GROUP (ORDER BY amt) AS q3
	, PERCENTILE_DISC(0.75) WITHIN GROUP (ORDER BY amt)  - 
		PERCENTILE_DISC(0.25) WITHIN GROUP (ORDER BY amt) AS iqr
FROM reg_sales
GROUP BY region 
ORDER BY region;

--region|q1 |median|q3 |iqr|
--------+---+------+---+---+
--Busan |350|   390|450|100|
--Seoul |350|   380|440| 90|

 

 

 

사분위수와 IQR 를 이용하여 이상치를 찾는 방식(identifying outliers by upper and lower limit based on quartiles and IQR using SQL in PostgreSQL)은 아래와 같습니다. (포스팅 상단의 도식 참조) 

 

* Upper Limit = Q1 - 1.5 * IQR

* Lower Limit = Q3 + 1.5 * IQR

 

if value > Upper Limit then 'Outlier'

or if value < Lower Limit then 'Outlier'

 

-- Identifying outliers by the upper and lower limit based on Quartiles and IQR as:
-- : Lower Limit = Q1 – 1.5 * IQR
-- : Upper Limit = Q3 + 1.5 * IQR

WITH stats AS (
	SELECT 
	region
	, PERCENTILE_DISC(0.25) WITHIN GROUP (ORDER BY amt) AS q1
	, PERCENTILE_DISC(0.75) WITHIN GROUP (ORDER BY amt) AS q3
	, PERCENTILE_DISC(0.75) WITHIN GROUP (ORDER BY amt)  - 
		PERCENTILE_DISC(0.25) WITHIN GROUP (ORDER BY amt) AS iqr
	FROM reg_sales
	GROUP BY region
)
SELECT 
	r.*
FROM reg_sales AS r
LEFT JOIN stats AS s ON r.region = s.region 
WHERE r.amt < (s.q1 - 1.5 * s.iqr) OR r.amt > (s.q3 + 1.5 * s.iqr) -- identifying outliers
ORDER BY region, amt;

--region|seller_id|amt |
--------+---------+----+
--Busan |        1|  10|
--Busan |        9|3200|
--Busan |       10|4600|
--Seoul |        1|  20|
--Seoul |       10|2500|

 

 

 

아래의 예에서는 사분위수와 IQR에 기반하여 이상치를 제거 (Removing outliers by upper and lower limit based on quartiles and IQR using SQL in PostgreSQL) 하여 보겠습니다. 

 

-- Removing outliers by the upper and lower limit based on Quartiles and IQR as:
-- : Lower Limit = Q1 – 1.5 * IQR
-- : Upper Limit = Q3 + 1.5 * IQR

WITH stats AS (
	SELECT 
	region
	, PERCENTILE_DISC(0.25) WITHIN GROUP (ORDER BY amt) AS q1
	, PERCENTILE_DISC(0.75) WITHIN GROUP (ORDER BY amt) AS q3
	, PERCENTILE_DISC(0.75) WITHIN GROUP (ORDER BY amt)  - 
		PERCENTILE_DISC(0.25) WITHIN GROUP (ORDER BY amt) AS iqr
	FROM reg_sales
	GROUP BY region
)
SELECT 
	r.*
FROM reg_sales AS r
LEFT JOIN stats AS s ON r.region = s.region 
WHERE r.amt > (s.q1 - 1.5 * s.iqr) AND r.amt < (s.q3 + 1.5 * s.iqr) -- removing outliers
ORDER BY region, amt;

--region|seller_id|amt|
--------+---------+---+
--Busan |        2|310|
--Busan |        3|350|
--Busan |        4|380|
--Busan |        5|390|
--Busan |        6|430|
--Busan |        7|450|
--Busan |        8|450|
--Seoul |        2|300|
--Seoul |        3|350|
--Seoul |        4|370|
--Seoul |        5|380|
--Seoul |        6|400|
--Seoul |        7|410|
--Seoul |        8|440|
--Seoul |        9|460|

 

[ Reference ]

* PostgreSQL PERCENTILE_DISC() function 

  : https://www.postgresql.org/docs/9.4/functions-aggregate.html

 

이번 포스팅이 많은 도움이 되었기를 바랍니다. 

행복한 데이터 과학자 되세요!   :-)

 

728x90
반응형
Posted by Rfriend
,