다운로드
작성자: admin 작성일시: 2017-06-28 19:10:45 조회수: 2815 다운로드: 200
카테고리: 기초 수학 태그목록:

함수

함수와 변수

함수(function)는 입력 값을 출력 값으로 바꾸어 출력하는 관계(relationship)를 말한다. 맵(map) 또는 매핑(mapping)이라는 용어를 사용하기도 한다. 예를 들어 $1, 2, 3, \ldots$ 란 숫자를 입력받아서 두 배가 되는 $2, 4, 6, \ldots$을 출력하는 것은 함수라고 할 수 있다.

$$ 1, 2, 3, \ldots \;\; \rightarrow \;\; \text{함수(function)} \;\; \rightarrow 2, 4, 6, \ldots $$

어떤 입력 값과 출력 값이 함수 관계를 이루기 위해서는 같은 입력 값에 대해서 항상 같은 출력 값이 나와야 한다. 예를 들어 똑같이 3을 입력했는데 어떤 경우에는 4가 나오고 어떤 경우에는 5가 나온다면 함수라고 할 수 없다.

함수에서 입력 변수가 가질 수 있는 값의 집합을 정의역(domain), 출력 변수가 가질 수 있는 값의 집합을 공역(range)이라고 한다. 정의역은 실수 전체인 경우가 많다. 하지만 함수에 따라서는 일부 숫자만 정의역으로 가질 수도 있다.

변수(variable)란 어떤 숫자를 대표하는 기호이다. 함수에서 입력 값이나 출력 값을 기호 즉 변수로 나타내기도 한다. 입력 값을 대표하는 변수를 입력 변수(input variable)라 하고 출력 값을 대표하는 변수를 출력 변수(output variable)라고 한다. 변수는 보통 $x$, $y$, $z$ 등의 알파벳 소문자로 표시한다. 함수에서 기호를 사용하는 이유는 입력 값과 출력 값의 관계를 수식으로 표현하기 위해서이다. 예를 들어 어떤 숫자를 입력으로 받아 그 값의 2배가 되는 값을 출력으로 한다면 다음처럼 표현할 수 있다.

$$ x \rightarrow 2x $$

또는

$$ y = 2x $$

함수를 여러개 사용할 때는 이름을 붙여 구별한다. 변수와 마찬가지로 함수도 $f$, $g$, $h$와 같이 알파벳 소문자로 표시한다. 함수를 표기할 때는 다음처럼 입력 변수를 붙여서 $f(x)$라고 표기한다. 이 기호는 "f 오브(of) x" 라고 읽는다.

$$ f(x) = 2x $$

파이썬의 함수는 이러한 수학 함수의 개념을 구현한 것으로 볼 수 있다. 예를 들어 다음 파이썬 함수 f는 입력 변수의 값을 2배하여 출력한다.

In:
def f(x):
    return 2 * x


x = 10
y = f(x)
print(x, y)
10 20

함수의 응용

서로 관계를 가지며 맺어지는 모든 숫자의 쌍은 함수라고 생각할 수 있다. 예를 들어,

  • 앰프의 조절 나사(knob)를 돌린 각도 $x$와 소리의 크기(volume) $y$
  • 등산을 할 때 출발점에서 간 거리 $x$와 그 위치의 해발 고도 $y$

등도 함수라고 할 수 있다.

예측(prediction) 문제도 독립 변수 $x$를 입력으로 가지고 종속 변수 $\hat{y}$이 원래의 출력 데이터 $y$와 가장 비슷한 함수 $\hat{y} = f(x)$를 찾는 문제라고 할 수 있다.

$$ y \approx \hat{y} = f(x) $$

연속

함수의 값이 중간에 갑자기 변하는 것을 불연속(discontinous)이라고 하고 반대로 중간에 갑자기 변하는 경우가 없으면 연속(continous)이라고 한다. 예를 들어 다음 함수는 헤비사이드 스텝 함수(Heaviside step function)라는 함수로 $x=0$에서 불연속인 함수이다.

$$ H(x) =\begin{cases} 0, & x < 0, \\ 1, & x \ge 0, \end{cases} $$
In:
def Heaviside(x):
    return 1 if x >= 0 else 0
In:
Heaviside(-0.01), Heaviside(0), Heaviside(0.01)
Out:
(0, 1, 1)

역함수

어떤 함수의 입력/출력 관계와 정반대의 입출력 관계를 가지는 함수를 역함수(inverse function)라고 한다.

예를 들어 어떤 함수 $f$가 $1, 2, 3, \ldots$ 를 입력받아서 $1, 4, 9, \ldots$ 을 출력하고 다른 함수 $g$는 반대로 $1, 4, 9, \ldots$ 를 입력받아서 $1, 2, 3, \ldots$ 을 출력하면 두 함수 $f$, $g$는 서로 역함수이다.

함수 $f$의 역함수는 $f^{-1}$ 기호로 표시한다.

$$ y = f(x), \;\;\; \rightarrow \;\;\; x = f^{-1}(y) $$

함수의 "역함수"와 함수의 "역수"는 다르다는 점에 주의한다.

$$ f^{-1}(x) \neq f(x)^{-1} = \dfrac{1}{f(x)} $$

함수가 존재한다고 해서 항상 역함수가 존재할 수 있는 것은 아니다. 예를 들어 두 개의 서로 다른 $x_1$, $x_2$값에 대해 $y$의 값이 $y^{\ast}$로 같다고 하자.

$$ f(x_1) = y^{\ast} $$$$ f(x_2) = y^{\ast} $$

그러면 반대로 $y^{\ast}$에 대응하는 $x$ 값을 선택할 수 없기 때문에 역함수가 존재하지 않는다.

예를 들어 다음 함수는 역함수가 존재하지 않는다.

$$ f(x) = x^2 $$

이 함수의 역함수가 존재하러면 정의역을 양수로 제한해야 한다 ($x > 0$) 이 때는 다음과 같이 역함수가 존재한다.

$$ f^{-1}(x) = \sqrt{x} $$

연습 문제 1

  1. 함수와 역함수의 또 다른 예를 생각해 보자.
  2. 원래의 함수 $f$에 들어갈 입력값 3개 $x_1$, $x_2$, $x_3$와 그에 해당하는 출력값 3개 $y_1$, $y_2$, $y_3$ 를 생각한다.
  3. 역함수에 $y_1$, $y_2$, $y_3$ 를 입력해서 진짜로 $x_1$, $x_2$, $x_3$이 나오는지 확인한다.

함수의 그래프

함수의 형상을 직관적으로 파악하기 위해 그래프(graph) 또는 플롯(plot)를 사용하기도 한다.

파이썬에서는 matplotlib의 라인 플롯을 사용하여 그래프를 만들 수 있다. 다만 matplotlib에서는 그래프를 작성할 영역을 작은 구간으로 나눈 독립 변수값 벡터 $x$ 를 생성하고 이 위치에 대한 함수값 벡터 $y$를 하나하나 계산하여 이렇게 만들어진 점을 직선으로 연결하는 방식으로 플롯을 그린다. 따라서 구간의 간격이 너무 크면 그래프가 부정확해지고 구간의 간격이 너무 작으면 계산 시간이 증가하며 메모리 등의 리소스가 낭비된다.

matplotlib으로 다음과 같은 함수의 그래프를 그려보자

$$ f(x) = x^3 - 3x^2 + x $$
In:
def f(x):
    return x**3 - 3 * x**2 + x

우선 $x=-1$ 부터 $x=3$까지 0.5 간격으로 9개의 점을 찍는다

In:
x = np.linspace(-1, 3, 9)
x
Out:
array([-1. , -0.5,  0. ,  0.5,  1. ,  1.5,  2. ,  2.5,  3. ])

그리고 이 위치에 대해 $y = f(x)$값을 구한다.

In:
y = f(x)
y
Out:
array([-5.   , -1.375,  0.   , -0.125, -1.   , -1.875, -2.   , -0.625,  3.   ])

이를 표로 나타내면 다음과 같다.

$x$ -1 -0.5 0 0.5 1 1.5 2 2.5 3
$y$ -5 -1.375 0 -0.125 -1 -1.875 -2 -0.625 3

matplotlib가 그리는 그래프는 이 표에 나타난 $x,y$ 쌍을 직선으로 연결한 그림이다.

In:
plt.plot(x, y, 'ro-')

plt.xlim(-2, 4)
plt.xticks(np.arange(-1, 4))
plt.yticks(np.arange(-5, 4))

plt.show()

이 $x$, $y$ 벡터의 구간을 더 조밀하게 만들면 그래프는 곡선으로 보이게 된다. 다음 그래프는 곡선으로 보이지만 실제로는 약 400개의 직선이 연결된 것이다.

In:
x = np.linspace(-1, 3, 400)
y = f(x)
plt.plot(x, y)

plt.xlim(-2, 4)
plt.xticks(np.arange(-1, 4))
plt.yticks(np.arange(-5, 4))

plt.show()

연습 문제 2

헤비사이드 스텝 함수의 그래프를 그려라.

역함수의 그래프

역함수의 그래프는 원래의 함수에서 $x$축과 $y$축과 바뀐 것이므로 $y=x$가 나타내는 직선(원점을 통과하는 기울기 1인 직선)을 대칭축으로 대칭인 함수의 그래프와 같다.

In:
def f1(x):
    return x ** 2

def f1inv(x):
    return np.sqrt(x)


x = np.linspace(0, 3, 300)
plt.plot(x, f1(x))
plt.plot(x, f1inv(x))
plt.plot(x, x, ":")
plt.axis("equal")
plt.xticks(range(-1, 10)); plt.xlim(0, 2)
plt.yticks(range(-1, 10)); plt.ylim(0, 2)
plt.show()

데이터 분석에서 많이 사용되는 함수들

데이터 분석에서 많이 사용되는 함수의 형태는 다항식(polynomial) 함수, 지수(exponential) 함수, 로그(log) 함수 등이다.

다항식 함수

다항식(polynomial) 함수는 상수항 $c_0$, 일차항 $c_1x$, 이차항 $c_2x^2$, $\cdots$ 등의 거듭제곱 항의 선형 조합으로 이루어진 함수이다. 다음은 단변수(uni-variate) 다항식 함수의 전형적인 형태이다.

$$ f(x) = c_0 + c_1 x + c_2 x^2 + \cdots + c_n x^n $$

지수 함수

정해진 어떤 값을 입력 값으로 거듭제곱하여 출력을 구하는 함수를 생각하자.

$$ y = a^x $$

거듭제곱을 할 때 아래에 있는 수를 밑(base)라고 한다. 밑을 오일러 수 $e$(약 2.718)로 하여 거듭제곱을 하는 함수를 지수 함수(exponential function)라고 한다.

$$ y = e^x $$

지수 함수는 다음처럼 표시할 수도 있다.

$$ y = \exp (x) =\exp x $$

지수 함수는 다음과 같은 특성을 가진다.

  • 양수($e$)를 거듭제곱한 값이므로 항상 양수이다.
  • $x=0$일 때 1이 된다.
  • $x$가 양의 무한대로 가면($x \rightarrow \infty$), 양의 무한대로 다가간다.
  • $x$가 음의 무한대로 가면($x \rightarrow -\infty$), 0으로 다가간다.
  • $x_1 > x_2$이면 $\exp{x_1} > \exp{x_2}$이다.

NumPy에서는 e 명령으로 오일러 수를, exp 명령으로 지수 함수를 계산한다. 여러가지 값을 대입하여 지수 함수의 값을 구해 위 성질이 성립하는지 살펴보자.

In:
np.e
Out:
2.718281828459045
In:
np.exp(-10), np.exp(-1), np.exp(-0.1), np.exp(0), np.exp(0.1), np.exp(1), np.exp(10)
Out:
(4.5399929762484854e-05,
 0.36787944117144233,
 0.90483741803595952,
 1.0,
 1.1051709180756477,
 2.7182818284590451,
 22026.465794806718)

위 특성에 의해 지수 함수의 그래프는 다음처럼 그려진다.

In:
xx = np.linspace(-2, 2, 100)
yy = np.exp(xx)
plt.plot(xx, yy)
plt.axhline(1, c='r', ls="--")
plt.axhline(0, c='r', ls="--")
plt.axvline(0, c='r', ls="--")
plt.show()

두 지수 함수의 곱의 값은 입력 값의 합의 지수 함수 값과 같다.

$$ e^{x_1} e^{x_2} = e^{x_1 + x_2}$$
In:
np.exp(2 + 3), np.exp(2) * np.exp(3)
Out:
(148.4131591025766, 148.4131591025766)

로지스틱(logistic) 함수는 지수 함수를 응용한 함수로 회귀 분석이나 인공 신경망에서 자주 사용된다.

$$ \sigma(x) = \dfrac{1}{1 + \exp(-x)} $$
In:
def logistic(x):
    return 1 / (1 + np.exp(-x))
In:
xx = np.linspace(-10, 10, 100)
plt.plot(xx, logistic(xx))
plt.title("logistic")
plt.show()

연습 문제 3

로지스틱 함수의 역함수를 구하라.

$$ y = \dfrac{1}{1 + \exp{(-x)}} $$

로그 함수

$e$를 거듭제곱하여 특정한 값이 되는 수를 찾아야 할 때가 있다. 예를 들어 $e$를 제곱하면 약 7.4가 되고 세제곱하면 약 20이 된다. 그렇다면 몇제곱을 해야 $10$이라는 값이 될까?

In:
np.exp(2), np.exp(3)
Out:
(7.3890560989306504, 20.085536923187668)

$e$를 약 2.3025851 거듭제곱을 하면 10이 되는 것을 확인할 수 있다. 이렇게 $e$를 거듭제곱하여 특정한 수 $a$가 되도록 해주는 수를 $\log a$라 표기하고 로그(log)라고 읽는다.

In:
np.exp(2.3025851)
Out:
10.000000070059542

NumPy에서 로그 함수 명령은 log이다.

In:
np.log(10)
Out:
2.3025850929940459

지수함수에서 밑이 $e$가 아닌 경우에는 다음처럼 로그를 이용하여 계산할 수 있다.

$$ y = a^x = (e^{\log a})^x = e^{x \log a} $$

로그는 지수함수의 출력이 특정한 값이 되게 하는 입력을 찾는 것이므로 지수함수의 역함수이다.

$$ y = \log x $$

로그 함수는 다음과 같은 특징을 가진다.

  • $x$값, 즉 입력변수값이 양수이어야 한다. 0이거나 음수이면 정의되지 않는다.
  • $x > 1$ 이면 양수가 된다.
  • $x=1$일 때 $y=0$이 된다.
  • $0 < x < 1$ 이면 음수가 된다.
  • $x_1 > x_2$이면 $\log{x_1} > \log{x_2}$이다.

로그 함수의 그래프는 다음과 같은 형태를 띈다.

In:
xx = np.linspace(0.01, 8, 100)
yy = np.log(xx)
plt.plot(xx, yy)
plt.axhline(0, c='r', ls="--")
plt.axvline(0, c='r', ls="--")
plt.axvline(1, c='r', ls="--")
plt.show()

로그 함수는 확률론에서 가장 많이 사용되는 함수이다. 그 이유는 로그 함수가 가지는 다음과 같은 특이한 성질때문이다.

로그 함수의 성질 1: 로그 함수는 곱하기를 더하기로 변환한다.

$$ \log{(x_1 \cdot x_2)} = \log{x_1} + \log{x_2} $$

이 성질을 확장하면 다음과 같이 표기한다.

$$ \log{\left(\prod_i x_i\right)} = \sum_i \left(\log{x_i}\right) $$

위 식에서 $x_1 = x_2 = \cdots = x $ 라면

$$ \log x^n = n \log x $$

연습 문제 4

$\log 2$의 값은 약 0.69, $\log 3$의 값은 약 1.10 이다. 이 때 $\log 12$의 값을 구하라.

로그 함수의 성질 2: 어떤 함수에 로그를 적용해도 함수의 최고점, 최저점의 위치는 변하지 않는다.

만약 양수값만을 가지는 함수가 있을 때 이 함수에 다시 로그함수를 적용하면 높낮이는 바뀌지만 최고점이나 최저점의 위치는 바뀌지 않는다. 따라서 최적화를 할 때 원래의 함수가 아니라 로그를 취한 함수에 대해 최적화를 실시하는 경우가 많다.

$$ \arg\max_x f(x) = \arg\max_x \log f(x) $$
In:
def ff(x):
    return x**3 - 12*x + 20 * np.sin(x) + 7
In:
xx = np.linspace(-4, 4, 300)
yy = ff(xx)

plt.subplot(211)
plt.plot(xx, yy)
plt.axhline(1, c='r', ls="--")
plt.title("f(x)")

plt.subplot(212)
plt.plot(xx, np.log(yy))
plt.axhline(0, c='r', ls="--")
plt.title("log f(x)")

plt.tight_layout()
plt.show()

로그 함수의 성질 3: 로그 함수는 0부터 1사이의 작은 값을 확대시켜 보여준다.

로그 함수는 0부터 1사이의 구간을 음의 무한대부터 0까지로 확장시켜주기 때문에 확률값처럼 0과 1사이에 있는 작은 값을 더 확실하게 비교할 수 있도록 한다.

In:
np.random.seed(0)
x = np.random.rand(5)
x = x / x.sum()

plt.subplot(211)
plt.bar(range(1, 6), x)
plt.ylim(0, 1)

plt.subplot(212)
plt.bar(range(1, 6), np.log(x))

plt.show()

소프트플러스(softplus) 함수는 지수 함수와 로그 함수를 결합하여 만든 함수로 인공 신경망에서 사용된다.

$$ \zeta(x) = \log( 1 + \exp(x)) $$
In:
def softplus(x):
    return np.log(1 + np.exp(x))
In:
xx = np.linspace(-10, 10, 100)
plt.plot(xx, softplus(xx))
plt.title("softplus")
plt.show()

다변수 함수

함수는 복수의 입력 변수를 가질 수도 있다. 이러한 함수를 다변수 함수(multivariate function)이라고 한다. 예를 들어 다음 수식은 함수 $f$가 2개의 입력 변수 $x$, $y$를 받아서 변수 $z$를 출력하는 다변수 함수라는 뜻이다.

$$ z = f(x, y) $$

다음은 다변수의 함수의 예이다.

$$ f(x, y) = 2x^2 + 6xy + 7y^2 - 26x - 54y + 107 $$

2개의 독립 변수를 가지는 함수 $f(x, y)$는 다음처럼 3차원 서피스 플롯(surface plot), 또는 컨투어 플롯(contour plot)으로 나타낼 수 있다.

In:
def f(x, y):
    return 2 * x**2 + 6 * x * y + 7 * y**2 - 26 * x - 54 * y + 107
In:
xx = np.linspace(-5, 5, 100)
yy = np.linspace(-4, 4, 100)
X, Y = np.meshgrid(xx, yy)
Z = f(X, Y)
In:
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()
fig.gca(projection='3d').plot_surface(X, Y, Z)
plt.xlabel('x')
plt.ylabel('y')
plt.title("Surface Plot")
plt.show()