๐Ÿ“study archive/ML DL

๋”ฅ๋Ÿฌ๋‹2์ฐจ์‹œ

Hush 2022. 8. 28. 20:23

ํผ์…‰ํŠธ๋ก (perceptron)์ด๋ž€?

๋‹ค์ˆ˜์˜ ์‹ ํ˜ธ๋ฅผ ์ž…๋ ฅ ๋ฐ›์•„ ํ•˜๋‚˜์˜ ์‹ ํ˜ธ๋ฅผ ์ถœ๋ ฅํ•œ๋‹ค.

์ถœ๋ ฅํ•˜๋Š” ์‹ ํ˜ธ๋Š” 1 ๋˜๋Š” 0์œผ๋กœ, "ํ๋ฅธ๋‹ค"์™€ "ํ๋ฅด์ง€ ์•Š๋Š”๋‹ค"๋ฅผ ํ‘œํ˜„ํ•œ๋‹ค.

์ž…๋ ฅ์‹ ํ˜ธ๊ฐ€ ๋‰ด๋Ÿฐ์— ๋ณด๋‚ด์งˆ ๋•Œ ๊ฐ๊ฐ ๊ณ ์œ ํ•œ ๊ฐ€์ค‘์น˜๊ฐ€ ๊ณฑํ•ด์ง„๋‹ค.

๊ทธ ํ›„ ๋‰ด๋ จ์—์„œ ๋ณด๋‚ธ ์‹ ํ˜ธ์˜ ์ดํ•ฉ์ด ์ •ํ•ด์ง„ ํ•œ๊ณ„(threshold)๋ฅผ ๋„˜์–ด์„ค ๋•Œ๋งŒ 1์„ ์ถœ๋ ฅํ•œ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด AND ๊ฒŒ์ดํŠธ์˜ ๊ฒฝ์šฐ w1, w2, theta ๋ฅผ 0.5, 0.5, 0.7๋กœ ์„ค์ •ํ•˜๋ฉด ํผ์…‰ํŠธ๋ก ์œผ๋กœ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•˜๋‹ค.

not AND๊ฒŒ์ดํŠธ์˜ ๊ฒฝํ›„ w1, w2, theta์˜ ๋ถ€ํ˜ธ๋ฅผ AND ๊ฒŒ์ดํŠธ์—์„œ ์ „๋ถ€ ๋’ค์ง‘์œผ๋ฉด ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•˜๋‹ค.

OR๊ฒŒ์ดํŠธ ๋˜ํ•œ ๋น„์Šทํ•œ ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

theta ๋ฅผ -b ๋กœ ์น˜ํ™˜ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์ด 0์„ ๊ธฐ์ค€์œผ๋กœ ํผ์…‰ํŠธ๋ก ์„ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋•Œ b๋ฅผ ํŽธํ–ฅ(bias)๋ผ๊ณ  ํ•œ๋‹ค.

numpy์˜ ์‚ฐ์ˆ ๊ณ„์‚ฐ๊ณผ, ์›์†Œ๋“ค์˜ ์ดํ•ฉ์„ ๊ตฌํ•ด์ฃผ๋Š” ํ•จ์ˆ˜ np.sum() ๋“ฑ์„ ํ™œ์šฉํ•˜๋ฉด  ํผ์…‰ํŠธ๋ก ์„ ์‰ฝ๊ฒŒ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

 

๋‹จ์ธต ํผ์…‰ํŠธ๋ก ์˜ ํ•œ๊ณ„

์šฐ๋ฆฌ๊ฐ€ ์ง€๊ธˆ๊นŒ์ง€ ๋…ผ์˜ํ•œ ํผ์…‰ํŠธ๋ก ์œผ๋กœ๋Š” XOR๊ฒŒ์ดํŠธ ๋“ฑ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์—†๋‹ค.

์ด๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ํผ์…‰ํŠธ๋ก ์„ ๋‹ค์ธต์œผ๋กœ ๊ตฌ์„ฑํ•˜๋ฉด ํ•œ๊ณ„๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

์‹ ๊ฒฝ๋ง์ด๋ž€

์‹ ๊ฒฝ๋ง์€ ์ž…๋ ฅ์ธต, ์€๋‹‰์ธต, ์ถœ๋ ฅ์ธต์œผ๋กœ ๊ตฌ์„ฑ๋œ๋‹ค.

0์ธต์ด ์ž…๋ ฅ์ธก, ๋งˆ์ง€๋ง‰์ธต์ด ์ถœ๋ ฅ์ธต์ด๊ณ  ๊ทธ ์‚ฌ์ด์— ์กด์žฌํ•˜๋Š” ๊ฒƒ๋“ค์ด ์€๋‹‰์ธต์ด๋‹ค.

๋‰ด๋Ÿฐ ์—ฐ๊ฒฐ ๋ฐฉ์‹์€ ํผ์…‰ํŠธ๋ก ๊ณผ ๋™์ผํ•˜๋‹ค.

 

ํ™œ์„ฑํ™” ํ•จ์ˆ˜

์ž…๋ ฅ ์‹ ํ˜ธ์˜ ์ดํ•ฉ์„ ์ถœ๋ ฅ ์‹ ํ˜ธ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜๋ฅผ ํ™œ์„ฑํ™” ํ•จ์ˆ˜(actication function)์ด๋ผ๊ณ  ํ•œ๋‹ค.

w1x1+w2x2+b ๊ฐ’์„ ํ™œ์„ฑํ™”ํ•จ์ˆ˜์— ์ž…๋ ฅํ•ด ์–ป์€ ๊ฒฐ๊ณผ๊ฐ€ y๊นŒ ๋˜๋Š” ๊ฒƒ์ด๋‹ค.

์ด ๊ณผ์ •์„ ๊ทธ๋ฆผ์œผ๋กœ ํ‘œํ˜„ํ•ด ๋ณด๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

๊ณ„๋‹จ ํ•จ์ˆ˜์™€ ์‹œ๊ทธ๋ชจ์ด๋“œ ํ•จ์ˆ˜

ํ™œ์„ฑํ™” ํ•จ์ˆ˜๋กœ ์‚ฌ์šฉ๋˜๋Š” ๊ณ„๋‹จํ•จ์ˆ˜๋Š” ์ž„๊ณ„๊ฐ’์„ ๊ฒฝ๊ณ„๋กœ ์ถœ๋ ฅ์ด ๋ฐ”๋€Œ๋Š” ํ•จ์ˆ˜๋กœ, ํŽด์…‰ํŠธ๋ก ์—์„œ ์‚ฌ์šฉํ•˜์˜€๋‹ค.

์‹œ๊ทธ๋ชจ์ด๋“œ ํ•จ์ˆ˜๋Š”  ์‹ ๊ฒฝ๋ง์—์„œ ํ™œ์„ฑํ™”ํ•จ์ˆ˜๋กœ ์‚ฌ์šฉ๋˜๋ฉฐ, ์ˆ˜์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

 

์„ ํ˜• ํ•จ์ˆ˜์™€ ๋น„์„ ํ˜• ํ•จ์ˆ˜

์„ ํ˜• ํ•จ์ˆ˜๋Š” ์ž…๋ ฅ๊ฐ’์— ๋”ฐ๋ผ ๊ฒฐ๊ณผ๊ฐ’์ด ์„ ํ˜•์ ์œผ๋กœ ์ถœ๋ ฅ๋˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.

๋น„์„ ํ˜• ํ•จ์ˆ˜๋Š” ์„ ํ˜• ํ•จ์ˆ˜๊ฐ€ ์•„๋‹Œ ๋ชจ๋“  ํ•จ์ˆ˜์ด๋‹ค.

๊ณ„๋‹จ ํ•จ์ˆ˜, ์‹œ๊ทธ๋ชจ์ด๋“œ ํ•จ์ˆ˜๋Š” ๋ชจ๋‘ ๋น„์„ ํ˜• ํ•จ์ˆ˜์— ์†ํ•œ๋‹ค.

ํ™œ์„ฑํ™”ํ•จ์ˆ˜๋กœ ์„ ํ˜• ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋ฉด ์—ฌ๋Ÿฌ ์ธต์„ ์Œ“์•„๋„ ์„ ํ˜• ํ˜•ํƒœ๋ฅผ ๋ฒ—์–ด๋‚  ์ˆ˜๊ฐ€ ์—†๋‹ค๋Š” ํ•œ๊ณ„์— ๋ด‰์ฐฉํ•œ๋‹ค.

๋”ฐ๋ผ์„œ ์ธต์„ ์Œ“์•„ ์‹ฌ์ธต์ ์ธ ๊ธฐ๋Šฅ์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ํ™œ์„ฑํ™”ํ•จ์ˆ˜๋กœ ๋ฐ˜๋“œ์‹œ ๋น„์„ ํ˜• ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค.

 

ReLU(Rectified Linear Unit)ํ•จ์ˆ˜

์‹œ๊ทธ๋ชจ์ด๋“œ ํ•จ์ˆ˜๋ฅผ ์‹ ๊ฒฝ๋ง ๋ถ„์•ผ์—์„œ ์˜ค๋ž˜์ „๋ถ€ํ„ฐ ์‚ฌ์šฉํ•ด์™”์œผ๋‚˜, ์ตœ๊ทผ์—๋Š” ReLUํ•จ์ˆ˜๋ฅผ ์ฃผ๋กœ ์ด์šฉํ•œ๋‹ค.

ReLUํ•จ์ˆ˜๋Š” ์ž…๋ ฅ์ด 0 ์„ ๋„˜์œผ๋ฉด ๊ทธ๋Œ€๋กœ, 0 ์ดํ•˜๋ฉด 0์„ ์ถœ๋ ฅํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ค.

 

๋‹ค์ฐจ์› ๋ฐฐ์—ด์ด๋ž€

๋‹ค์ฐจ์› ๋ฐฐ์—ด์ด๋ž€ ์ˆซ์ž์˜ ์ง‘ํ•ฉ์„ N์ฐจ์›์œผ๋กœ ๋‚˜์—ดํ•œ ๊ฒƒ์œผ๋กœ, ํŠนํžˆ 2์ฐจ์› ๋ฐฐ์—ด์„ ํ–‰๋ ฌ์ด๋ผ๊ณ  ๋ถ€๋ฅธ๋‹ค.

np.ndim() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๋ฐฐ์—ด์˜ ์ฐจ์› ์ˆ˜๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

ํ–‰๋ ฌ์˜ ๊ณฑ

ํ–‰๋ ฌ์˜ ๊ณฑ์„ ๊ณ„์‚ฐํ•˜๋ผ๋ฉด np.dot()ํ•จ์ˆ˜๋ฅผ ํ™œ์šฉํ•ด์•ผํ•œ๋‹ค.

ํ–‰๋ ฌ๊ณฑ์€ ๊ตํ™˜๋ฒ•์น™์ด ์„ฑ๋ฆฝํ•˜์ง€ ์•Š์Œ์— ์œ ์˜ํ•˜์ž.

๋‹ค์Œ ์‹ ๊ฒฝ๋ง์„ ํ–‰๋ ฌ ๊ณฑ์„ ์ด์šฉํ•˜์—ฌ ๊ตฌํ˜„ํ•ด๋ณด์ž.

import numpy as np

def calc(input_arr):
    W = np.array([[1, 3, 5],[2, 4, 6]])
    return np.dot(input_arr, W)
    
calc(np.array([1,2]))

 

3์ธต ์‹ ๊ฒฝ๋ง ๊ตฌํ˜„

๊ฐ€์ค‘์น˜์™€ ๊ฒฐ๊ณผ๊ฐ’์˜ ์œ„ ์ฒจ์ž๋Š” ํ•ด๋‹น ๊ฐ’์ด ๋ช‡ ์ธต์— ํ•ด๋‹นํ•˜๋Š”์ง€๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค.

๋˜ํ•œ ๊ฐ€์ค‘์น˜์˜ ์•„๋ž˜์ฒจ์ž๋Š” '๋‹ค์Œ ์ธต ๋ฒˆํ˜ธ, ์•ž ์ธต ๋ฒˆํ˜ธ'์ˆœ์„œ๋กœ ํ‘œ๊ธฐํ•œ๋‹ค.

์ด์ œ ํ–‰๋ ฌ์˜ ๊ณฑ์„ ์ด์šฉํ•˜๋ฉด 1์ธต์˜ '๊ฐ€์ค‘์น˜ ๋ถ€๋ถ„'์„ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ„์†Œํ™”๋œ ์‹์œผ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋ฅผ numpy๋ฅผ ํ™œ์šฉํ•˜์—ฌ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๊ฐ„๋‹จํžˆ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค.

import numpy as np

X = np.array([1.0, 0.5])
W = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
B = np.array([0.1, 0.2, 0.3])

Y = np.dot(X,W)+B

 

1์ธต์—์„œ 2์ธต์œผ๋กœ ๊ฐ€๋Š” ๊ณผ์ •๋˜ํ•œ ์œ ์‚ฌํ•˜๋‹ค.

 

2์ธต์—์„œ ์ถœ๋ ฅ์ธต์œผ๋กœ ์‹ ํ˜ธ๊ฐ€ ์ „๋‹ฌ๋˜๋Š” ๊ณผ์ •๋„ ๊ฑฐ์˜ ๋™์ผํ•˜์ง€๋งŒ, ํ™œ์„ฑํ™” ํ•จ์ˆ˜ ํ•˜๋‚˜๋งŒ ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค.

์ถœ๋ ฅ์ธต์˜ ํ™œ์„ฑํ™” ํ•จ์ˆ˜๋Š” ํ’€๊ณ ์ž ํ•˜๋Š” ๋ฌธ์ œ์˜ ์„ฑ์งˆ์— ๋งž๊ฒŒ ์ •์˜ํ•œ๋‹ค.

๊ฒฐ๊ณผ๊ฐ’์„ ์˜ˆ์ธกํ•˜๋Š” ํšŒ๊ท€๋ฌธ์ œ๋Š” ํ•ญ๋“ฑํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๊ณ ,

๋‘ ๊ฐœ์˜ ํด๋ž˜์Šค๋ฅผ ๋ถ„๋ฅ˜ํ•˜๋Š” ๋ฌธ์ œ์—๋Š” sigmoid ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉฐ, 

์—ฌ๋Ÿฌ ํด๋ž˜์Šค๋ฅผ ๋ถ„๋ฅ˜ํ•  ๋•Œ๋Š” softmax ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

 

์ด๋ฅผ ํ•œ๋ฒˆ์— ๊ตฌํ˜„ํ•˜๋ ค๋ฉด

init_network() ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ๊ฐ€์ค‘์น˜์™€ ํŽธํ–ฅ์„ ํ•œ ๋”•์…”๋„ˆ๋ฆฌ์— ์ €์žฅํ•˜๊ณ ,

forward() ํ•จ์ˆ˜๋กœ ์ž…๋ ฅ ์‹ ํ˜ธ๋ฅผ ์ถœ๋ ฅ์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ฒ˜๋ฆฌ ๊ณผ์ •์„ ๊ตฌํ˜„ํ•œ๋‹ค.

import numpy as np

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def identity_function(x):
    return x

def init_network():
    network = {}
    network['W1'] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])
    network['b1'] = np.array([0.1, 0.2, 0.3])
    network['W2'] = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])
    network['b2'] = np.array([0.1, 0.2])
    network['W3'] = np.array([[0.1, 0.3], [0.2, 0.4]])
    network['b3'] = np.array([0.1, 0.2])
    
    return network

def forward(network, x):
    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']
    
    a1 = np.dot(x, W1) + b1
    z1 = sigmoid(a1)
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)
    a3 = np.dot(z2, W3) + b3
    y = identity_function(a3)
    
    return y

network = init_network()
x = np.array([1.0, 0.5])
y = forward(network, x)
print(y) # [0.31682708 0.69627909]

 

์ถœ๋ ฅ์ธต์˜ ์„ค๊ณ„๋„ ์œ ์‚ฌํ•˜์ง€๋งŒ ์ถ”๊ฐ€๋กœ ์•Œ์•„์•ผ ํ•  ๊ฐœ๋…์ด ์žˆ๋‹ค.

 

๊ธฐ๊ณ„ํ•™์Šต ๋ฌธ์ œ๋Š” ํฌ๊ฒŒ ๋ถ„๋ฅ˜(classification) ๋ฌธ์ œ์™€ ํšŒ๊ท€(regression) ๋ฌธ์ œ๋กœ ๋‚˜๋‰˜๋Š”๋ฐ, ์‹ ๊ฒฝ๋ง์€ ๋‘ ๊ฒฝ์šฐ ๋ชจ๋‘ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

 

๋ถ„๋ฅ˜๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ์–ด๋А class์— ์†ํ•˜๋Š”์ง€ ๊ตฌ๋ถ„ํ•˜๋Š” ๋ฌธ์ œ๋กœ, ์‚ฌ์ง„ ์† ์ธ๋ฌผ์˜ ์„ฑ๋ณ„์„ ๊ตฌ๋ถ„ํ•˜๋Š” ๋ฌธ์ œ ๋“ฑ์ด ํ•ด๋‹น๋œ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ softmaxํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

ํšŒ๊ท€๋Š” ์ž…๋ ฅ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํŠน์ • ์ˆ˜์น˜๋ฅผ ์˜ˆ์ธกํ•˜๋Š” ๋ฌธ์ œ์ด๋‹ค. ์‚ฌ์ง„ ์† ์ธ๋ฌผ์˜ ๋ชธ๋ฌด๊ฒŒ๋ฅผ ์˜ˆ์ธกํ•˜๋Š” ๋ฌธ์ œ ๋“ฑ์ด ํ•ด๋‹น๋œ๋‹ค.

์ผ๋ฐ˜์ ์œผ๋กœ ํ•ญ๋“ฑ ํ•จ์ˆ˜๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

 

ํ•ญ๋“ฑ ํ•จ์ˆ˜๋Š” ์ž…๋ ฅ์„ ๊ทธ๋Œ€๋กœ ์ถœ๋ ฅํ•˜๋Š” ํ•จ์ˆ˜์ด๋‹ˆ ๋”ฑํžˆ ๊ตฌํ˜„์ด๋ž„ ๊ฒƒ๋„ ์—†๋‹ค.

softmax ํ•จ์ˆ˜์˜ ์‹์€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

 

์ž…๋ ฅ์‹ ํ˜ธ a = [0.3, 2.9, 4.0]์ผ๋•Œ softmaxํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

import numpy as np

A = np.array([0.3, 2.9, 4.0])

def softmax(input_arr):
    return np.exp(input_arr)/np.sum(np.exp(input_arr))

print(softmax(A))

๋‹ค๋งŒ softmax๋ฅผ ์ปดํ“จํ„ฐ๊ฐ€ ๊ณ„์‚ฐํ•˜๋Š” ๊ณผ์ •์—์„œ ์˜ค๋ฒ„ํ”Œ๋กœ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด๋ฅผ ์œ„ํ•ด ์ž…๋ ฅ ์‹ ํ˜ธ ์ค‘ ์ตœ๋Œ“๊ฐ’์„ ๋ชจ๋“  ํ•ญ์— ๋นผ์ฃผ๋Š” ํ…Œํฌ๋‹‰์„ ์‚ฌ์šฉํ•œ๋‹ค.(๊ทธ๋ž˜๋„ ๊ฐ’์€ ๋™์ผํ•˜๋‹ˆ๊นŒ)

์ด๋ฅผ ๊ตฌํ˜„ํ•˜๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค

c = np.max(a)
softmax(a - c) # ๊ฒŒ์‚ฐ ๊ฐ€๋Šฅ

 

softmax ํ•จ์ˆ˜๋ฅผ ์ด์šฉํ•˜๋Š” ๋ถ„๋ฅ˜ ๋ฌธ์ œ์˜ ๋‰ด๋Ÿฐ ์ˆ˜๋Š” ๋ถ„๋ฅ˜ํ•˜๊ณ  ์‹ถ์€ class์˜ ์ˆ˜๋กœ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ด ์ผ๋ฐ˜์ ์ด๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ์†๊ธ€์”จ ์ด๋ฏธ์ง€๋ฅผ ์ˆซ์ž 0๋ถ€ํ„ฐ 9๊นŒ์ง€๋กœ ๋ถ„๋ฅ˜ํ•˜๋Š” ๋ฌธ์ œ๋ผ๋ฉด ์ถœ๋ ฅ์ธต์˜ ๋‰ด๋Ÿฐ์€ 10๊ฐœ๋กœ ์„ค์ •ํ•œ๋‹ค.