<scala class 예시 1> 다음 글이다.

http://[scala] class 예시 1 - 일반 클래스, 싱글톤 클래스(singleton class), 케이스 클래스(case class), main메소드/App 상속 클래스, 합성 타입(Compound), 제네릭(generic) 클래스






scala의 implicit은 다른 언어에서도 볼 수 있는 개념이지만, 더 큰 느낌이다.. C++언어와 C#에서 사용했던 클래스의 연산자(unary operator)를 재정의와 흡사하다.  하지만, 더 크게 보면, 클래스간 타입을 변환할 수 있다. (이런 언어 기능은 다른 언어에서도 본 적이 없다)


전에 (클래스 + 3)와 (3 + 클래스)와 같은 형태의 지원에 대해서는 아래 링크에서 조금 다뤘다. 

http://knight76.tistory.com/entry/scala-%EB%AC%B5%EC%8B%9C%EC%A0%81-%ED%83%80%EC%9E%85-%EB%B3%80%ED%99%98)



implicit converter부터 살펴본다.

class CompanyMember(val id: Int)
class SchoolMember(val id: Int)

3개의 클래스는 부모 클래스가 동일하지 않을 뿐더라 아예 호환할 수 없는 클래스이기에, 아래와 같은 코드를 짜면 type mismatch 에러가 발생한다. 



val nationalMember : SchoolMember = CompanyMember(1)


비슷하게 구현하려면 trait나 abstract class를 써야 할 것이다. 




암시적 변환은 일종의 숨겨진 함수 정도로 보면 된다. 표현식을 특정 타입으로 할당할 때, 잘 안되면, 범위(scope)에 있는 implicit type converter를 찾는다. 만약 implicit type converter가 있다면 그 코드로 변환한다.



이해할 수 있도록, 간단한 예제를 진행해 본다. 아래 코드는 컴파일만 되도록 한 코드이다. 


아까처럼 CompanyMember와 SchoolMember 케이스 클래스를 그대로 쓴다.

case class CompanyMember(val id: Int)
case class SchoolMember(val id: Int)

SchoolMember 클래스를 매개변수로 받아 CompnayMember 타입으로 리턴하는 메소드를 정의하고, 간단하게 사용한 후, 출력한다. 


def schoolMemberToCompanyMember(member: SchoolMember) : CompanyMember
= CompanyMember(member.id)

val sm : CompanyMember = schoolMemberToCompanyMember(SchoolMember(10))
println(sm.id)

결과는 10이다. 정상이다.




이제 implicit을 메소드 앞에 붙이고, 해당 메소드를 사용하는 부분에서 보이지 않도록 삭제한다. 


implicit def schoolMemberToCompanyMember(member: SchoolMember) : CompanyMember
= CompanyMember(member.id)

//val sm : CompanyMember = schoolMemberToCompanyMember(SchoolMember(10))
val sm : CompanyMember = SchoolMember(10)
println(sm.id)


실행 결과는 10이다. 동일한 결과가 나온다. (확 감이 오지 않은가?)



여기다가 하나 더 추가해 보자.. NationalMember를 추가해서 m이라는 멤버 필드을 두자.


case class CompanyMember(val id: Int)
case class SchoolMember(val id: Int)
case class NationalMember(val id: Int) {
val m = id + 100000
}



실행 코드는 추가해본다. 

implicit def schoolMemberToCompanyMember(member: SchoolMember) 
         : CompanyMember = CompanyMember(member.id)
implicit def companyMemberToNationalMember(member: CompanyMember) : NationalMember = NationalMember(member.id)

val sm : CompanyMember = SchoolMember(10)
println(sm.id)

val a : NationalMember = new CompanyMember(1)
println(a.m)


결과는 다음과 같다.


10

100001





implicit type conveter는 scope가 같아야 한다. 따라서 같은 scope에 두거나 import 문을 다음처럼 써야 한다. 



case class CompanyMember(val id: Int)
case class SchoolMember(val id: Int)
case class NationalMember(val id: Int) {
val m = id + 100000
}

object ImplicitRef {
implicit def schoolMemberToCompanyMember(member: SchoolMember) : CompanyMember = CompanyMember(member.id)

implicit def companyMemberToNationalMember(member: CompanyMember) : NationalMember = NationalMember(member.id)
}

object Main extends App {

import com.google.ImplicitRef._

val sm : CompanyMember = SchoolMember(10)
println(sm.id)

val a : NationalMember = new CompanyMember(1)
println(a.m)
}


결과는 위와 동일하다.




만약, 두 개의 implicit def 변환 중 schoolMember만 CompanyMember의 변환만 사용하고 싶다면, 다음과 같이 명확하게 정한다. 그래서 의도에 맞게 개발할 수 있다. 



import com.google.ImplicitRef.schoolMemberToCompanyMember

val sm : CompanyMember = SchoolMember(10)
println(sm.id)

val a : NationalMember = new CompanyMember(1) // type mismatch error
println(a.m)



스칼라의 묵시적 변환을 이해할 수 있는 코드를 살펴본다. 


scala.Predef 클래스를 참조하면, 묵시적 변환 코드가 있다. 




// "Autoboxing" and "Autounboxing" ---------------------------------------------------

implicit def byte2Byte(x: Byte) = java.lang.Byte.valueOf(x)
implicit def short2Short(x: Short) = java.lang.Short.valueOf(x)
implicit def char2Character(x: Char) = java.lang.Character.valueOf(x)
implicit def int2Integer(x: Int) = java.lang.Integer.valueOf(x)
implicit def long2Long(x: Long) = java.lang.Long.valueOf(x)
implicit def float2Float(x: Float) = java.lang.Float.valueOf(x)
implicit def double2Double(x: Double) = java.lang.Double.valueOf(x)
implicit def boolean2Boolean(x: Boolean) = java.lang.Boolean.valueOf(x)

implicit def Byte2byte(x: java.lang.Byte): Byte = x.byteValue
implicit def Short2short(x: java.lang.Short): Short = x.shortValue
implicit def Character2char(x: java.lang.Character): Char = x.charValue
implicit def Integer2int(x: java.lang.Integer): Int = x.intValue
implicit def Long2long(x: java.lang.Long): Long = x.longValue
implicit def Float2float(x: java.lang.Float): Float = x.floatValue
implicit def Double2double(x: java.lang.Double): Double = x.doubleValue
implicit def Boolean2boolean(x: java.lang.Boolean): Boolean = x.booleanValue



다음은 Option 예제이다. 아래 코드를 대충 보면 어이없는 코드이지만, Iterator와 Option을 비교한 값이다. 실행도 되는 코드이다. 타입이 다른데 비교가 가능한 이유가 바로 implicit 이다.


val name = Iterator("Samuel", "Santos")
val iterator = name.toIterator
if (iterator != Option("Samuel")) {
System.out.println("11")
}



Option object 소스에 implicit def option2Iterable이 있어서 Option을 Iterator와 비교할 수 있었다.

object Option {

import scala.language.implicitConversions

/** An implicit conversion that converts an option to an iterable value
*/
implicit def option2Iterable[A](xo: Option[A]): Iterable[A] = xo.toList






다음은 implicit class를 살펴본다. (이전까지 implicit conveter를 다뤘다)


String 객체에 대해서 암시적인 변환을 진행하는 코드인데, 클래스 기반이 되도록 하는 예시를 살펴본다.

implicit class를 선언할 때 non-implicit인 매개변수가 최소 하나가 반드시 있어야 한다.

implicit class Member(val _name: String) {
def name = "member name : " + _name
}
println("samuel".name)

결과는 다음과 같다.


member name : samuel



코드를 깔끔히 하기 위해서 아래와 같이 썼더니. wrong top statement declaration 컴파일 에러가 발생한다. object로 감싸야 한다.


implicit class Member(val _name: String) { .. }


wrapper object를 하나 만들어서 implicit class를 감싸게 한다. trait, class, object에 감싸야 한다. 이제 컴파일이 된다.


object MemberWrapper {
implicit class Member(val _name: String) {
def name = "member name : " + _name
}
}

object Main extends App {
import com.google.MemberWrapper._
println("samuel".name)
}


코드를 실행하면 다음과 같다.


member name : samuel



래퍼 클래스에서 implicit class를 추가할 수 있으며, 실행할 수 있다. 

object MemberWrapper {
implicit class Member(val _name: String) {
def name = "member name : " + _name
}
implicit class Person(val _id: Int) {
def name ="Person id : " + _id
}
}

object Main extends App {
import com.google.MemberWrapper._
println("samuel".name)
println(1.name)
}


필드를 사용한 예시에서 함수로 바꿔본다.


object MemberWrapper {
implicit class Member(val _name: String) {
def method[A](f: => A) : String = {
f
"member name : " + _name
}
}
}

object Main extends App {
import com.google.MemberWrapper._
println("samuel" method println("this function"))
}

결과는 다음과 같다. 



this function

member name : samuel








이제, 함수를 호출할 때 매개변수를 생략할 수 있는 implicit parameter를 살펴본다. 

implicit 매개변수가 있는 간단한 메소드이다.  메소드 매개변수 이름이 정확히 맞아야 한다. method 메소드는 i라는 변수를 기반으로 추측할 수 있다. 



def method(implicit i: Int) = println(i)
implicit val i = 10
method


중요한 것은 implicit modifier가 반드시 붙어야 동작한다.

만약 implicit modifier을 사용하지 않으면, could not find implicit value for parameter i: Int 이라는 런타임 에러가 발생한다.


첫 매개변수는 non-implicit이고 두 번째 매개변수를 implicit로 정의하려면, (..., implicit ...) 이 아닌

(.. )(implicit .. )으로 나눠야 한다. 이렇게 안하면 컴파일 에러가 발생한다.

def plus(i: Int) (implicit j: Int) = println(i + j)
implicit val j = 20
plus(10)

결과는 예상대로 30이다.



첫 매개변수는 non-implicit이고 두 번째, 세 번째 매개변수는 implicit를 정의한다면, 다음과 같을 것이다.


def plus(i: Int) (implicit j: Int, k: Int) = {
println("k:" + k)
println(i + j + k)
}
implicit val j = 20
plus(10)


결과는 쇼킹하다. implicit 값을 k에도 저장했다. 결과는 다음과 같다.

k:20

50



비슷한 방식으로 여러개를 두면 이렇게 전달된다. 반드시 타입에 영향을 줄 수 있으니 잘 써야 할 것 같다
def plus(i: Int) (implicit j: Int, k: Int, x:Int) = {
println("k:" + k)
println("x:" + x)
println(i + j + k + x)
}
implicit val j = 5
plus(10)



만약 타입이 다른 implicit 매개변수를 추가하면 어떤 일이 발생할까?
def plus(i: Int) (implicit j: Int, k: Long) = {
println("k:" + k)
println(i + j + k)
}
implicit val j = 5
plus(10)

역시 could not find implicit value for parameter k: Long라는 런타임 에러가 발생한다.
아래와 같이 수정해서 실행한다.

def plus(i: Int) (implicit j: Int, k: Long) = {
println("k:" + k)
println(i + j + k)
}
implicit val j = 5
implicit val k = 10L
plus(10)
결과는 다음과 같다.

k:10
25


매개변수를 모두 implicit을 주면 에러가 발생한다. 

def plus(implicit i: Int, j: Int) = {
println(i + j)
}
implicit val i = 5
implicit val j = 10
plus

에러 내용은 다음과 같다. 
ambiguous implicit values:
 both value i in object Main of type => Int
 and value j in object Main of type => Int
 match expected type Int


타입을 바꿔서 테스트한다.

def plus(implicit i: Int, j: Long) = {
println(i + j)
}
implicit val i = 5
implicit val j = 10L
plus
실행결과는 의도된대로 15이다. 


Future 클래스가 대표적인 implicit 매개변수 예시라 한다. (공부 더 해야지..)

http://docs.scala-lang.org/overviews/core/futures.html


  1. implicit val ec: ExecutionContext = ...
  2. val inverseFuture : Future[Matrix] = Future {
  3. fatMatrix.inverse()
  4. } // ec is implicitly passed





이제, class 3 으로 넘어간다. 


[scala] class 3 - 믹스인(mixin) 클래스, AnyVal, 유니버셜 트레이트(trait), abstract type


Posted by '김용환'
,



개연적 추론

개연적 추리

그럴만 하겠군





Induction [2] (귀납)은 그럴만하겠구나 방식으로 생각하는(plausible reasoning) 방식의 하나의 대표적인 예다.


연적 추론은 (논리적 엄밀성)을 보장하지 않으므로 사례를 통한 검증과 연역적 증명으로 논리적. 엄밀성을 (보완)해야 한다.


http://domath.kr/wiki/index.php/MPR_Intro#cite_note-2



http://m.blog.naver.com/selrim11/50106269307



더 읽어볼 거리

http://zolaist.org/wiki/index.php/%EA%B7%80%EB%82%A9%EC%9D%98_%EB%AC%B8%EC%A0%9C

Posted by '김용환'
,




parameter sweep, sweep은 하드웨어 용어에서 나온 듯 하다. 

구글에서 검색하면 논리/물리 회로를 테스트할 때가 자주 나온다.


parameter sweep은 일종의 자동화 튜닝 기능으로 특정 범위 내에서 나름 정해진 방법(random, step)으로 변수 값을 변화시켜 데이터 결과를 얻는다. 즉, 다양한 내용을 넣고 어떤 결과가 나오는지 명확하게 확인할 수 있기 때문이다. 



즉, 애플리케이션이나 테스트할 플랫폼을 블랙 박스로 여기고 다양한 정보를 정해진 방법으로 입력할 수 있는 형태를 parameter sweep이라 한다.


성능 분야 뿐 아니라 최근에 머신 러닝이 뜨면서 이런 단어를 쓰고 있다. 


https://msdn.microsoft.com/en-us//library/azure/dn905810.aspx


Tune Model Hyperparameters


 

Updated: April 29, 2016

Performs a parameter sweep on a model to determine the optimum parameter settings



이를 한국어로 표시하면 

https://msdn.microsoft.com/ko-kr/library/azure/dn905810.aspx


모델 하이퍼 조정


 

최적의 매개 변수 설정 결정 하는 모델에 매개 변수 비우기를 수행합니다

범주: 기계 학습 / 학습




정확하게 한국말로 표현하기가 어색한데,  '매개변수 비우기'라는 이름으로 번역되는 경우가 있다. 

내가 생각할 때는 이 말도 맞지만, 때로는  '매개변수로 전달'이라는 뜻으로 번역해도 괜찮을 것 같다. 



Posted by '김용환'
,