Skip to content

Tutiroal_04

Yeon edited this page Jun 8, 2017 · 4 revisions

Caffe2 ๊ธฐ์ดˆ - Workspaces, Operators, and Nets

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” Caffe2์˜ ๊ธฐ๋ณธ์ ์ธ ๊ตฌ์„ฑ์š”์†Œ์— ๋Œ€ํ•ด ์†Œ๊ฐœํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

  • Workspaces(์ž‘์—… ๊ณต๊ฐ„)
  • Operators(์—ฐ์‚ฐ์ž)
  • Nets

์ด ์ฑ•ํ„ฐ๋ฅผ ์‹œ์ž‘ํ•˜๊ธฐ์— ์•ž์„œ Intro Tutorial์„ ๋ณต์Šตํ•˜์…”๋„ ์ข‹์Šต๋‹ˆ๋‹ค.

Browse the Tutorial

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ๋Š” Caffe2์˜ ๊ธฐ๋ณธ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋Š” ์—ฐ์‚ฐ์ž์™€ net์„ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋น„๋กฏํ•œ ๊ธฐ๋ณธ ๊ฐœ๋…์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋จผ์ €, caffe2๋ฅผ importํ•ฉ๋‹ˆ๋‹ค. core์™€ workspace๋Š” ๊ฐ€์žฅ ๋งŽ์ด ์“ฐ๊ฒŒ ๋  2๊ฐ€์ง€๊ฐ€ ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. caffe2์— ์˜ํ•ด ๋งŒ๋“ค์–ด์ง„ ํ”„๋กœํ† ์ฝœ ๋ฒ„ํผ๋ฅผ ์กฐ์ข…ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด, caffe2.proto์—์„œ caffe2_pb2๋„ ํ•จ๊ป˜ importํ•ฉ๋‹ˆ๋‹ค.

    # ๊ธฐ๋ณธ์ ์ธ ํŒŒ์ด์ฌ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋„ ๋ช‡ ๊ฐœ importํ•ด์ค๋‹ˆ๋‹ค. 
    from matplotlib import pyplot
    import numpy as np
    import time
    
    # ์•„๋ž˜์˜ droid๋“ค์ด ์ง€๊ธˆ ์ฐพ๋Š” ๊ฒƒ๋“ค์ž…๋‹ˆ๋‹ค. 
    from caffe2.python import core, workspace
    from caffe2.proto import caffe2_pb2
    # Let's show all plots inline.
    %matplotlib inline

caffe2๊ฐ€ GPU๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๋Š”๋‹ค๋Š” ๊ฒฝ๊ณ  ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. CPU ์ „์šฉ ๋นŒ๋“œ๋ฅผ ์‹คํ–‰์‹œํ‚ค๊ณ  ์žˆ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. CPU๋งŒ์œผ๋กœ๋„ ์•„๋ฌด ๋ฌธ์ œ์—†์ด ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ณ , ๋ฌธ์ œ๋ฅผ ์ผ์œผํ‚ค์ง€ ์•Š์œผ๋‹ˆ ๊ฑฑ์ •ํ•˜์ง€ ๋งˆ์„ธ์š”!

Workspaces

๋จผ์ € ๋ชจ๋“  ๋ฐ์ดํ„ฐ๊ฐ€ ๋ชจ์ด๋Š” workspace๋ถ€ํ„ฐ ์‚ดํŽด๋ด…์‹œ๋‹ค.

๋งŒ์•ฝ Matlab์— ์ต์ˆ™ํ•˜๋‹ค๋ฉด, workspace๋Š” ๋งŒ๋“ค๊ณ  ์ €์žฅํ•˜๋Š” blob๋“ค๋กœ ๊ตฌ์„ฑ๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ blob์„ numpy์˜ ndarray์™€ ์œ ์‚ฌํ•˜์ง€๋งŒ ์—ฐ์†์ ์ธ n์ฐจ์›์˜ Tensor๋กœ ๊ฐ„์ฃผ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์•„๋ž˜์„œ blob์€ ๋ชจ๋“  ์œ ํ˜•์˜ C++ ๊ฐ์ฒด๋ฅผ ์ €์žฅ ํ•  ์ˆ˜ ์žˆ๋Š” ์œ ํ˜•ํ™”๋œ ํฌ์ธํ„ฐ์ง€๋งŒ, Tensor๋Š” blob์— ์ €์žฅ๋œ ๊ฐ€์žฅ ์ผ๋ฐ˜์ ์ธ ์œ ํ˜•์ด๋ผ๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ค„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋จผ์ € ์ธํ„ฐํŽ˜์ด์Šค๋ถ€ํ„ฐ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

Blobs()๋Š” workspace์— ์กด์žฌํ•˜๋Š” ๋ชจ๋“  blob๋“ค์„ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค. HasBlob() ์ฟผ๋ฆฌ๋Š” workspace์— blob์ด ์กด์žฌํ•˜๋Š”์ง€ ์—ฌ๋ถ€๋ฅผ ์•Œ๋ ค์ค๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ ์•„๋ฌด๊ฒƒ๋„ ๊ฐ–๊ณ ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    print("Current blobs in the workspace: {}".format(workspace.Blobs()))
    print("Workspace has blob 'X'? {}".format(workspace.HasBlob("X")))

FeedBlob()์„ ์‚ฌ์šฉํ•ด blob์„ workspace๋กœ ๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

    X = np.random.randn(2, 3).astype(np.float32)
    print("Generated X from numpy:\n{}".format(X))
    workspace.FeedBlob("X", X)
    Generated X from numpy:
    [[-0.56927377 -1.28052795 -0.95808828]
     [-0.44225693 -0.0620895  -0.50509363]]

์ด์ œ workspace์— ์–ด๋–ค blob์ด ์žˆ๋Š”์ง€ ํ™•์ธ ํ•ด ๋ด…์‹œ๋‹ค.

    print("Current blobs in the workspace: {}".format(workspace.Blobs()))
    print("Workspace has blob 'X'? {}".format(workspace.HasBlob("X")))
    print("Fetched X:\n{}".format(workspace.FetchBlob("X")))
    Current blobs in the workspace: [u'X']
    Workspace has blob 'X'? True
    Fetched X:
    [[-0.56927377 -1.28052795 -0.95808828]
     [-0.44225693 -0.0620895  -0.50509363]]

์ € ๋ฐฐ์—ด๋“ค์ด ๋™์ผํ•œ ๊ฒƒ์ธ์ง€ ํ™•์ธ ํ•ด ๋ด…์‹œ๋‹ค.

    np.testing.assert_array_equal(X, workspace.FetchBlob("X"))

๋งŒ์•ฝ, ์กด์žฌํ•˜์ง€ ์•Š๋Š” blob์— ์ ‘๊ทผ์„ ์‹œ๋„ํ•œ๋‹ค๋ฉด ์—๋Ÿฌ๊ฐ€ ๋‚˜ํƒ€๋‚  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

    try:
        workspace.FetchBlob("invincible_pink_unicorn")
    except RuntimeError as err:
        print(err)
    [enforce fail at pybind_state.cc:441] gWorkspace->HasBlob(name).

์ฆ‰์‹œ ์‚ฌ์šฉํ•˜์ง€ ๋ชปํ•  ์ˆ˜๋„ ์žˆ๋Š” ๊ฒƒ์ด ์žˆ์Šต๋‹ˆ๋‹ค: ํŒŒ์ด์ฌ์—์„œ, ๊ฐ๊ฐ ๋‹ค๋ฅธ ์ด๋ฆ„์„ ๊ฐ–๊ณ  ์žˆ๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ workspace๋ฅผ ๊ฐ–๊ณ  ์ž‘์—…์„ ์ „ํ™˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋‹ค๋ฅธ workspace์— ์กด์žฌํ•˜๋Š” blob๋“ค์€ ์„œ๋กœ์—๊ฒŒ ๋…๋ฆฝ์ ์ž…๋‹ˆ๋‹ค. CurrentWorkspace ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•˜์—ฌ ํ˜„์žฌ workspace๋ฅผ ์กฐํšŒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฆ„(gutentag)์„ ์ด์šฉํ•ด ์ž‘์—… ๊ณต๊ฐ„์„ ์ „ํ™˜ํ•˜๊ณ , ๋งŒ์•ฝ ์กด์žฌํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด ์ƒ์„ฑํ•ด๋ด…์‹œ๋‹ค.

    print("Current workspace: {}".format(workspace.CurrentWorkspace()))
    print("Current blobs in the workspace: {}".format(workspace.Blobs()))

    # workspace๋ฅผ ์ „ํ™˜ํ•ฉ๋‹ˆ๋‹ค. ๋‘ ๋ฒˆ์งธ ์ธ์ž "True"๋Š” workspace๊ฐ€ ์—†์„ ๋•Œ ์ƒ์„ฑํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
    workspace.SwitchWorkspace("gutentag", True)

    # ํ˜„์žฌ workspace๋ฅผ ์ถœ๋ ฅ ํ•ด๋ด…์‹œ๋‹ค. ์•„์ง workspace์— ์•„๋ฌด๊ฒƒ๋„ ์—†๋Š” ๊ฒƒ์„ ์žŠ์ง€ ๋งˆ์„ธ์š”.
    print("Current workspace: {}".format(workspace.CurrentWorkspace()))
    print("Current blobs in the workspace: {}".format(workspace.Blobs()))
    Current workspace: default
    Current blobs in the workspace: ['X']
    Current workspace: gutentag
    Current blobs in the workspace: []

๊ธฐ๋ณธ workspace๋กœ ๋‹ค์‹œ ๋Œ์•„๊ฐ€ ๋ด…์‹œ๋‹ค.

    workspace.SwitchWorkspace("default")
    print("Current workspace: {}".format(workspace.CurrentWorkspace()))
    print("Current blobs in the workspace: {}".format(workspace.Blobs()))
    Current workspace: default
    Current blobs in the workspace: ['X']

๋งˆ์ง€๋ง‰์œผ๋กœ, ResetWorkspace()๋Š” ํ˜„์žฌ workspace์˜ ๋ชจ๋“  ๋‚ด์šฉ์„ ์‚ญ์ œํ•ฉ๋‹ˆ๋‹ค.

    workspace.ResetWorkspace()

Operators

Caffe2์˜ ์—ฐ์‚ฐ์ž๋Š” ์ผ์ข…์˜ ํ•จ์ˆ˜๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. C++์ชฝ์—์„œ๋Š” ๋ชจ๋‘ ๊ณตํ†ต ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ํŒŒ์ƒ๋˜์–ด ์œ ํ˜•๋ณ„๋กœ ๋“ฑ๋ก๋˜๋ฏ€๋กœ runtime ์ค‘์— ๋‹ค๋ฅธ ์—ฐ์‚ฐ์ž๋ฅผ ํ˜ธ์ถœ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์—ฐ์‚ฐ์ž์˜ ์ธํ„ฐํŽ˜์ด์Šค๋Š” caffe2/proto/caffe2.proto์— ์ •์˜๋˜์–ด์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ, ๊ทธ๊ฒƒ์€ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ž…๋ ฅ์„ ๋ฐ›์•„ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์ถœ๋ ฅ์„ ๋งŒ๋“ค์–ด๋ƒ…๋‹ˆ๋‹ค.

Caffe2 Python์—์„œ "์—ฐ์‚ฐ์ž ๋งŒ๋“ค๊ธฐ"๋ผ๊ณ  ๋งํ•˜๋ฉด ์•„๋ฌด๊ฒƒ๋„ ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์—ฐ์‚ฐ์ž์˜ ํŠน์ง•์„ ์ง€์ •ํ•˜๋Š” ํ”„๋กœํ† ์ฝœ ๋ฒ„ํผ๋ฅผ ์ƒ์„ฑ ํ•  ๋ฟ์ด์ฃ . ๋‚˜์ค‘์— ์‹คํ–‰์„ ์œ„ํ•ด C ++ ๋ฐฑ์—”๋“œ๋กœ ์ „์†ก๋ฉ๋‹ˆ๋‹ค. protobuf์— ์ต์ˆ™ํ•˜์ง€ ์•Š๋‹ค๋ฉด ๊ตฌ์กฐํ™” ๋œ ๋ฐ์ดํ„ฐ๋ฅผ ์œ„ํ•œ json๊ฐ™์€ ์ง๋ ฌํ™” ๋„๊ตฌ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฉด ์ข‹์Šต๋‹ˆ๋‹ค. ํ”„๋กœํ† ์ฝœ ๋ฒ„ํผ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์—ฌ๊ธฐ๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค.

์‹ค์ œ ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ด…์‹œ๋‹ค.

    # ์—ฐ์‚ฐ์ž ์ƒ์„ฑ
    op = core.CreateOperator(
        "Relu", # ์‹คํ–‰์‹œํ‚ค๊ณ ์žํ•˜๋Š” ์—ฐ์‚ฐ์ž์˜ ํƒ€์ž…
        ["X"], # ์ด๋ฆ„์„ ์ด์šฉํ•ด input blob์„ listing
        ["Y"], # ์ด๋ฆ„์„ ์ด์šฉํ•ด output blob์„ listing
    )
    # ๋!

์•ž์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ, ์ƒ์„ฑ๋œ ์—ฐ์‚ฐ์ž๋ผ๋Š” ๊ฒƒ์€ ์‹ค์งˆ์ ์œผ๋กœ protobuf ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. ๋‚ด์šฉ์„ ์‚ดํŽด๋ด…์‹œ๋‹ค.

    print("Type of the created op is: {}".format(type(op)))
    print("Content:\n")
    print(str(op))
    Type of the created op is: <class 'caffe2.proto.caffe2_pb2.OperatorDef'>
    Content:
    
    input: "X"
    output: "Y"
    name: ""
    type: "Relu"

๋์Šต๋‹ˆ๋‹ค, ์—ฐ์‚ฐ์ž๋ฅผ ์‹คํ–‰์‹œ์ผœ๋ด…์‹œ๋‹ค. ๋จผ์ €, input X๋ฅผ workspace๋กœ ๊ฐ€์ ธ์˜ต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋‚˜์„œ, ์—ฐ์‚ฐ์ž๋ฅผ ์‹คํ–‰์‹œํ‚ค๋Š” ๊ฐ€์žฅ ์‰ฌ์šด ๋ฐฉ๋ฒ•์€ workspace.RunOperatorOnce(operator) ๋ช…๋ น์–ด ์ž…๋‹ˆ๋‹ค.

    workspace.FeedBlob("X", np.random.randn(2, 3).astype(np.float32))
    workspace.RunOperatorOnce(op)

์‹คํ–‰ ์ดํ›„์—, ์—ฐ์‚ฐ์ž๊ฐ€ ์ œ๋Œ€๋กœ ์ผ์„ ์ˆ˜ํ–‰ํ•˜๋Š”์ง€ ์‚ดํŽด๋ด…์‹œ๋‹ค. ์—ฌ๊ธฐ์„œ๋Š” ์—ฐ์‚ฐ์ž๊ฐ€ ์‹ ๊ฒฝ๋ง([Relu])์„ ํ™œ์„ฑํ™”ํ•˜๋Š” ์—ญํ• ์„ ํ•˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

    print("Current blobs in the workspace: {}\n".format(workspace.Blobs()))
    print("X:\n{}\n".format(workspace.FetchBlob("X")))
    print("Y:\n{}\n".format(workspace.FetchBlob("Y")))
    print("Expected:\n{}\n".format(np.maximum(workspace.FetchBlob("X"), 0)))
    Current blobs in the workspace: ['X', 'Y']
    
    X:
    [[ 1.03125858  1.0038228   0.0066975 ]
     [ 1.33142471  1.80271244 -0.54222912]]
    
    Y:
    [[ 1.03125858  1.0038228   0.0066975 ]
     [ 1.33142471  1.80271244  0.        ]]
    
    Expected:
    [[ 1.03125858  1.0038228   0.0066975 ]
     [ 1.33142471  1.80271244  0.        ]]

์ด ์˜ˆ์—์„œ Y์™€ ์ถœ๋ ฅ์ด ์ผ์น˜ํ•˜๋Š” ๊ฒƒ์„ ๊ธฐ๋Œ€ ํ•œ ๊ฒƒ์ด๋ผ๋ฉด, ์ด ์—ฐ์‚ฐ์ž๋Š” ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜๊ณ  ์žˆ๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์—ฐ์‚ฐ์ž๋Š” ํ•„์š”ํ•˜๋‹ค๋ฉด ์„ ํƒ์  ์ธ์ˆ˜(arguments) ๋˜ํ•œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์—ฐ์‚ฐ์ž์™€ ์ธ์ˆ˜๋Š” ํ‚ค-๊ฐ’ ์Œ์œผ๋กœ ์ง€์ •๋ฉ๋‹ˆ๋‹ค. ํ…์„œ๋ฅผ ๋งŒ๋“ค์–ด Gaussian ํ™•๋ฅ  ๋ณ€์ˆ˜๋กœ ์ฑ„์šฐ๋Š” ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

    op = core.CreateOperator(
        "GaussianFill",
        [], # GaussianFill์€ ๋‹ค๋ฅธ ์ธ์ž(ํŒŒ๋ผ๋ฏธํ„ฐ)๋ฅผ ํ•„์š”๋กœํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
        ["Z"],
        shape=[100, 100], # int๋“ค์„ ๋ฆฌ์ŠคํŒ…ํ•ด์„œ ์ธ์ˆ˜๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
        mean=1.0,  # floatํ˜•์‹์œผ๋กœ ์†Œ์ˆ˜์  ์•„๋ž˜ ํ•œ์ž๋ฆฌ๋ฅผ ๊ฐ–๋Š” mean
        std=1.0, # floatํ˜•์‹์œผ๋กœ ์†Œ์ˆ˜์  ์•„๋ž˜ ํ•œ์ž๋ฆฌ๋ฅผ ๊ฐ–๋Š” std
    )
    print("Content of op:\n")
    print(str(op))
    Content of op:
    
    output: "Z"
    name: ""
    type: "GaussianFill"
    arg {
      name: "std"
      f: 1.0
    }
    arg {
      name: "shape"
      ints: 100
      ints: 100
    }
    arg {
      name: "mean"
      f: 1.0
    }

๊ทธ๊ฒƒ์„ ์‹คํ–‰ํ•˜๊ณ  ์˜๋„ํ•œ ๋Œ€๋กœ ๊ฐ’์ด ๋‚˜์˜ค๋Š”์ง€ ๋ด…์‹œ๋‹ค.

    workspace.RunOperatorOnce(op)
    temp = workspace.FetchBlob("Z")
    pyplot.hist(temp.flatten(), bins=50)
    pyplot.title("Distribution of Z")
    <matplotlib.text.Text at 0x7f2bd2d51710>

์ข… ๋ชจ์–‘์˜ ๊ณก์„ ์ด ๋ณด์—ฌ์ง€๋ฉด ์ œ๋Œ€๋กœ ์ž‘๋™ ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค!

Nets

net์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ณ„์‚ฐ ๊ทธ๋ž˜ํ”„์ž…๋‹ˆ๋‹ค. Net์€ ์ผ๋ จ์˜ ๋ช…๋ น์œผ๋กœ ์ž‘์„ฑ๋œ ํ”„๋กœ๊ทธ๋žจ์ฒ˜๋Ÿผ, ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์—ฐ์‚ฐ์ž๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค. ํ•œ ๋ฒˆ ์‚ดํŽด๋ด…์‹œ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ net์— ๋Œ€ํ•ด ๋งํ•  ๋•Œ, BlobReference์— ๋Œ€ํ•ด์„œ๋„ ํ•จ๊ป˜ ๋งํ•˜๊ณ  ์žˆ๋Š” ์…ˆ์ž…๋‹ˆ๋‹ค. BlobReference๋Š” ๋ฌธ์ž์—ด ์ฃผ์œ„๋ฅผ ๊ฐ์‹ธ์„œ ์—ฐ์‚ฐ์ž๋ฅผ ์‰ฝ๊ฒŒ ์—ฐ๊ฒฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ์˜ ํŒŒ์ด์ฌ math์™€ ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ฐ™์€ ์—ญํ• ์„ ํ•˜๋Š” network๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค.

    X = np.random.randn(2, 3)
    W = np.random.randn(5, 3)
    b = np.ones(5)
    Y = X * W^T + b

์ฐจ๊ทผ์ฐจ๊ทผ ๊ณผ์ •์„ ๋ณด์—ฌ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค. Caffe2์˜ core.Net์€ NetDef ํ”„๋กœํ† ์ฝœ ๋ฒ„ํผ์˜ ์ฃผ๋ณ€์„ ๊ฐ์‹ธ๋Š” class์ž…๋‹ˆ๋‹ค.

network๋ฅผ ์ƒ์„ฑํ•˜๋ฉด, ๊ทธ ๊ธฐ์ €์˜ ํ”„๋กœํ† ์ฝœ ๋ฒ„ํผ๋Š” ๋„คํŠธ์›Œํฌ ์ด๋ฆ„์„ ์ œ์™ธํ•˜๊ณ  ๊ธฐ๋ณธ์ ์œผ๋กœ ๋น„์–ด์žˆ์Šต๋‹ˆ๋‹ค. net์„ ๋งŒ๋“ค๊ณ  proto ๋‚ด์šฉ์„ ๋ณด์—ฌ์ฃผ๊ฒŒ ๋งŒ๋“ค์–ด ๋ด…์‹œ๋‹ค.

    net = core.Net("my_first_net")
    print("Current network proto:\n\n{}".format(net.Proto()))
    Current network proto:
    
    name: "my_first_net"

X๋ผ๊ณ  ๋ถˆ๋ฆฌ๋Š” blob์„ ๋งŒ๋“ค๊ณ , GaussianFill์„ ์ด์šฉํ•ด์„œ ๋žœ๋ค ๋ฐ์ดํ„ฐ๋กœ ์ฑ„์›๋‹ˆ๋‹ค.

    X = net.GaussianFill([], ["X"], mean=0.0, std=1.0, shape=[2, 3], run_once=0)
    print("New network proto:\n\n{}".format(net.Proto()))
    New network proto:
    
    name: "my_first_net"
    op {
      output: "X"
      name: ""
      type: "GaussianFill"
      arg {
        name: "std"
        f: 1.0
      }
      arg {
        name: "run_once"
        i: 0
      }
      arg {
        name: "shape"
        ints: 2
        ints: 3
      }
      arg {
        name: "mean"
        f: 0.0
      }
    }

์•ž์„  core.CreateOperator ํ˜ธ์ถœ๊ณผ ์•ฝ๊ฐ„์˜ ์ฐจ์ด์ ์„ ๊ด€์ฐฐ ํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ, net์ด ์žˆ๋‹ค๋ฉด, ์—ฐ์‚ฐ์ž๋ฅผ ๋ฐ”๋กœ ์ƒ์„ฑํ•˜๊ณ  ๋™์‹œ์— ํŒŒ์ด์ฌ ํŠธ๋ฆญ์„ ์‚ฌ์šฉํ•˜์—ฌ net์— ์ถ”๊ฐ€์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค : SomeOp๊ฐ€ ์—ฐ์‚ฐ์ž์˜ ๋ฌธ์ž์—ด ํƒ€์ž…์œผ๋กœ ๋“ฑ๋ก๋œ ์ƒํƒœ์—์„œ net.SomeOp์„ ํ˜ธ์ถœํ•˜๋ฉด ์ด๊ฒƒ์€ ๊ณง๋ฐ”๋กœ ๋‹ค์Œ์œผ๋กœ ๋ฒˆ์—ญ์‹œํ‚ต๋‹ˆ๋‹ค.

    op = core.CreateOperator("SomeOp", ...)
    net.Proto().op.append(op)

๋˜ํ•œ, X๊ฐ€ ๋ฌด์—‡์ธ์ง€ ๊ถ๊ธˆํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. X๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ 2๊ฐ€์ง€๋ฅผ ๊ธฐ๋กํ•˜๋Š” BlobReference์ž…๋‹ˆ๋‹ค.

  • ์ด๋ฆ„์ด ๋ฌด์—‡์ธ์ง€. str(X)๋ฅผ ์ด์šฉํ•ด์„œ ์ด๋ฆ„์— ์ ‘๊ทผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ทธ๊ฒƒ์œผ๋กœ๋ถ€ํ„ฐ ์–ด๋–ค net์ด ์ƒ์„ฑ๋˜๋Š”์ง€. ๋‚ด๋ถ€ ๋ณ€์ˆ˜ _from_net์— ์˜ํ•ด์„œ ๊ธฐ๋ก๋˜๋Š”๋ฐ ๋ณ„๋กœ ํ•„์š”ํ•˜์ง€๋Š” ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•ด๋ด…์‹œ๋‹ค. ๋˜ ํ•œ ๊ฐ€์ง€ ๊ธฐ์–ตํ•ด์•ผ ํ•  ๊ฒƒ์€ ์šฐ๋ฆฌ๋Š” ์•„์ง ์•„๋ฌด๊ฒƒ๋„ ์‹คํ–‰ํ•˜์ง€ ์•Š์•˜๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ X๋Š” symbol์ผ ๋ฟ ์•„๋ฌด๊ฒƒ๋„ ๊ฐ–๊ณ  ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ ๋‹น์žฅ ์ˆซ์ž ๊ฐ’์„ ์–ป๋Š” ๊ฒƒ์„ ๊ธฐ๋Œ€ํ•˜์ง€๋Š” ๋งˆ์„ธ์š” :)

    print("Type of X is: {}".format(type(X)))
    print("The blob name is: {}".format(str(X)))
    Type of X is: <class 'caffe2.python.core.BlobReference'>
    The blob name is: X

๊ณ„์†ํ•ด์„œ W์™€ b๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

    W = net.GaussianFill([], ["W"], mean=0.0, std=1.0, shape=[5, 3], run_once=0)
    b = net.ConstantFill([], ["b"], shape=[5,], value=1.0, run_once=0)

์ด์ œ, ๊ฐ„๋‹จํ•œ ์ฝ”๋“œ๊ฐ€ ํ•˜๋‚˜ ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค. BlobReference ๊ฐ์ฒด๋Š” ์ƒ์„ฑ๋œ net์ด ๋ฌด์—‡์ธ์ง€ ์•Œ๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, net์—์„œ ์—ฐ์‚ฐ์ž๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ BlobReference์œผ๋กœ๋ถ€ํ„ฐ ์—ฐ์‚ฐ์ž๋ฅผ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์‹์œผ๋กœ FC์—ฐ์‚ฐ์ž๋ฅผ ๋งŒ๋“ค์–ด๋ด…์‹œ๋‹ค.

    Y = X.FC([W, b], ["Y"])

X.FC(...)๋Š” X๋ฅผ ํ•ด๋‹น ์—ฐ์‚ฐ์ž์˜ ์ฒซ ๋ฒˆ์งธ input์œผ๋กœ ์‚ฝ์ž… ํ•ด net.FC์˜ ๊ฐ„๋‹จํ•œ ๋Œ€๋ฆฌ์ž ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์œ„์—์„œ ํ•œ ์ž‘์—…์€ ๋‹ค์Œ์˜ ๊ฒƒ๊ณผ ๋™์ผํ•ฉ๋‹ˆ๋‹ค.

    Y = net.FC([X, W, b], ["Y"])

ํ˜„์žฌ network๋ฅผ ์‚ดํŽด๋ด…์‹œ๋‹ค.

    print("Current network proto:\n\n{}".format(net.Proto()))
    Current network proto:
    
    name: "my_first_net"
    op {
      output: "X"
      name: ""
      type: "GaussianFill"
      arg {
        name: "std"
        f: 1.0
      }
      arg {
        name: "run_once"
        i: 0
      }
      arg {
        name: "shape"
        ints: 2
        ints: 3
      }
      arg {
        name: "mean"
        f: 0.0
      }
    }
    op {
      output: "W"
      name: ""
      type: "GaussianFill"
      arg {
        name: "std"
        f: 1.0
      }
      arg {
        name: "run_once"
        i: 0
      }
      arg {
        name: "shape"
        ints: 5
        ints: 3
      }
      arg {
        name: "mean"
        f: 0.0
      }
    }
    op {
      output: "b"
      name: ""
      type: "ConstantFill"
      arg {
        name: "run_once"
        i: 0
      }
      arg {
        name: "shape"
        ints: 5
      }
      arg {
        name: "value"
        f: 1.0
      }
    }
    op {
      input: "X"
      input: "W"
      input: "b"
      output: "Y"
      name: ""
      type: "FC"
    }

๋„ˆ๋ฌด ์žฅํ™ฉํ•˜์ฃ ? ๊ทธ๋ž˜ํ”„๋กœ ์‹œ๊ฐํ™” ํ•ด๋ด…์‹œ๋‹ค. Caffe2๋Š” ์•„์ฃผ ๊ธฐ๋ณธ์ ์ธ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ์‹œ๊ฐํ™” ๋„๊ตฌ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ipython์œผ๋กœ ๊ทธ๊ฒƒ์„ ๋ณด์—ฌ ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

    from caffe2.python import net_drawer
    from IPython import display
    graph = net_drawer.GetPydotGraph(net, rankdir="LR")
    display.Image(graph.create_png(), width=800)

์šฐ๋ฆฌ๋Š” Net์„ ์ •์˜ํ–ˆ์ง€๋งŒ ์•„์ง ์•„๋ฌด๊ฒƒ๋„ ์‹คํ–‰๋˜์ง€๋Š” ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์œ„์˜ net์€ ๋„คํŠธ์›Œํฌ์˜ ์ •์˜๋ฅผ ๊ฐ–๊ณ  ์žˆ๋Š” protobuf๋ผ๋Š” ๊ฒƒ์„ ๊ธฐ์–ตํ•˜์„ธ์š”. ์‹ค์ œ๋กœ ๋„คํŠธ์›Œํฌ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์›ํ•  ๋•Œ, ๋‹ค์Œ์˜ ์ผ๋“ค์ด ์ผ์–ด๋‚ฉ๋‹ˆ๋‹ค.

  • protobuf์—์„œ C++ net ๊ฐ์ฒด๋ฅผ ์ธ์Šคํ„ด์Šคํ™”ํ•ฉ๋‹ˆ๋‹ค.
  • ์ธ์Šคํ„ด์Šคํ™” ๋œ net์˜ Run () ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๊ฐ€ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ•˜๊ธฐ ์ „์— ResetWorkspace() ๋ช…๋ น์–ด๋ฅผ ์ด์šฉํ•ด ๋ชจ๋“  workspace์˜ ์•ž์„  ๋ณ€์ˆ˜๋“ค์„ clearํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

ํŒŒ์ด์ฌ์„ ์ด์šฉํ•ด์„œ net์„ ์‹คํ–‰์‹œํ‚ค๋Š” ๋ฐฉ๋ฒ•์€ ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์•„๋ž˜ ์˜ˆ์ œ ์ค‘์— ์ฒซ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์„ ์ˆ˜ํ–‰ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

  1. ์ธ์Šคํ„ด์Šคํ™”์‹œ์ผœ ์‹คํ–‰์‹œํ‚จ ํ›„์— ๋ฐ”๋กœ ํŒŒ๊ดดํ•˜๋Š” workspace.RunNetOnce()์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  2. ์กฐ๊ธˆ ๋” ๋ณต์žกํ•˜๊ณ  2๊ฐ€์ง€ ๋‹จ๊ณ„๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค:

    (a) workspace๊ฐ€ ์†Œ์œ ํ•œ C++ net ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด workspace.CreateNet()๋ฅผ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค.

    (b) network ์ด๋ฆ„์„ ์ „๋‹ฌํ•ด์„œ workspace.RunNet()์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    workspace.ResetWorkspace()
    print("Current blobs in the workspace: {}".format(workspace.Blobs()))
    workspace.RunNetOnce(net)
    print("Blobs in the workspace after execution: {}".format(workspace.Blobs()))
    # blobs์˜ ๋‚ด์šฉ์„ dumpํ•ฉ์‹œ๋‹ค.
    for name in workspace.Blobs():
        print("{}:\n{}".format(name, workspace.FetchBlob(name)))
    Current blobs in the workspace: []
    Blobs in the workspace after execution: ['W', 'X', 'Y', 'b']
    W:
    [[-0.96537346  0.42591459  0.66788739]
     [-0.47695673  2.25724339 -0.10370601]
     [-0.20327474 -3.07469416  0.47715324]
     [-1.62159526  0.73711687 -1.42365313]
     [ 0.60718107 -0.50448036 -1.17132831]]
    X:
    [[-0.99601173 -0.61438894  0.10042733]
     [ 0.23359862  0.15135486  0.77555442]]
    Y:
    [[ 1.76692021  0.07781416  3.13944149  2.01927781  0.58755434]
     [ 1.35693741  1.14979863  0.85720366 -0.37135673  0.15705228]]
    b:
    [ 1.  1.  1.  1.  1.]

์ž, ์ด๋ฒˆ์—๋Š” ๋‘ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์„ ์ด์šฉํ•ด net์„ ์ƒ์„ฑํ•˜๊ณ  ์‹คํ–‰์‹œ์ผœ๋ด…์‹œ๋‹ค. ResetWorkspace()๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณ€์ˆ˜๋ฅผ ์ง€์šฐ๊ณ , ์ „์— ์ƒ์„ฑ ํ•ด ๋‘” workspace์˜ net ๊ฐ์ฒด์ธ CreateNet(net_object)๋ฅผ ์ด์šฉํ•ด net์„ ๋งŒ๋“ญ๋‹ˆ๋‹ค. ์ดํ›„ RunNet(net_name)์— ์ด๋ฆ„์„ ์ „๋‹ฌํ•˜์—ฌ net์„ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

    workspace.ResetWorkspace()
    print("Current blobs in the workspace: {}".format(workspace.Blobs()))
    workspace.CreateNet(net)
    workspace.RunNet(net.Proto().name)
    print("Blobs in the workspace after execution: {}".format(workspace.Blobs()))
    for name in workspace.Blobs():
        print("{}:\n{}".format(name, workspace.FetchBlob(name)))
    Current blobs in the workspace: []
    Blobs in the workspace after execution: ['W', 'X', 'Y', 'b']
    W:
    [[-0.29295802  0.02897477 -1.25667715]
     [-1.82299471  0.92877913  0.33613944]
     [-0.64382178 -0.68545657 -0.44015241]
     [ 1.10232282  1.38060772 -2.29121733]
     [-0.55766547  1.97437167  0.39324901]]
    X:
    [[-0.47522315 -0.40166432  0.7179445 ]
     [-0.8363331  -0.82451206  1.54286408]]
    Y:
    [[ 0.22535783  1.73460138  1.2652775  -1.72335696  0.7543118 ]
     [-0.71776152  2.27745867  1.42452145 -4.59527397  0.4452306 ]]
    b:
    [ 1.  1.  1.  1.  1.]

RunNetOnce์™€ RunNet์€ ๋ช‡ ๊ฐ€์ง€ ์ฐจ์ด์ ์ด ์žˆ๋Š”๋ฐ, ์•„๋งˆ ์ฃผ์š” ์ฐจ์ด์ ์€ ์—ฐ์‚ฐ์†๋„์ผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. RunNetOnce๋Š” protobuf๋ฅผ ์ง๋ ฌํ™”ํ•˜์—ฌ Python๊ณผ C ์‚ฌ์ด๋ฅผ ํ†ต๊ณผํ•˜๊ณ  ๋„คํŠธ์›Œํฌ๋ฅผ ์ธ์Šคํ„ด์Šคํ™”ํ•˜๋Š” ๊ฒƒ๊นŒ์ง€ ํฌํ•จํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹คํ–‰ํ•˜๋Š” ๋ฐ ์‹œ๊ฐ„์ด ์˜ค๋ž˜ ๊ฑธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ๋ฅผ ์ „๋ฐ˜์ ์œผ๋กœ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

    # `%timeit`์˜ ๋งˆ๋ฒ•์ด C++์—์„œ ์ œ๋Œ€๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๊ฒƒ ๊ฐ™์•„์„œ loop๋ฅผ ์ด์šฉํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. 
    start = time.time()
    for i in range(1000):
        workspace.RunNetOnce(net)
    end = time.time()
    print('Run time per RunNetOnce: {}'.format((end - start) / 1000))
    
    start = time.time()
    workspace.CreateNet(net)
    for i in range(1000):
    workspace.RunNet(net.Proto().name)
    end = time.time()
    print('Run time per RunNet: {}'.format((end - start) / 1000))
    Run time per RunNetOnce: 0.000364284992218
    Run time per RunNet: 4.42600250244e-06

ํŒŒ์ด์ฌ์—์„œ Caffe2๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ์œ„์˜ ๋ช‡ ๊ฐ€์ง€ ์ฃผ์š” ๊ตฌ์„ฑ ์š”์†Œ๋ฅผ ํ™œ์šฉํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋” ๋งŽ์€ ๊ฒƒ์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ๋Š๊ปด์ง€๋ฉด, ํŠœํ† ๋ฆฌ์–ผ์— ์ถ”๊ฐ€ ํ•  ๊ณ„ํš์ž…๋‹ˆ๋‹ค. ์ด์ œ๋ถ€ํ„ฐ, ํŠœํ† ๋ฆฌ์–ผ์˜ ๋‚˜๋จธ์ง€ ๋ถ€๋ถ„์„ ํ™•์ธ ํ•ด๋ณด์„ธ์š”!

Clone this wiki locally