05_handling_series(apply)
In [1]:
import pandas as pd
from collections import OrderedDict

scientists = pd.read_csv('./data/scientists.csv')
In [2]:
ages = scientists['Age']

print('max: {}'.format(ages.max()))
print("mean: {}".format(ages.mean()))
max: 90
mean: 59.125


boolean 추출

  • 평균나이보다 나이가 많은 사람

모든 데이터에 대해 한 번에 연산하는 것을 Broadcasting이라 함

In [3]:
ages[ages > ages.mean()]
Out[3]:
1    61
2    90
3    66
7    77
Name: Age, dtype: int64


broadcasting

In [4]:
print(pd.Series([1, 100]))

print("\n=================================\n")
print(ages + pd.Series([1, 100]))
0      1
1    100
dtype: int64

=================================

0     38.0
1    161.0
2      NaN
3      NaN
4      NaN
5      NaN
6      NaN
7      NaN
dtype: float64
In [5]:
rev_age = ages.sort_index(ascending=False)
print(rev_age) # index의 역순
7    77
6    41
5    45
4    56
3    66
2    90
1    61
0    37
Name: Age, dtype: int64
In [6]:
print(ages*2)
print("\n=================================\n")

print(ages + ages.sort_index(ascending=False))
0     74
1    122
2    180
3    132
4    112
5     90
6     82
7    154
Name: Age, dtype: int64

=================================

0     74
1    122
2    180
3    132
4    112
5     90
6     82
7    154
Name: Age, dtype: int64

ages * 2ages+ages.sort_index(ascending=False)의 결과값이 동일 벡터와 벡터의 연산은 일치하는 인덱스끼리 값을 수행

In [7]:
from IPython.core.display import HTML, display
display(HTML("<style> .container{width:100% !important;}</style>"))

'pandas > basic' 카테고리의 다른 글

07.handling_dataframe(bool-apply)  (0) 2018.12.09
06.handling_dataframe(bool)  (0) 2018.12.09
04.handling_series(basic)  (0) 2018.12.09
03.create_data_frame  (0) 2018.12.09
02.basic_statistic  (0) 2018.12.09
04_handling_series(basic)
In [1]:
import pandas as pd
from collections import OrderedDict
In [2]:
scientists = pd.DataFrame(OrderedDict([
    ["Occupation", ["Chemist", "Statistician"]],
    ["Born", ["1920-07-25", "1876-06-13"]],
    ["Died", ["1958-04-16", "1937-10-16"]],
    ["Age", [37, 61]]
]), index=["Rosaline Franklin", "William Gosset"])
In [3]:
first_row = scientists.loc["William Gosset"]
print(first_row)

## Age열에 정수를 전달해도 series의 자료형을 오브젝트로 인식
Occupation    Statistician
Born            1876-06-13
Died            1937-10-16
Age                     61
Name: William Gosset, dtype: object


index, values, keys

In [4]:
print("index: \t{}".format(first_row.index))
print("values: \t{}".format(first_row.values))
print("keys: {}".format(first_row.keys()))
index: 	Index(['Occupation', 'Born', 'Died', 'Age'], dtype='object')
values: 	['Statistician' '1876-06-13' '1937-10-16' 61]
keys: Index(['Occupation', 'Born', 'Died', 'Age'], dtype='object')
In [5]:
# index 속성 응용
# index 속성의 첫번째 값 추출
print("{}".format(first_row.index[0]))
Occupation
In [6]:
# key method 
# key method 결과값을 이용하여 인덱스의 첫번째 값을 추출
print("{}".format(first_row.keys()[0]))
Occupation


statistic

In [7]:
ages = scientists["Age"]
print(ages)
Rosaline Franklin    37
William Gosset       61
Name: Age, dtype: int64
In [8]:
print("mean: {}".format(ages.mean()))
print("min: {}".format(ages.min()))
print("max: {}".format(ages.max()))
print("std: {}".format(ages.std()))
mean: 49.0
min: 37
max: 61
std: 16.97056274847714


series method

series describe
append 2개 이상의 시리즈 연결
describe 요약 통계량 계산
drop_duplicates 중복값이 없는 시리즈
equals 시리즈에 해당 값을 요소가 있는지 확인
get_values 시리즈 값 구하기(values 속성과 동일)
isin 시리즈에 포합된 값이 있는지 확인
min 최소값
max 최댓값
mean 평균
median 중간값
replace 특정 값을 가진 시리즈 값을 교체
sample 임의의 값을 반환
sort_values 값을 정렬
to_frame 시리즈를 데이터프레임으로 변환
In [9]:
from IPython.core.display import HTML, display
display(HTML("<style> .container{width:100% !important;}</style>"))


'pandas > basic' 카테고리의 다른 글

06.handling_dataframe(bool)  (0) 2018.12.09
05.handling_series(apply)  (0) 2018.12.09
03.create_data_frame  (0) 2018.12.09
02.basic_statistic  (0) 2018.12.09
01.data_slicing  (0) 2018.12.09
03_create_data_frame
In [1]:
import pandas as pd
In [2]:
s = pd.Series(["bonggu", 31])
print(s)
0    bonggu
1        31
dtype: object


Series 생성

In [3]:
s = pd.Series(["bong_gu", "chatterBOX"])
s = pd.Series(["bong_gu", "cahtterBOX"], index=["person", "who"])
print(s)
person       bong_gu
who       cahtterBOX
dtype: object


DataFrame 생성

  • dictionary
In [4]:
scientists = pd.DataFrame({
    'Name': ["Bong_gu", "Yang_o"],
    "Job" : ["buyer", "Data_analysis"],
    "Born": ["SEOUL", "DONGHAE"],
    "Age": [31, 31],
    "Hate": ["JaeHyeop","JAeHyeop"]
}, index=["Bong_gu", "Yang_o"], columns=["Name", "Job", "Born", "Hate", "Age"] )
scientists
Out[4]:
Name Job Born Hate Age
Bong_gu Bong_gu buyer SEOUL JaeHyeop 31
Yang_o Yang_o Data_analysis DONGHAE JAeHyeop 31
In [5]:
## DataFrame에서 순서보장
from collections import OrderedDict

scientists = pd.DataFrame(OrderedDict([
    ["name", ["Rosaline Franklin", "William Gosset"]],
    ["Occupation", ["Chemist", "Statistician"]],
    ["Born", ["1920-07-25", "1876-06-13"]],
    ["Died", ["1958-04-16", "1937-10-16"]],
    ["Age", [37, 61]]
]))

print(scientists)
                name    Occupation        Born        Died  Age
0  Rosaline Franklin       Chemist  1920-07-25  1958-04-16   37
1     William Gosset  Statistician  1876-06-13  1937-10-16   61
In [6]:
from IPython.core.display import display, HTML

display(HTML("<style> .container{width:100% !important;}</style>"))

'pandas > basic' 카테고리의 다른 글

06.handling_dataframe(bool)  (0) 2018.12.09
05.handling_series(apply)  (0) 2018.12.09
04.handling_series(basic)  (0) 2018.12.09
02.basic_statistic  (0) 2018.12.09
01.data_slicing  (0) 2018.12.09
02_basic_statistic
In [1]:
import pandas as pd

df = pd.read_csv("./data/gapminder.tsv", sep="\t")
In [2]:
print(df.head(n=10))
       country continent  year  lifeExp       pop   gdpPercap
0  Afghanistan      Asia  1952   28.801   8425333  779.445314
1  Afghanistan      Asia  1957   30.332   9240934  820.853030
2  Afghanistan      Asia  1962   31.997  10267083  853.100710
3  Afghanistan      Asia  1967   34.020  11537966  836.197138
4  Afghanistan      Asia  1972   36.088  13079460  739.981106
5  Afghanistan      Asia  1977   38.438  14880372  786.113360
6  Afghanistan      Asia  1982   39.854  12881816  978.011439
7  Afghanistan      Asia  1987   40.822  13867957  852.395945
8  Afghanistan      Asia  1992   41.674  16317921  649.341395
9  Afghanistan      Asia  1997   41.763  22227415  635.341351


groupby

In [3]:
print(df.groupby("year")["lifeExp"].mean())
print("\n======================================\n")
print(df.groupby("continent")["country"].nunique())
print("\n======================================\n")
year
1952    49.057620
1957    51.507401
1962    53.609249
1967    55.678290
1972    57.647386
1977    59.570157
1982    61.533197
1987    63.212613
1992    64.160338
1997    65.014676
2002    65.694923
2007    67.007423
Name: lifeExp, dtype: float64

======================================

continent
Africa      52
Americas    25
Asia        33
Europe      30
Oceania      2
Name: country, dtype: int64

======================================

In [4]:
df.groupby(["year", "continent"])["lifeExp"].mean()
Out[4]:
year  continent
1952  Africa       39.135500
      Americas     53.279840
      Asia         46.314394
      Europe       64.408500
      Oceania      69.255000
1957  Africa       41.266346
      Americas     55.960280
      Asia         49.318544
      Europe       66.703067
      Oceania      70.295000
1962  Africa       43.319442
      Americas     58.398760
      Asia         51.563223
      Europe       68.539233
      Oceania      71.085000
1967  Africa       45.334538
      Americas     60.410920
      Asia         54.663640
      Europe       69.737600
      Oceania      71.310000
1972  Africa       47.450942
      Americas     62.394920
      Asia         57.319269
      Europe       70.775033
      Oceania      71.910000
1977  Africa       49.580423
      Americas     64.391560
      Asia         59.610556
      Europe       71.937767
      Oceania      72.855000
1982  Africa       51.592865
      Americas     66.228840
      Asia         62.617939
      Europe       72.806400
      Oceania      74.290000
1987  Africa       53.344788
      Americas     68.090720
      Asia         64.851182
      Europe       73.642167
      Oceania      75.320000
1992  Africa       53.629577
      Americas     69.568360
      Asia         66.537212
      Europe       74.440100
      Oceania      76.945000
1997  Africa       53.598269
      Americas     71.150480
      Asia         68.020515
      Europe       75.505167
      Oceania      78.190000
2002  Africa       53.325231
      Americas     72.422040
      Asia         69.233879
      Europe       76.700600
      Oceania      79.740000
2007  Africa       54.806038
      Americas     73.608120
      Asia         70.728485
      Europe       77.648600
      Oceania      80.719500
Name: lifeExp, dtype: float64


graph

In [5]:
%matplotlib inline
import matplotlib.pyplot as plt

plt.rcParams["figure.figsize"] = (12, 9)
plt.rcParams['axes.unicode_minus'] = False
In [6]:
lifeExp = df.groupby("year")["lifeExp"].mean()
lifeExp.plot()
plt.show()
In [7]:
from IPython.core.display import display, HTML

display(HTML("<style> .container{width:100% !important;}</style>"))

'pandas > basic' 카테고리의 다른 글

06.handling_dataframe(bool)  (0) 2018.12.09
05.handling_series(apply)  (0) 2018.12.09
04.handling_series(basic)  (0) 2018.12.09
03.create_data_frame  (0) 2018.12.09
01.data_slicing  (0) 2018.12.09
01_data_slicing
In [1]:
import pandas as pd
In [2]:
df = pd.read_csv("./data/gapminder.tsv", sep="\t")


데이터 확인하기

In [3]:
print(df.head()) # 앞부분
print("\n{}".format(type(df)))
print("\n{}".format(df.shape)) # shape
print("\n{}".format(df.columns)) # shape
print("\n{}\n".format(df.dtypes)) # columns type
print("{}".format(df.info())) # info
       country continent  year  lifeExp       pop   gdpPercap
0  Afghanistan      Asia  1952   28.801   8425333  779.445314
1  Afghanistan      Asia  1957   30.332   9240934  820.853030
2  Afghanistan      Asia  1962   31.997  10267083  853.100710
3  Afghanistan      Asia  1967   34.020  11537966  836.197138
4  Afghanistan      Asia  1972   36.088  13079460  739.981106

<class 'pandas.core.frame.DataFrame'>

(1704, 6)

Index(['country', 'continent', 'year', 'lifeExp', 'pop', 'gdpPercap'], dtype='object')

country       object
continent     object
year           int64
lifeExp      float64
pop            int64
gdpPercap    float64
dtype: object

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1704 entries, 0 to 1703
Data columns (total 6 columns):
country      1704 non-null object
continent    1704 non-null object
year         1704 non-null int64
lifeExp      1704 non-null float64
pop          1704 non-null int64
gdpPercap    1704 non-null float64
dtypes: float64(2), int64(2), object(2)
memory usage: 80.0+ KB
None


데이터 추출

In [4]:
## columns 1개 추출
country_df = df["country"]
print(type(country_df))
print(country_df.head())
print("\n==============================\n")
print(country_df.tail())
<class 'pandas.core.series.Series'>
0    Afghanistan
1    Afghanistan
2    Afghanistan
3    Afghanistan
4    Afghanistan
Name: country, dtype: object

==============================

1699    Zimbabwe
1700    Zimbabwe
1701    Zimbabwe
1702    Zimbabwe
1703    Zimbabwe
Name: country, dtype: object


columns 3개 추출 "country", "continent", "year"

  • type
  • head
  • tail
In [5]:
subset = df[["country", "continent", "year"]]

print(subset.dtypes) ## type
print("\n==============================\n")
print(subset.head()) ## head
print("\n==============================\n")
print(subset.tail()) ## tail
country      object
continent    object
year          int64
dtype: object

==============================

       country continent  year
0  Afghanistan      Asia  1952
1  Afghanistan      Asia  1957
2  Afghanistan      Asia  1962
3  Afghanistan      Asia  1967
4  Afghanistan      Asia  1972

==============================

       country continent  year
1699  Zimbabwe    Africa  1987
1700  Zimbabwe    Africa  1992
1701  Zimbabwe    Africa  1997
1702  Zimbabwe    Africa  2002
1703  Zimbabwe    Africa  2007


loc 속성으로 데이터 추출

  • 인덱스가 음이 아닌 정수 사용
  • 인덱스 vs 행번호
In [6]:
## 인덱스가 0, 99인 데이터 추출

print(df.loc[0])
print("\n==============================\n")
print(df.loc[99])
country      Afghanistan
continent           Asia
year                1952
lifeExp           28.801
pop              8425333
gdpPercap        779.445
Name: 0, dtype: object

==============================

country      Bangladesh
continent          Asia
year               1967
lifeExp          43.453
pop            62821884
gdpPercap       721.186
Name: 99, dtype: object
In [7]:
## 마지막 데이터 추출, shape()이용
### shape는 정수로서 실제크기를 말하지만
### pandas의 인덱스는 0부터 시작하기때문에 1을 빼줘야함

last_row = df.shape[0]-1
print(df.loc[last_row])

print("\n==============================\n")
## 마지막 데이터 추출, tail()이용
### n 인자 사용
print(df.tail(n=1))
country      Zimbabwe
continent      Africa
year             2007
lifeExp        43.487
pop          12311143
gdpPercap     469.709
Name: 1703, dtype: object

==============================

       country continent  year  lifeExp       pop   gdpPercap
1703  Zimbabwe    Africa  2007   43.487  12311143  469.709298
In [8]:
### 인덱스가 0, 99, 999인 데이터를 추출
### list사용

print(df.loc[[0, 99, 999]])
         country continent  year  lifeExp       pop    gdpPercap
0    Afghanistan      Asia  1952   28.801   8425333   779.445314
99    Bangladesh      Asia  1967   43.453  62821884   721.186086
999     Mongolia      Asia  1967   51.253   1149500  1226.041130


iloc 속성으로 데이터 추출

  • loc는 데이터프레임의 인덱스를 사용하여 데이터를 추출
  • iloc는 행번호를 사용하여 데이터를 추출
In [9]:
print(df.iloc[1])
print("\n==============================\n")
print(df.iloc[99])
country      Afghanistan
continent           Asia
year                1957
lifeExp           30.332
pop              9240934
gdpPercap        820.853
Name: 1, dtype: object

==============================

country      Bangladesh
continent          Asia
year               1967
lifeExp          43.453
pop            62821884
gdpPercap       721.186
Name: 99, dtype: object
In [10]:
### iloc에 -1은 행 데이터를 추출
print(df.iloc[-1])
print(df.iloc[1710])
country      Zimbabwe
continent      Africa
year             2007
lifeExp        43.487
pop          12311143
gdpPercap     469.709
Name: 1703, dtype: object

IndexErrorTraceback (most recent call last)
<ipython-input-10-8a802f6f3585> in <module>
      1 ### iloc에 -1은 행 데이터를 추출
      2 print(df.iloc[-1])
----> 3 print(df.iloc[1710])

/anaconda3/lib/python3.6/site-packages/pandas/core/indexing.py in __getitem__(self, key)
   1476 
   1477             maybe_callable = com._apply_if_callable(key, self.obj)
-> 1478             return self._getitem_axis(maybe_callable, axis=axis)
   1479 
   1480     def _is_scalar_access(self, key):

/anaconda3/lib/python3.6/site-packages/pandas/core/indexing.py in _getitem_axis(self, key, axis)
   2100 
   2101             # validate the location
-> 2102             self._validate_integer(key, axis)
   2103 
   2104             return self._get_loc(key, axis=axis)

/anaconda3/lib/python3.6/site-packages/pandas/core/indexing.py in _validate_integer(self, key, axis)
   2007         l = len(ax)
   2008         if key >= l or key < -l:
-> 2009             raise IndexError("single positional indexer is out-of-bounds")
   2010 
   2011     def _getitem_tuple(self, tup):

IndexError: single positional indexer is out-of-bounds
In [11]:
print(df.iloc[[0, 99, 999]])
         country continent  year  lifeExp       pop    gdpPercap
0    Afghanistan      Asia  1952   28.801   8425333   779.445314
99    Bangladesh      Asia  1967   43.453  62821884   721.186086
999     Mongolia      Asia  1967   51.253   1149500  1226.041130
In [12]:
### : -- 모든행
subset = df.loc[:, ["year", "pop"]]
print(subset.head())

subset = df.iloc[:, [2, 4, -1]]
print(subset.head())
   year       pop
0  1952   8425333
1  1957   9240934
2  1962  10267083
3  1967  11537966
4  1972  13079460
   year       pop   gdpPercap
0  1952   8425333  779.445314
1  1957   9240934  820.853030
2  1962  10267083  853.100710
3  1967  11537966  836.197138
4  1972  13079460  739.981106
In [13]:
small_range = range(5) ## 

subset = df.iloc[:, small_range]
print(subset.head())

print("\n==============================\n")
range2 = list(range(3, 6))
subset = df.iloc[:, range2]
print(subset.head())
       country continent  year  lifeExp       pop
0  Afghanistan      Asia  1952   28.801   8425333
1  Afghanistan      Asia  1957   30.332   9240934
2  Afghanistan      Asia  1962   31.997  10267083
3  Afghanistan      Asia  1967   34.020  11537966
4  Afghanistan      Asia  1972   36.088  13079460

==============================

   lifeExp       pop   gdpPercap
0   28.801   8425333  779.445314
1   30.332   9240934  820.853030
2   31.997  10267083  853.100710
3   34.020  11537966  836.197138
4   36.088  13079460  739.981106
In [14]:
range3 = list(range(0, 6, 2))
subset = df.iloc[:, range3]
print(subset.head())
print("\n==============================\n")
subset = df.iloc[:, 0:6:2]
print(subset.head())
       country  year       pop
0  Afghanistan  1952   8425333
1  Afghanistan  1957   9240934
2  Afghanistan  1962  10267083
3  Afghanistan  1967  11537966
4  Afghanistan  1972  13079460

==============================

       country  year       pop
0  Afghanistan  1952   8425333
1  Afghanistan  1957   9240934
2  Afghanistan  1962  10267083
3  Afghanistan  1967  11537966
4  Afghanistan  1972  13079460
In [15]:
### loc, iloc, 데이터셋이 클 수록 loc 속성이 유리
print(df.iloc[[0, 99, 999], [0, 3, 5]])
print(df.loc[[0, 99, 999], ["country", "lifeExp", "gdpPercap"]])
         country  lifeExp    gdpPercap
0    Afghanistan   28.801   779.445314
99    Bangladesh   43.453   721.186086
999     Mongolia   51.253  1226.041130
         country  lifeExp    gdpPercap
0    Afghanistan   28.801   779.445314
99    Bangladesh   43.453   721.186086
999     Mongolia   51.253  1226.041130
In [16]:
from IPython.core.display import display, HTML

display(HTML("<style> .container{width:100% !important;}</style>"))

'pandas > basic' 카테고리의 다른 글

06.handling_dataframe(bool)  (0) 2018.12.09
05.handling_series(apply)  (0) 2018.12.09
04.handling_series(basic)  (0) 2018.12.09
03.create_data_frame  (0) 2018.12.09
02.basic_statistic  (0) 2018.12.09

matrixdata.frame의 조작

  • apply(), sweep(), 그리고 outer()는 매트릭스와 동작
  • tapply()는 그룹화할때 사용

matrix와 array

a = matrix(1:20, nrow=5)
a
##      [,1] [,2] [,3] [,4]
## [1,]    1    6   11   16
## [2,]    2    7   12   17
## [3,]    3    8   13   18
## [4,]    4    9   14   19
## [5,]    5   10   15   20
  • apply
apply(a, 1, mean)
## [1]  8.5  9.5 10.5 11.5 12.5
apply(a, 2, mean)
## [1]  3  8 13 18

x = matrix(rnorm(20, mean=0, sd=10), nrow=4)
x
##            [,1]         [,2]         [,3]      [,4]      [,5]
## [1,]  -9.934007  0.006597635  -3.84921296  6.084250  6.165411
## [2,] -20.017956  1.991361506  -7.30670901  5.212370 -9.884440
## [3,]  -5.166649 -9.524993094  -0.08221195  3.766401 12.265300
## [4,]   6.278801 -2.190847659 -15.43569788 11.086988  4.038638
  • sweep()
# apply로 최솟값을 구한 후 각 원소에서 최솟값을 뺀다.
x1 = sweep(x, 1, apply(x, 1, min), `-`) 
x1
##           [,1]      [,2]      [,3]     [,4]     [,5]
## [1,]  0.000000  9.940604  6.084794 16.01826 16.09942
## [2,]  0.000000 22.009317 12.711247 25.23033 10.13352
## [3,]  4.358344  0.000000  9.442781 13.29139 21.79029
## [4,] 21.714499 13.244850  0.000000 26.52269 19.47434
# 최솟값을 뺀 후 각행을 최대값을 나눈다.
# 이는 python의 scikit-learn의 MinMaxScaler()와 같은 전처리와 같다.
x2 = sweep(x1, 1, apply(x, 1, max), `/`) 
x2
##           [,1]     [,2]      [,3]     [,4]     [,5]
## [1,] 0.0000000 1.612318 0.9869242 2.598084 2.611248
## [2,] 0.0000000 4.222517 2.4386695 4.840471 1.944128
## [3,] 0.3553394 0.000000 0.7698777 1.083658 1.776581
## [4,] 1.9585570 1.194630 0.0000000 2.392235 1.756504

  • outer()
# 첫번째 열에 1:3을 채우고, 첫번째 행에 1:10 까지 채운다
# 그리고 나머지 원소는 "*"를 이용하여 곱한 원소로 채운다
outer(1:3, 1:10, "*")
##      [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## [1,]    1    2    3    4    5    6    7    8    9    10
## [2,]    2    4    6    8   10   12   14   16   18    20
## [3,]    3    6    9   12   15   18   21   24   27    30

'R > functional' 카테고리의 다른 글

parallelize  (0) 2018.06.06
lapply  (0) 2018.06.06
parallelize.utf8

parallelize

parallel::mclapply(), parallel::mcMap() windows에서는 사용할 수 없고, mac에서만 사용할 수 있음

require(parallel)
## Loading required package: parallel
cores = detectCores() # 4

unlist(mclapply(21:30, sqrt, mc.cores=4))
##  [1] 4.582576 4.690416 4.795832 4.898979 5.000000 5.099020 5.196152
##  [8] 5.291503 5.385165 5.477226

이 경우에서, mclapply()는 실제로 lapply()보다 느리다. 여러 코어에 계산을 보내고 결과를 수집하기 때문이다. 다음 예를 통해 이를 확인해보면 다음과 같다

boot_df = function(x){
        x[sample(nrow(x), replace=TRUE), ]
}

rsquared = function(model){
        summary(model)$r.square
}
boot_lm = function(i){
        rsquared(lm(mpg~wt+disp, data=boot_df(mtcars)))
}

system.time(lapply(1:5000, boot_lm)) # 5000번 반복
##    user  system elapsed 
##   5.746   0.068   5.975
cores = detectCores()
system.time(mclapply(1:5000, boot_lm, mc.cores=cores)) # 5000번 반복
##    user  system elapsed 
##   6.969   0.253   3.141

'R > functional' 카테고리의 다른 글

data_frame, apply  (0) 2018.06.07
lapply  (0) 2018.06.06
  • 1000개의 무작위 균일 난수를 입력으로 제공받은 함수를 호출

# 임의의 무작위 데이터를 생성
l = replicate(20, rnorm(sample(1:10, 1), mean=0, sd=1), simplify=FALSE)

# for 루프로 작성

out = vector("list", length(l))
for (i in seq(l)) {
    out[[i]] = length(l[[i]])
}
unlist(out)
##  [1]  5  4  5  9 10  3  5  3  3  9  1 10  9  5  8  9  2  9 10  9
# lapply로 작성
unlist(lapply(l, length))
##  [1]  5  4  5  9 10  3  5  3  3  9  1 10  9  5  8  9  2  9 10  9

  • data.frame에 lapply 적용하기

# 평균(mean)으로 각 열을 나눔
mtcars[] = lapply(mtcars, function(x){
        x/mean(x) # x에는 data.frame의 각 열이 들어옴
    })

  • for문 사용

xs = runif(1e4)
res = c()

# 첫번째 방법
for (x in xs) {
    res = c(res, sqrt(x))
}

res = numeric(length(xs)) # numeric : 길이만큼 0벡터 만듬
for (i in seq(xs)) {
    res[i] = sqrt(xs[i])
    }

  • lapply로 구현하기

xs = runif(1e4)
ret = unlist(lapply(xs, function(x){
       sqrt(x)
    }))
ret[1:10]
##  [1] 0.4223976 0.5768065 0.9410556 0.2452229 0.8626159 0.9631699 0.5534060
##  [8] 0.6318466 0.8488031 0.8736057
res = numeric(length(xs))
ret = unlist(lapply(seq(xs), function(i){
        res[i] = sqrt(xs[i])
    }))
ret[1:10]
##  [1] 0.4223976 0.5768065 0.9410556 0.2452229 0.8626159 0.9631699 0.5534060
##  [8] 0.6318466 0.8488031 0.8736057

'R > functional' 카테고리의 다른 글

data_frame, apply  (0) 2018.06.07
parallelize  (0) 2018.06.06

#!/usr/bin/env python3


Linear Support Vector Machine: Soft Margin


# x1 = Sepal Length

# x2 - Petal Width


구분 가능한 소프트 마진 SVM을 텐서플로에 구현하기 위해서는 다음과 같은 비용함수를 구현해야합니다.

$$\frac{1}{n} \sum^{n}_{i=1}{max \left(0,1-y_{i}(Ax_{i}-b) \right)}+a \parallel A \parallel ^{2}$$

$A$는 기울기 벡터, $b$는 절편, $x_{i}$는 입력벡터, $y_{i}$는 실제 분류 대상 값(-1, 1)이고 $a$는 소프트 마진 구분 정도를 가리키는 규칙화 매개변수 입니다.


그래프 세션을 시작하고, 필요한 데이터를 로드합니다. 꽃받침 길이와 꽃잎 폭에 해당하는 데이터셋의 첫번재, 네 번째 변수를 로딩합니다. setosa종일 때는 값이 1이고, 그 외의 경우에는 값이 -1이 되게 대상 값을 로드합니다.

from sklearn.datasets import load_iris

import numpy as np

import tensorflow as tf

from tensorflow.python.framework import ops


ops.reset_default_graph()


sess = tf.Session()

iris = load_iris()



# load the data

x_vals = iris.data[:, [0,3]]

print(x_vals[:6])

# [[5.1 0.2]

#  [4.9 0.2]

#  [4.7 0.2]

#  [4.6 0.2]

#  [5.  0.2]

#  [5.4 0.4]]


y_vals = np.array([1 if y==0 else -1 for y in iris.target])

print(y_vals)

# [ 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 -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 -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]



데이터셋을 학습셋과 테스트셋으로 분류합니다. 학습셋, 테스트셋 모두에 정확도를 평가할 것입니다. 선형적으로 구분이 가능한 데이터셋이기 때문에 둘 모두 100%의 정확도를 기대할 수 있습니다.

# split data

from sklearn.model_selection import train_test_split


x_train, x_test, y_train, y_test = train_test_split(x_vals, y_vals,

                                                    random_state=0, stratify=y_vals)



작업크기를 설정하고 placeholder와 model 변수를 선언합니다. SVM 알고리즘 수렴에 도움이 되게 일괄 작업 크기를 크게 설정하였습니다. 일괄 작업 크기가 작으면 최대 마진 직선이 조금씩 움직일 것을 예상할 수 있습니다. 수렴이 진행됨에 따라 학습률의 크기를 줄이는 것이 이상적입니다. 

Sepal Lentgh와 Petal Width 두가지 예상 변수가 있기 때문에 A는 2x1의 형태로 변수를 만듭니다.

# placeholder

x_data = tf.placeholder(shape=[None, 2], dtype=tf.float32)

y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32)


# create Variable

A = tf.Variable(tf.random_normal(shape=[2, 1]))

b = tf.Variable(tf.random_normal(shape=[1, 1]))



모델 출력값을 선언합니다. 올바르게 분류된 경우라면 대상 값이 setosa 일 때는 1보다 크거나 같은 값이 출력되고, 대상 값이 setosa가 아닐 때는 -1보다 작거나 같은 값이 출력됩니다.

# fomula (y = ax - b)

fomula = tf.subtract(tf.matmul(x_data, A), b)



이 내용들을 조합하여 최대 마진 비용에 필요한 구성 요소들을 선언합니다.

먼저 벡터의 norm(L2)을 계산하는 함수를 선언합니다. 그런 다음에 마진 매개변수 $a$를 추가합니다.

그리고 이 두 항을 더하는 분류 비용 함수를 선언합니다.

L2_norm = tf.reduce_sum(tf.square(A))

# declare loss function

# Loss = summation(max(0, 1 - pred*actual)) + alpha * L2_norm(A)^2

alpha = tf.constant([0.01])


# Margin term in loss

left_term = tf.reduce_mean(tf.maximum(0., tf.subtract(1., tf.multiply(fomula, y_target))))


# Put terms together

loss = tf.add(left_term, tf.multiply(alpha, L2_norm))


학습셋과 테스트셋을 대상으로 정확도를 측정하기 위해 예측 함수와 정확도 함수를 선언합니다.

# prediction function

prediction = tf.sign(fomula)

accuracy = tf.reduce_mean(tf.cast(tf.equal(prediction, y_target), tf.float32))



최적화 함수를 선언하고 모델 변수를 초기화합니다.

train_step = tf.train.GradientDescentOptimizer(0.01).minimize(loss)


# initialize variable

init = tf.global_variables_initializer()

sess.run(init)



학습 루프를 실행합니다. 비용함수 값과 더불어 학습셋과 테스트셋 양쪽의 정확도를 기록합니다.

test_acc = []

train_acc = []

loss_vec = []

batch_size = 112

for i in np.arange(1000):

    rand_idx = np.random.choice(len(x_train), size=batch_size)

    rand_x = x_train[rand_idx]

    rand_y = y_train[rand_idx].reshape(-1, 1)


    sess.run(train_step, feed_dict={x_data:rand_x, y_target:rand_y})


    temp_loss = sess.run(loss, feed_dict={x_data:rand_x, y_target:rand_y})

    loss_vec.append(temp_loss)


    temp_train_acc = sess.run(accuracy, feed_dict={x_data:x_train, y_target:y_train.reshape(-1, 1)})

    train_acc.append(temp_train_acc)


    temp_test_acc = sess.run(accuracy, feed_dict={x_data:x_test, y_target:y_test.reshape(-1, 1)})

    test_acc.append(temp_test_acc)


    if (i+1) % 150 == 0:

        print('step {}:\n  A={}, b={}\nloss={}\n'.format(i+1, sess.run(A), sess.run(b), temp_loss))

        # step 150:

        # A=[[-0.1508689 ]

        #    [-0.02083003]], b=[[0.03109207]]

        # loss=[0.6171418]


        # step 300:

        # A=[[-0.06546283]

        #    [-0.4349473 ]], b=[[-0.04024722]]

        # loss=[0.39113477]


        # step 450:

        # A=[[ 0.01723341]

        #    [-0.8050836 ]], b=[[-0.12105083]]

        # loss=[0.41022006]


        # step 600:

        # A=[[ 0.07058643]

        #    [-1.1637722 ]], b=[[-0.19953299]]

        # loss=[0.2737451]


        # step 750:

        # A=[[ 0.14719042]

        #    [-1.503774  ]], b=[[-0.28408656]]

        # loss=[0.2209843]


        # step 900:

        # A=[[ 0.19714044]

        #    [-1.8002963 ]], b=[[-0.35890797]]

        # loss=[0.17502114]



결과를 그림으로 나타내려면 다음과 같이 계수를 추출하고, setosa 종 여부에 따라 x 값을 분리해야 합니다.

# visualization

import matplotlib.pyplot as plt

[[a1], [a2]] = sess.run(A)

[[b]] = sess.run(b)


slope = -a2/a1

icept = b


best_fit = []

for i in x_vals[:, 1]:

    temp = i * slope + icept

    best_fit.append(temp)


setosa_x = [setosa[1] for i, setosa in enumerate(x_vals) if y_vals[i] == 1]

setosa_y = [setosa[0] for i, setosa in enumerate(x_vals) if y_vals[i] == 1]

not_setosa_x = [setosa[1] for i, setosa in enumerate(x_vals) if y_vals[i] == -1]

not_setosa_y = [setosa[0] for i, setosa in enumerate(x_vals) if y_vals[i] == -1]



다음 코드를 이용하여 선형 구분자 및 정확도, 비용 함수를 그림으로 표현할 수 있습니다.

_, axe = plt.subplots(1, 3)


axe[0].scatter(setosa_x, setosa_y, marker='o', label='setosa')

axe[0].scatter(not_setosa_x, not_setosa_y, marker='o', label='non-setosa')

axe[0].plot(x_vals[:, 1], best_fit, c='red', label='Linear Separator')

axe[0].set_ylim([0, 10])

axe[0].legend(loc='best')

axe[0].set_title('Sepal Length vs Petal Width')

axe[0].set_xlabel('Petal Width')

axe[0].set_ylabel('Sepal Length')


axe[1].plot(train_acc, c='k', linestyle='-', label='Training Accuracy')

axe[1].plot(test_acc, c='r', linestyle='--', label='Test Accuracy')

axe[1].set_title('Train and Test Accuracy')

axe[1].set_xlabel('Genearation')

axe[1].set_ylabel('Accuracy')

axe[1].legend(loc='best')


axe[2].plot(loss_vec, c='k')

axe[2].set_title('Loss per Generation')

axe[2].set_xlabel('Generation')

axe[2].set_ylabel('loss')


plt.show()

학습 진행중인 모델의 최종 결과 그래프와 테스트셋과 학습셋의 정확도, 두 분류가 선형적으로 구분 가능하기 때문에 정확도가 100%에 도달




참고 자료: 

[1]TensorFlow Machine Learning Cookbook, Nick McClure

[2]https://github.com/nfmcclure/tensorflow_cookbook


'Tensorflow > Support Vector Machine' 카테고리의 다른 글

SVM intro  (0) 2018.05.01

Introduction


Support Vector Machine는 이진 분류 기법입니다. 기본 Idea는 두 분류 사이에 존재하는 선형 구분선hyperplane을 찾는 것입니다.

분류대상의 값을 -1, 1이라 가정합니다. 두 분류를 구분하는 직선은 무수히 많지만, 두 분류에서 가장 멀리 떨어진 구분선을 최적 선형 구분자라할 수 있습니다.


구분 가능한 두 분류 o, x가 주어졌을 때 두 분류를 구분하는 선형 구분 방정식을 찾고자 합니다.

왼쪽 그림을 보면 두 분류를 구분하는 여러 직선이 존재한다는 것을 알 수 있습니다. 오른쪽 그림은 분류 사이이의 magin을 최대로 하는 유일한 직선을 나타낸 것입니다.

마진의 폭은 $\frac{2}{llAll}$ 입니다.


초평면은 다음 방정식으로 표현할 수 있습니다.$$Ax-b=0$$

A는 기울기를 나태는 벡터고, $x$는 입력 벡터입니다. 최대 margin의 폭은 A L2 norm 값으로 나눈 값이 됩니다. 기하학적으로 2차원상의 한점에서 직선까지의 거리를 구하는 상황입니다.


선형적으로 구분 가능한 이진 분류 데이터의 경우 margin을 최대화 하려면 A의 L2 norm값을 최소화해야 합니다. 이 최솟값은 다음 제약도 만족해야 합니다.

$$y_{i}(Ax_{i}-b)\ge 1\forall i$$

이 제한을 만족해야만 한 분류에 속하는 모든 점이 구분선의 같은 편에 족재하게 됩니다.


모든 데이터셋을 선형적으로 구분할 수 있는 것은 아니기 때문에 선을 넘어가는 점을 대상으로 한 cost function을 도입할 수 있습니다. n개의 데이터 지점에 대해 soft margin cost function은 다음과 같이 정의합니다.

$$\frac{1}{n}\sum^{n}_{i=1}max \left(0,1 - y_{i}(Ax_{i}-b) \right) +a\parallel A \parallel ^{2}$$

데이터 포인트가 올바른 자리에 있으면 $y_{i}(Ax_{i}-b)$의 값은 항상 1보다 클 것입니다. 그러면 cost function의 좌측항은 0이 되어 cont function에 영향을 미치는 부분은

$a\parallel A\parallel ^{2}$인 margin의 크기만 남게 됩니다.


이 cost function을 사용하면 데이터 포인트가 margin line 을 넘어가는 경우를 허용하는 선형 구분 직선을 찾을 수 있습니다.

$a$ 값에 따라 허용하는 정도가 느슨할 수 있고, 엄격할 수 있습니다. 

$a$ 값이 클수록 margin의 폭이 늘어나고 작을 수록 엄격한 margin을 적용하게 됩니다.


'Tensorflow > Support Vector Machine' 카테고리의 다른 글

Linear Support Vector Machine: Soft Margin  (0) 2018.05.01

#!/usr/bin/env python3


Logistic Regression


logistic regression은 아래 1차 함수를 sigmoid와 함성합니다.

y = sigmoid(Ax + b)


birth weight data를 웹상에서 불러오겠습니다.


다음은 웹(github)에서 데이터를 불러오는 과정입니다.

현재 디렉토리에 'birth_weight.csv'가 없을 때 웹상에서 파일을 불러오는 코드는 다음과 같습니다.

import requests

import os.path


birth_weight_file = 'birth_weight.csv'

if not os.path.exists(birth_weight_file):

    url='https://raw.githubusercontent.com/nfmcclure/tensorflow_cookbook/master/01_Introduction/07_Working_with_Data_Sources/birthweight_data/birthweight.dat'

    load_file = requests.get(url)

    data = load_file.text.split('\r\n')

    header = data[0].split('\t')

    raw_birth_data = [[float(args) for args in row.split('\t') if len(args) >= 1] for row in data[1:] if len(row)>=1]

    length = len(raw_birth_data[0])

    birth_data = np.empty([0, length])

    for birth in raw_birth_data:

        birth_data = np.vstack([raw_birth_data, birth])


print(header)

# ['LOW', 'AGE', 'LWT', 'RACE', 'SMOKE', 'PTL', 'HT', 'UI', 'BWT']


print(birth_data)

# [[1.000e+00 2.800e+01 1.130e+02 ... 0.000e+00 1.000e+00 7.090e+02]

#  [1.000e+00 2.900e+01 1.300e+02 ... 0.000e+00 1.000e+00 1.021e+03]

#  [1.000e+00 3.400e+01 1.870e+02 ... 1.000e+00 0.000e+00 1.135e+03]

#  ...

#  [0.000e+00 2.400e+01 2.160e+02 ... 0.000e+00 0.000e+00 4.593e+03]

#  [0.000e+00 4.500e+01 1.230e+02 ... 0.000e+00 0.000e+00 4.990e+03]

#  [0.000e+00 4.500e+01 1.230e+02 ... 0.000e+00 0.000e+00 4.990e+03]]


이제 이 파일을 다음 코드를 이용하여 만들어보겠습니다.

import csv


with open(birth_weight_file, 'w', newline='') as f:

    writer = csv.writer(f)

    writer.writerow(header)

    writer.writerows(birth_data)

    f.close()



이제 birth_weight_file.csv 가 현재 디렉토리에 생성되었습니다.

이 파일을 다시 불러오겠습니다.

import numpy as np


birth_data = []

with open(birth_weight_file, newline='') as csvfile:

    csv_reader = csv.reader(csvfile)

    birth_header = next(csv_reader)

    birth_data = [[float(args) for args in row] for row in csv_reader]

    birth_data = np.array(birth_data)


print(birth_data)

# [[1.000e+00 2.800e+01 1.130e+02 ... 0.000e+00 1.000e+00 7.090e+02]

#  [1.000e+00 2.900e+01 1.300e+02 ... 0.000e+00 1.000e+00 1.021e+03]

#  [1.000e+00 3.400e+01 1.870e+02 ... 1.000e+00 0.000e+00 1.135e+03]

#  ...

#  [0.000e+00 2.400e+01 2.160e+02 ... 0.000e+00 0.000e+00 4.593e+03]

#  [0.000e+00 4.500e+01 1.230e+02 ... 0.000e+00 0.000e+00 4.990e+03]

#  [0.000e+00 4.500e+01 1.230e+02 ... 0.000e+00 0.000e+00 4.990e+03]]


pandas로도 csv파일을 불러올 수 있습니다.

import pandas as pd

birth_data = []

birth_data_pd = pd.read_csv(birth_weight_file)

birth_data = birth_data_pd.values


print(birth_data)

# [[1.000e+00 2.800e+01 1.130e+02 ... 0.000e+00 1.000e+00 7.090e+02]

#  [1.000e+00 2.900e+01 1.300e+02 ... 0.000e+00 1.000e+00 1.021e+03]

#  [1.000e+00 3.400e+01 1.870e+02 ... 1.000e+00 0.000e+00 1.135e+03]

#  ...

#  [0.000e+00 2.400e+01 2.160e+02 ... 0.000e+00 0.000e+00 4.593e+03]

#  [0.000e+00 4.500e+01 1.230e+02 ... 0.000e+00 0.000e+00 4.990e+03]

#  [0.000e+00 4.500e+01 1.230e+02 ... 0.000e+00 0.000e+00 4.990e+03]]



이제 데이터를 불러오는 과정이 끝났으니 tensorflow로 Logistic Regression을 적용해보겠습니다.

Losistic Regression을 적용하기 전에 algorithm을 살펴보겠습니다.

Logistic Regression의 흐름


우선 데이터셋에서 변수를 추출하겠습니다.

birth_m_data = birth_data[:,1:8]

print(birth_m_data)

# [[ 28. 113.   1. ...   1.   0.   1.]

#  [ 29. 130.   0. ...   0.   0.   1.]

#  [ 34. 187.   1. ...   0.   1.   0.]

#  ...

#  [ 24. 216.   0. ...   0.   0.   0.]

#  [ 45. 123.   0. ...   1.   0.   0.]

#  [ 45. 123.   0. ...   1.   0.   0.]]


birth_target = birth_data[:, 0]

print(birth_target)

# [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. 1. 1. 1. 1. 1. 1. 1. 1. 1. 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. 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. 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.]



scikit-learn의 train_test_split함수를 사용해도 되지만 파이썬 코드를 사용해서 훈련데이터와 학습데이터를 8:2로 분할하겠습니다.

# Split data into train/test = 80%/20%

data_size = len(birth_m_data)

train_idx = np.random.choice(data_size, round(data_size*0.8), replace=False)

temp_test_idx = set(np.arange(data_size)) - set(train_idx)

test_idx = np.array(list(temp_test_idx))


x_train = birth_m_data[train_idx]

x_test = birth_m_data[train_idx]

y_train = birth_target[test_idx]

y_test = birth_target[test_idx]


print(x_train)

# [[ 20. 105.   1. ...   0.   0.   0.]

#  [ 31. 100.   0. ...   0.   0.   1.]

#  [ 32. 132.   0. ...   0.   0.   0.]

#  ...

#  [ 20. 120.   1. ...   0.   0.   0.]

#  [ 20. 150.   0. ...   0.   0.   0.]

#  [ 16. 110.   1. ...   0.   0.   0.]]


print(x_test)

# [[ 20. 105.   1. ...   0.   0.   0.]

#  [ 31. 100.   0. ...   0.   0.   1.]

#  [ 32. 132.   0. ...   0.   0.   0.]

#  ...

#  [ 20. 120.   1. ...   0.   0.   0.]

#  [ 20. 150.   0. ...   0.   0.   0.]

#  [ 16. 110.   1. ...   0.   0.   0.]]



데이터셋 변수를 최솟값 0, 최댓값 1이 되도록 스케일링 해보겠습니다. 사용자 정의 함수를 이용하여 직접 코드를 짤 수도 있고,

scikit-learn의 MinMaxScaler 메소드로도 할 수 있습니다.

2가지 모두 해보겠습니다.

# user define function

def zero_to_one(m):

    col_max = np.max(x_train, axis=0)

    col_min = np.min(x_train, axis=0)

    return (m-col_min)/(col_max-col_min)


x_train_scaled_def = np.nan_to_num(zero_to_one(x_train))

print(x_train_scaled_def)

# [[0.19354839 0.14705882 1.         ... 0.         0.         0.        ]

#  [0.5483871  0.11764706 0.         ... 0.         0.         1.        ]

#  [0.58064516 0.30588235 0.         ... 0.         0.         0.        ]

#  ...

#  [0.19354839 0.23529412 1.         ... 0.         0.         0.        ]

#  [0.19354839 0.41176471 0.         ... 0.         0.         0.        ]

#  [0.06451613 0.17647059 1.         ... 0.         0.         0.        ]]


x_test_scaled_def = np.nan_to_num(zero_to_one(x_test))

print(x_test_scaled_def)

# [[0.19354839 0.14705882 1.         ... 0.         0.         0.        ]

#  [0.5483871  0.11764706 0.         ... 0.         0.         1.        ]

#  [0.58064516 0.30588235 0.         ... 0.         0.         0.        ]

#  ...

#  [0.19354839 0.23529412 1.         ... 0.         0.         0.        ]

#  [0.19354839 0.41176471 0.         ... 0.         0.         0.        ]

#  [0.06451613 0.17647059 1.         ... 0.         0.         0.        ]]


# scikit-learn

from sklearn.preprocessing import MinMaxScaler

scaler = MinMaxScaler()

scaler.fit(x_train)


x_train_scaled = scaler.transform(x_train)

print(x_train_scaled)

# [[0.19354839 0.14705882 1.         ... 0.         0.         0.        ]

#  [0.5483871  0.11764706 0.         ... 0.         0.         1.        ]

#  [0.58064516 0.30588235 0.         ... 0.         0.         0.        ]

#  ...

#  [0.19354839 0.23529412 1.         ... 0.         0.         0.        ]

#  [0.19354839 0.41176471 0.         ... 0.         0.         0.        ]

#  [0.06451613 0.17647059 1.         ... 0.         0.         0.        ]]


x_test_scaled = scaler.transform(x_test)

print(x_test_scaled)

# [[0.19354839 0.14705882 1.         ... 0.         0.         0.        ]

#  [0.5483871  0.11764706 0.         ... 0.         0.         1.        ]

#  [0.58064516 0.30588235 0.         ... 0.         0.         0.        ]

#  ...

#  [0.19354839 0.23529412 1.         ... 0.         0.         0.        ]

#  [0.19354839 0.41176471 0.         ... 0.         0.         0.        ]

#  [0.06451613 0.17647059 1.         ... 0.         0.         0.        ]]



이제 데이터로딩과 전처리가 완료 되었으니 tensorflow로 logistic 분석을 해보겠습니다.

먼저 tensorflow로 학습 algorithm tool을 만듭니다.

import tensorflow as tf

from tensorflow.python.framework import ops

import matplotlib.pyplot as plt


ops.reset_default_graph()

# Create graph

sess = tf.Session()


# Set for reproducible results

np.random.seed(seed=99)

tf.set_random_seed(seed=99)


# Initialize placeholders

x_data = tf.placeholder(shape=[None, 7], dtype=tf.float32)

y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32)


# Create variables for linear regression

A = tf.Variable(tf.random_normal(shape=[7,1]))

b = tf.Variable(tf.random_normal(shape=[1,1]))


# Declare model operations

fomula = tf.add(tf.matmul(x_data, A), b)


# Declare loss function (Cross Entropy loss)

loss = tf.reduce_mean(tf.nn.sigmoid_cross_entropy_with_logits(logits=fomula, labels=y_target))


# Declare optimizeraon

opt = tf.train.GradientDescentOptimizer(0.01)

train_step = opt.minimize(loss)


# Initialize variables

init = tf.global_variables_initializer()

sess.run(init)


# Actual Prediction

prediction = tf.round(tf.sigmoid(fomula))

predictions_correct = tf.cast(tf.equal(prediction, y_target), tf.float32) # tf.cast: 자료형태를 변환합니다. tf.cast(input tensor, dtype)

accuracy = tf.reduce_mean(predictions_correct)



이제 algorithm tool을 만들었으니 이를 바탕으로 학습을 시켜보겠습니다.

# Training loop

batch_size = 25

loss_vec = []

train_acc = []

test_acc = []

for i in range(1500):

    rand_idx = np.random.choice(len(x_train_scaled), size=batch_size)

    rand_x = x_train_scaled[rand_idx]

    rand_y = y_train[rand_idx].reshape(-1, 1) # reshape에 주의

    

    sess.run(train_step, feed_dict={x_data:rand_x, y_target:rand_y})

    temp_loss = sess.run(loss, feed_dict={x_data:rand_x, y_target:rand_y}) # train step을 실행

    loss_vec.append(temp_loss)


    temp_train = sess.run(accuracy, feed_dict={x_data:x_train_scaled, y_target:y_train.reshape(-1, 1)}) # accuracy를 실행, reshape 주의

    train_acc.append(temp_train)


    temp_test = sess.run(accuracy, feed_dict={x_data:x_test_scaled, y_target:y_test.reshape(-1, 1)}) # accuracy를 실행, reshape 주의

    test_acc.append(temp_test)

    

    if (i+1)%300==0:

        print('Loss = {}'.format(temp_loss))

        # Loss: 0.8982473015785217

        # Loss: 0.641773521900177

        # Loss: 0.630251944065094

        # Loss: 0.5026944279670715

        # Loss: 0.5662710070610046

        # Loss: 0.6175627708435059

        # Loss: 0.5372310876846313

sess.close()


위의 결과를 바탕으로 시각화를 하는 코드는 다음과 같습니다.

_, axe = plt.subplots(1, 2)

# Plot loss over time

axe[0].plot(loss_vec, 'k-')

axe[0].set_title('Cross Entropy Loss per Generation')

axe[0].set_xlabel('Generation')

axe[0].set_ylabel('Cross Entropy Loss')


# Plot train and test accuracy

axe[1].plot(train_acc, 'k-', label='Train Set Accuracy')

axe[1].plot(test_acc, 'r--', label='Test Set Accuracy')

axe[1].set_title('Train and Test Accuracy')

axe[1].set_xlabel('Generation')

axe[1].set_ylabel('Accuracy')

axe[1].legend(loc='lower right')

plt.show()

Loss 함수와 Accuracy




참고 자료: 

[1]TensorFlow Machine Learning Cookbook, Nick McClure

[2]https://github.com/nfmcclure/tensorflow_cookbook

'Tensorflow > Linear Regression' 카테고리의 다른 글

Elastic Net Regression  (0) 2018.04.29
LASSO and Ridge Regression  (1) 2018.04.27
Deming Regression  (0) 2018.04.27
Loss Function in Linear Regressions  (0) 2018.04.26
TensorFlow Way of LinearRegression  (0) 2018.04.26

#!/usr/bin/env python3


Elastic Net Regression


elastic net regression을 풀기위해서는 아래 방정식을 적용합니다.

$$y = Ax + b$$


#  y = Sepal Length

#  x = Pedal Length, Petal Width, Sepal Width


사용자 정의 형태로 만들어 인자를 변경하며 결과를 확인해보겠습니다.

elastic net regression의 cost function은 다음과 같습니다.

$$cost = mean \left( \sum{\left (y - \overset{\wedge}{y}\right)^{2} }\right) + 1 \cdot mean \left (\sum{\left | x_{i} \right |}\right) +1 \cdot mean \left (\sum {x^{2}_{i}} \right ) $$

import matplotlib.pyplot as plt

import numpy as np

import tensorflow as tf

from sklearn import datasets

from tensorflow.python.framework import ops


def elastic_net_func(idx, batch_size):

    ops.reset_default_graph()


    # iris.data = [(Sepal Length, Sepal Width, Petal Length, Petal Width)]

    iris = datasets.load_iris()

    x_vals = iris.data[:, idx]

    y_vals = iris.data[:, 0]


    # Initialize placeholders

    x_data = tf.placeholder(shape=[None, 1], dtype=tf.float32)

    y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32)


    # Create variables for linear regression

    A = tf.Variable(tf.random_normal(shape=[1,1]))

    b = tf.Variable(tf.random_normal(shape=[1,1]))


    with tf.Session() as sess:

        fomula = tf.add(tf.matmul(x_data, A), b)

        np.random.seed(seed=42)

        tf.set_random_seed(seed=42)


        l1_a_loss = tf.reduce_mean(tf.abs(A))

        l2_a_loss = tf.reduce_mean(tf.square(A))

        y_loss = tf.reduce_mean(tf.square(y_target - fomula)) 


        loss = tf.add(tf.add(l1_a_loss, l2_a_loss), y_loss) # cost function


        opt = tf.train.GradientDescentOptimizer(0.001)

        train_step = opt.minimize(loss)


        # Initialize variables

        init = tf.global_variables_initializer()

        init.run()


        loss_vec = []

        for i in range(1000):

            rand_idx = np.random.choice(len(x_vals), size=batch_size)

            rand_x = x_vals[rand_idx].reshape(-1, 1)

            rand_y = y_vals[rand_idx].reshape(-1, 1)


            my_dict = {x_data:rand_x, y_target:rand_y}

            sess.run(train_step, feed_dict=my_dict)

            temp_loss = sess.run(loss, feed_dict=my_dict)

            loss_vec.append(temp_loss)

            if (i+1)%200==0:

                print('step {}: A={}, b={}, Loss={}'.format(i+1, A.eval()[0], b.eval()[0], temp_loss))


        [coef] = A.eval()[0]

        [intercept] = b.eval()[0]


        best_params = []

        for i in x_vals:

            poly = i*coef + intercept

            best_params.append(poly)


    _, axe = plt.subplots(1, 2)

    axe[0].scatter(x_vals, y_vals, edgecolors='k', label='data points')

    axe[0].plot(x_vals, best_params, c='red', label='best pit line')

    axe[0].set_title('index={}\nslope = {:.5f}, intercept = {:.5f}'.format(idx ,coef, intercept))

    axe[0].set_xlabel('{}'.format(iris.feature_names[idx]))

    axe[0].set_ylabel('{}'.format(iris.feature_names[0]))

    axe[0].legend(loc=2)


    axe[1].plot(loss_vec, c='k')

    axe[1].set_xlabel('Generation')

    axe[1].set_ylabel('Loss')

    axe[1].set_title('Loss per Generation')


    plt.show()


사용자 정의 함수를 이용하여 인자에 따른 시각화를 해보겠습니다.

elastic_net_func(idx=1, batch_size=50)

sepal width vs sepal length

# step 200: A=[1.70271], b=[-0.14161193], Loss=6.42409610748291

# step 400: A=[1.6244563], b=[0.16109753], Loss=6.042064189910889

# step 600: A=[1.5415831], b=[0.44974053], Loss=5.765136241912842

# step 800: A=[1.4513652], b=[0.72334766], Loss=4.744622707366943

# step 1000: A=[1.3864329], b=[0.99185705], Loss=5.004234790802002



elastic_net_func(idx=2, batch_size=50)

petal length vs sepal length

# step 200: A=[1.3025422], b=[-0.19726731], Loss=7.4931416511535645

# step 400: A=[1.2043393], b=[0.24439183], Loss=5.619389057159424

# step 600: A=[1.1216723], b=[0.6478416], Loss=4.893489837646484

# step 800: A=[1.0472624], b=[1.0189508], Loss=5.274661540985107

# step 1000: A=[0.9723399], b=[1.3565185], Loss=2.696936845779419



elastic_net_func(idx=3, batch_size=50)

petal width VS sepal length

# step 200: A=[1.3511531], b=[1.0177041], Loss=14.15509033203125

# step 400: A=[1.5765594], b=[2.0053844], Loss=8.151086807250977

# step 600: A=[1.4302077], b=[2.6739304], Loss=5.979291915893555

# step 800: A=[1.2245288], b=[3.1957018], Loss=4.475618362426758

# step 1000: A=[1.0373899], b=[3.6267276], Loss=3.252098560333252




참고 자료: 

[1]TensorFlow Machine Learning Cookbook, Nick McClure

[2]https://github.com/nfmcclure/tensorflow_cookbook

'Tensorflow > Linear Regression' 카테고리의 다른 글

Logistic Regression  (0) 2018.05.01
LASSO and Ridge Regression  (1) 2018.04.27
Deming Regression  (0) 2018.04.27
Loss Function in Linear Regressions  (0) 2018.04.26
TensorFlow Way of LinearRegression  (0) 2018.04.26

#!/usr/bin/env python3


LASSO and Ridge Regression


이전 포스팅 보기

[1]Ridge, [2]Lasso


LASSO Ridge는 모두 출력 값에 미치는 regularization을 적용합니다.

tensorflow에서는 기울기A값에 의존하는 항을 cost function에 추가하면 이런 효과를 얻을 수 있습니다.


LASSO의 경우 기울기A가 특정 값 이상이 되면 cost를 크게 증가시키는 항을 추가해야합니다.

tensorflow의 논리 연산을 사용할 수도 있지만, 이렇게 하면 경사도를 계산할 수 없습니다. 대신에 step function을 연속 함수로 근사한 continuous heavyside step 함수를 조절해서 사용하여 문제를 해결 할 수 있습니다.


step function은 step이 중요합니다. step이 너무 높으면 수렴하지 않는 경우가 발생할 수 있습니다.


iris데이터셋으로 LASSO를 적용해보겠습니다. 


먼저 data를 로딩하고 placeholder를 생성하겠습니다.

import tensorflow as tf

from tensorflow.python.framework import ops

import numpy as np

from sklearn.datasets import load_iris


ops.reset_default_graph()


iris = load_iris()

# iris.keys(): dict_keys(['data', 'target', 'target_names', 'DESCR', 'feature_names'])

# iris.feature_names: ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']


regression_type = 'LASSO' # LASSO, Ridge


x_vals = iris.data[:, 3] # petal width

y_vals = iris.data[:, 0] # sepal length


x_data = tf.placeholder(shape=[None, 1], dtype=tf.float32)

y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32)


A = tf.Variable(tf.random_normal(shape=[1, 1]))

b = tf.Variable(tf.random_normal(shape=[1, 1]))


연속함수로 근사한 LASSO의 cost function인 heavyside step function은 다음과 같이 쓸 수 있습니다.$$y = \frac {1}{e^{ \left( x-\theta \right) \cdot (-\delta) }+1}$$


Ridge의 cost function은 다음과 같습니다.

$$mean\left(\sum { \left( y-\overset { \wedge  }{ y }  \right) ^{ 2 } }\right) + mean \left(\theta \sum {A^{ 2 } } \right)$$

여기서 $\theta$는 critical value임계값을 말하며 $\delta$는 step의 sensitivity민감도를 나타냅니다.


activate function인 continuous heavyside step함수는 다음 코드로 시각화 할 수 있습니다.

deltas = [0.1, 1, 5, 50]

_, axes = plt.subplots(2, 2)


for ax, delta in zip(axes.ravel(), deltas):

    line = np.linspace(-5, 5)

    theta = 0.9

    step = 1

    y = 1/(np.exp((line-theta)*(-delta)) + 1) * step

    ax.plot(line, y)

    ax.set_title('$\delta$={}'.format(delta))

plt.show()

$\delta$값에 따른 heavyside step function



따라서 LASSO와 Ridge의 cost function을 고려한 연산과정은 다음과 같습니다

with tf.Session() as sess:

    fomula = tf.add(tf.matmul(x_data, A), b)


    if regression_type == 'LASSO':

        lasso_params = tf.constant(0.9, dtype=tf.float32) # limit slope

        heavyside_step = tf.truediv(1., tf.add(tf.exp(tf.multiply(tf.subtract(A, lasso_params), -50)), 1))

        regularization = tf.multiply(99., heavyside_step)

        loss = tf.add(tf.reduce_mean(tf.square(y_target-fomula)), regularization)


    elif regression_type == 'Ridge':

        ridge_params = tf.constant(1., dtype=tf.float32)

        ridge_loss = tf.reduce_mean(tf.square(A))


loss = tf.expand_dims(tf.add(tf.reduce_mean(tf.square(y_target-fomula)),

                                     tf.multiply(ridge_params, ridge_loss)), 0) 


    opt = tf.train.GradientDescentOptimizer(learning_rate=0.001)

    train_step = opt.minimize(loss)


    init = tf.global_variables_initializer()

    init.run()


    loss_vec = []

    for i in range(1500):

        rnd_idx = np.random.choice(len(x_vals), size = batch_size)

        rnd_x = x_vals[rnd_idx].reshape(-1, 1)

        rnd_y = y_vals[rnd_idx].reshape(-1, 1)


        my_dict = {x_data:rnd_x, y_target:rnd_y}

        sess.run(train_step, feed_dict=my_dict)

        temp_loss = sess.run(loss, feed_dict=my_dict)

        loss_vec.append(temp_loss[0])


        if (i+1)%300 == 0:

            print('step={}: A={}, b={}, Loss={}'.format(i+1, A.eval(), b.eval(), temp_loss))

     # step=300: A=[[0.7634046]], b=[[2.8413053]], Loss=[[5.382721]]

     # step=600: A=[[0.75245243]], b=[[3.7877374]], Loss=[[1.4977918]]

     # step=900: A=[[0.7403701]], b=[[4.3101645]], Loss=[[0.6288415]]

     # step=1200: A=[[0.72969586]], b=[[4.60605]], Loss=[[0.40883213]]

     # step=1500: A=[[0.72272784]], b=[[4.7734385]], Loss=[[0.3297159]]

    slope = A.eval()[0]

    cept = b.eval()[0]



더 자세히 알아보기 위해  시각화 하면

best_fit = []    

for i in x_vals.ravel():

    poly = i*slope + cept

    best_fit.append(poly)


_, ax = plt.subplots(1, 2)

ax[0].scatter(x_vals, y_vals, edgecolors='k', label='Data Points')

ax[0].plot(x_vals, best_fit, c='red', label='Best fit line', linewidth=3)

ax[0].legend(loc=2)

ax[0].set_title('Petal Width vs Sepal Length')

ax[0].set_xlabel('Petal Width')

ax[0].set_ylabel('Sepal Length')


ax[1].plot(loss_vec, c='k')

ax[1].set_title(regression_type + ' Loss per Generation')

ax[1].set_xlabel('Generation')

ax[1].set_ylabel('Loss')


plt.show()

LASSO Regression과 Loss함수



위의 코드를 사용자 정의 함수로 만들어 LASSO, Ridge를 살펴보겠습니다



위의 결과는 아래 코드로 확인할 수 있습니다.

my_regression_type(regression_type='LASSO', batch_size=50)

# step=300: A=[[0.764575]], b=[[2.5382898]], Loss=[[5.8621655]]

# step=600: A=[[0.7535565]], b=[[3.618642]], Loss=[[1.8615394]]

# step=900: A=[[0.7427662]], b=[[4.2173624]], Loss=[[0.7045775]]

# step=1200: A=[[0.7338138]], b=[[4.5521526]], Loss=[[0.44136143]]

# step=1500: A=[[0.72335386]], b=[[4.739038]], Loss=[[0.23825285]]

LASSO Linear Regression과 Loss



my_regression_type(regression_type='Ridge', batch_size=50)

# step=300: A=[[1.9796406]], b=[[1.416961]], Loss=[8.540436]

# step=600: A=[[1.7114378]], b=[[2.419876]], Loss=[5.517313]

# step=900: A=[[1.4033114]], b=[[3.132286]], Loss=[3.4445624]

# step=1200: A=[[1.1520133]], b=[[3.6732914]], Loss=[2.298217]

# step=1500: A=[[0.95343864]], b=[[4.086554]], Loss=[1.4839184]

Ridge Linear Regression과 Loss 




참고 자료: 

[1]TensorFlow Machine Learning Cookbook, Nick McClure

[2]https://github.com/nfmcclure/tensorflow_cookbook

'Tensorflow > Linear Regression' 카테고리의 다른 글

Logistic Regression  (0) 2018.05.01
Elastic Net Regression  (0) 2018.04.29
Deming Regression  (0) 2018.04.27
Loss Function in Linear Regressions  (0) 2018.04.26
TensorFlow Way of LinearRegression  (0) 2018.04.26

#!/usr/bin/env python3


Deming Regression


Deming regression은 total regression전회귀로도 불립니다.

Deming regression는 y값과 x값의 오차를 최소화 합니다.

Deming regression을 구현하기 위해서는 Loss Cost Function을 수정해야합니다.

일반적인 선형 회귀의 비용함수는 수직거리를 최소화 하기 때문입니다.

직선의 기울기와 y절편을 이용하여 점까지 수식 거리를 구하고

tensorflow가 그 값을 최소화 하게 합니다.




직선까지의 수직 거리를 최소화(좌) 직선까지의 전체거리를 최소화(우)

출처: https://github.com/nfmcclure/tensorflow_cookbook/


데이터를 로딩하고 placeholder를 다음과 같이 생성해보겠습니다.

import tensorflow as tf

from tensorflow.python.framework import ops

import numpy as np

from sklearn.datasets import load_iris


ops.reset_default_graph()


iris = load_iris()

print(iris.keys())

# dict_keys(['data', 'target', 'target_names', 'DESCR', 'feature_names'])


print(iris.feature_names)

# ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']


# load the data

x_val = iris.data[:,3] # petal width

y_val = iris.data[:,0] # sepal length


# initialize placeholders

x_data = tf.placeholder(shape=[None, 1], dtype=tf.float32)

y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32)


# create variables for linear regression

A = tf.Variable(tf.random_normal(shape=[1, 1]))

b = tf.Variable(tf.random_uniform(shape=[1, 1]))



직선 $y = mx +b$와 점 $(x_{0}, y_{0})$가 주어졌을 때 둘 사이의 수직 거리는 다음과 같이 쓸 수 있습니다.

$$d=\frac{\left |y_{0}-(mx_{0}+b) \right|}{\sqrt{m^{2}+1}}$$



따라서 이 식을 이용하여 loss function을 재구성하여 linear regression을 구현해보겠습니다.

with tf.Session() as sess:

    fomula = tf.add(tf.matmul(x_data, A) ,b)

    demm_numer = tf.abs(tf.subtract(fomula, y_target)) # numerator

    demm_denom = tf.sqrt(tf.add(tf.square(A), 1)) # denominator

    loss = tf.reduce_mean(tf.truediv(demm_numer, demm_denom)) # 점과 직선사이의 거리


    opt = tf.train.GradientDescentOptimizer(learning_rate=0.15)

    train_step = opt.minimize(loss)


    init = tf.global_variables_initializer()

    init.run()


    loss_vec = []

    batch_size = 125

    

    for i in range(1000):

        rand_idx = np.random.choice(len(x_val), size=batch_size)

        rand_x = x_val[rand_idx].reshape(-1, 1)

        rand_y = y_val[rand_idx].reshape(-1, 1)


        my_dict = {x_data:rand_x, y_target:rand_y}

        sess.run(train_step, feed_dict=my_dict)

        temp_loss = sess.run(loss, feed_dict=my_dict)

        loss_vec.append(temp_loss)


        if (i+1)%100==0:

            print('step {}: A={}, b={}, Loss={}'.format(i+1, A.eval(), b.eval(), temp_loss))

            # step 100: A=[[2.8481812]], b=[[2.1150784]], Loss=0.39886653423309326

            # step 200: A=[[2.4716957]], b=[[2.581221]], Loss=0.4149680733680725

            # step 300: A=[[2.0858126]], b=[[3.1767926]], Loss=0.37009572982788086

            # step 400: A=[[1.5102198]], b=[[3.989578]], Loss=0.30516621470451355

            # step 500: A=[[1.0213077]], b=[[4.55735]], Loss=0.25061553716659546

            # step 600: A=[[1.0353084]], b=[[4.609328]], Loss=0.2725234925746918

            # step 700: A=[[1.0107175]], b=[[4.6160936]], Loss=0.3082656264305115

            # step 800: A=[[1.0400845]], b=[[4.612001]], Loss=0.27881959080696106

            # step 900: A=[[1.0318567]], b=[[4.6159105]], Loss=0.27347463369369507

            # step 1000: A=[[0.9662517]], b=[[4.5973287]], Loss=0.2258552461862564


    [slope] = A.eval()

    [cept] = b.eval()



위의 결과를 시각화하는 코드는 다음와 같습니다.

import matplotlib.pyplot as plt


best_fit = []

for i in x_val.ravel():

    poly = i*slope[0] + cept[0]

    best_fit.append(poly)


_, axes = plt.subplots(1, 2)

axes[0].scatter(x_val, y_val, edgecolors='k', label='Data Points')

axes[0].plot(x_val, best_fit, c='red', label='Best fit line')

axes[0].set_title('Petal Width vs Sepal Length', size=12)

axes[0].set_xlabel('Petal Width')

axes[0].set_ylabel('Sepal Length')

axes[0].legend(loc=2)


axes[1].plot(loss_vec, c='k')

axes[1].set_title('Demming Loss per Generation', size=12)

axes[1].set_xlabel('Iteration')

axes[1].set_ylabel('Demming Loss')


plt.show()

Demming Regression과 Loss Function




참고 자료: 

[1]TensorFlow Machine Learning Cookbook, Nick McClure

[2]https://github.com/nfmcclure/tensorflow_cookbook

#!/usr/bin/env python3


Loss Function in Linear Regressions


이 그림은 Learning rate에 따른 L1과 L2 손실함수를 보여줍니다. 

learning rate가 낮으면 정확도는 높아지지만 그만큼 많은 시간과 비용이 들어가며

learning rate가 높으면 발산 or 수렴할 수 있습니다. 따라서 적절한 learning rate를 선정하는 것이 중요합니다.




Linear Regression: L1 vs L2

출처: https://github.com/nfmcclure/tensorflow_cookbook



L1 Loss for Linear Least Squares 공식은 다음과 같습니다.

$$S =\sum_{i=1}^{N  }{ \left| y_{i}-\overset {\wedge }{y}_{i} \right |} $$

여기서 $N$은 data points의 수이고, $y_{i}$는 $y$의 실제 값이며, $\overset{\wedge}{y_{i}}$는 $i$번째 $y$의 예측 값입니다.


iris데이터셋에 L1 Loss function을 사용하여 결과를 확인해보면 다음과 같습니다.

from sklearn.datasets import load_iris

import tensorflow as tf

import numpy as np

from tensorflow.python.framework import ops


ops.reset_default_graph()


iris = load_iris()

print(iris.keys())

# dict_keys(['data', 'target', 'target_names', 'DESCR', 'feature_names'])

print(iris.feature_names)

# ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']


x_vals = iris.data[:, 3] # petal width

y_vals = iris.data[:, 0] # sepal length


batch_size = 25

lrn_rate = 0.1 # divergenc at 0.4

iterations = 100


x_data = tf.placeholder(shape=[None, 1], dtype=tf.float32)

y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32)


A = tf.Variable(tf.random_normal(shape=[1, 1]))

b = tf.Variable(tf.random_normal(shape=[1, 1]))


with tf.Session() as sess:

    model_output = tf.add(tf.matmul(x_data, A), b)


    loss_l1 = tf.reduce_mean(tf.abs(y_target - model_output))


    my_opt_l1 = tf.train.GradientDescentOptimizer(learning_rate=lrn_rate)

    train_step_l1 = my_opt_l1.minimize(loss_l1)


    init = tf.global_variables_initializer()

    init.run()


    loss_vec_l1 = []

    for i in range(iterations):

        rnd_idx = np.random.choice(len(x_vals), size=batch_size)

        rnd_x = x_vals[rnd_idx].reshape(-1, 1)

        rnd_y = y_vals[rnd_idx].reshape(-1, 1)


        feed = {x_data:rnd_x, y_target:rnd_y}

        sess.run(train_step_l1, feed_dict=feed)

        temp_loss_l1 = sess.run(loss_l1, feed_dict=feed)

        loss_vec_l1.append(temp_loss_l1)


        if (i+1)%10 == 0:

            print('Step {}: A={}, b={}'.format(i+1, A.eval(), b.eval()))

            # Step 10: A=[[-0.4101382]], b=[[-0.2588229]]

            # Step 20: A=[[0.7642619]], b=[[0.74117714]]

            # Step 30: A=[[1.9774618]], b=[[1.7411773]]

            # Step 40: A=[[2.3398612]], b=[[2.3091774]]

            # Step 50: A=[[2.252261]], b=[[2.6771777]]



이번에는 L2 Loss function에 대해 알아보겠습니다.

L2 Loss for Linear Least Squares는 다음과 같으며

$$S = \sum_{i=1}^{N}{\left(y_{i}-\overset{\wedge}{y_{i}} \right)^{2}}$$

위와 마찬가지로 $N$은 data points의 수이고, $y_{i}$는 $y$의 실제 값이며, $\overset{\wedge}{y_{i}}$는 $i$번째 $y$의 예측 값입니다.


다음 코드는 iris데이터에 L2 Loss function을 사용한 예입니다.

ops.reset_default_graph()


iris = load_iris()

print(iris.keys())

# dict_keys(['data''target', 'target_names', 'DESCR', 'feature_names'])

print(iris.feature_names)

# ['sepal length (cm)', 'sepal width (cm)', 'petal length (cm)', 'petal width (cm)']


x_vals = iris.data[:, 3] # petal width

y_vals = iris.data[:, 0] # sepal length


x_data = tf.placeholder(shape=[None, 1], dtype=tf.float32)

y_target = tf.placeholder(shape=[None, 1], dtype=tf.float32)


A = tf.Variable(tf.random_normal(shape=[1, 1]))

b = tf.Variable(tf.random_normal(shape=[1, 1]))


with tf.Session() as sess:

    fomula = tf.add(tf.matmul(x_data, A), b)

    loss_l2 = tf.reduce_mean(tf.square(y_target - fomula))


    opt = tf.train.GradientDescentOptimizer(lrn_rate)

    train_step_l2 = opt.minimize(loss_l2)


    init = tf.global_variables_initializer()

    init.run()


    loss_vec_l2 = []

    for i in range(iterations):

        rand_idx = np.random.choice(len(x_vals), size=batch_size)

        rand_x = x_vals[rand_idx].reshape(-1, 1)

        rand_y = y_vals[rand_idx].reshape(-1, 1)


        my_dict = {x_data:rand_x, y_target:rand_y}

        sess.run(train_step_l2, feed_dict=my_dict)


        temp_loss_l2 = sess.run(loss_l2, feed_dict=my_dict)

        loss_vec_l2.append(temp_loss_l2)


        if (i+1)%20 == 0:

            print('step {}: A={}, b={}'.format(i+1, A.eval()[0], b.eval()[0]))

            # step 20: A=[1.876194], b=[3.1437955]

            # step 40: A=[1.3978924], b=[4.1212244]

            # step 60: A=[1.1288545], b=[4.4799623]

            # step 80: A=[0.9617775], b=[4.64575]

            # step 100: A=[0.88910973], b=[4.7133427]



L1 Loss function과 L2 Loss function을 시각화하는 코드는 다음과 같습니다.             

import matplotlib.pyplot as plt


plt.plot(loss_vec_l1, c='k', label='L1 Loss')

plt.plot(loss_vec_l2, c='red', ls='--', label='L2 Loss')

plt.title('L1 and L2 Loss per Generation, learning rate={}'.format(lrn_rate))

plt.xlabel('Generation')

plt.ylabel('Loss')

plt.legend(loc=1)

plt.show()



learning rate=0.1일 때 수렴(좌) , learning rate=0.4일 때 발산(우)





참고 자료: 

[1]TensorFlow Machine Learning Cookbook, Nick McClure

[2]https://github.com/nfmcclure/tensorflow_cookbook


+ Recent posts