<jupyter_start><jupyter_text>이번에는 Ray를 활용하면서 visualization하는 방법에 대해 알아보겠습니다.     1. Actor는 현재 노트북이 열린 pid와는 다른 pid에서 실행이 되므로, Actor안에서 노트북으로 바로 출력하기 어렵다.    2. 따라서 Actor는 자신의 score 데이터를 다른 곳에 넘겨준다.    3. 2번에서 넘겨준 데이터를 learner에서 plot한다(learner는 쥬피터 노트북 pid에서 실행이 되므로).     4. 마지막으로, 쥬피터에서 가능한 방법이긴 하지만 wandb를 사용하는 것보다 느리다.<jupyter_code>import sys
IN_COLAB = "google.colab" in sys.modules

if IN_COLAB:
    !pip install ray
import ray
import numpy as np
from collections import defaultdict
import matplotlib.pyplot as plt
from IPython.display import clear_output
ray.init() 
@ray.remote 
class Plot_inline:  
    def __init__(self): 
        # actor의 개수가 여러개 있을 때 동적으로 dictionary의 key를 생성할 수 있도록 defalutdict를 활용
        self.score_dict = defaultdict(list) 
    
    def store_actor_data(self, actor_idx, score): 
        ''' Actor의 data를 저장합니다 '''
        self.score_dict[actor_idx].append(score) 
        
    def store_learner_data(self, score): 
        ''' Learner의 data를 저장합니다 '''
        self.score_dict['learner'].append(score) 

    def get_status(self): 
        ''' 쌓인 data를 return합니다 '''
        return self.score_dict 
@ray.remote
class Actor:
    def __init__(self, num_actors, plot_util):
        self.plot_util = plot_util
        self.num_actors = num_actors
        
    def gen_data(self):
        ''' 임의의 데이터를 plot_util 객체에 넘겨줍니다. '''
        for _ in range(100):
            score = np.random.randn() 
            actor_idx = np.random.randint(1, self.num_actors+1)
            self.plot_util.store_actor_data.remote(actor_idx, score) 
        return "Done."  # done은 안보내줘도 됩니다. 그냥 실행 완료 signal을 보내주도록 쓴 것 입니다.
class Learner:
    def __init__(self, plot_util): 
        self.plot_util = plot_util 

    def train(self):
        ''' 임의의 데이터를 plot_util에 넘깁니다 '''
        for _ in range(30): 
            score = np.random.randn()  
            self.plot_util.store_learner_data.remote(score) 
        self.plot_inline() 
        print("Done.")

    def plot_inline(self):  
        ''' 쥬피터 노트북에 plot해주는 함수. 크기와 나누는 것은 임의로 나누었습니다. '''
        score_dict = ray.get(self.plot_util.get_status.remote()) 
        clear_output(True)
        plt.figure(facecolor='w', figsize=(25,25)) 
        for idx in range(1, len(score_dict)):
            i,j = (idx-1)//5, (idx-1)%5 
            plt.subplot2grid((5,5), (i,j)) 
            plt.plot(score_dict[idx]) 
            plt.title(f"Score of Actor {idx}")
        if (j+1)%5==0:
            plt.subplot2grid((5,5), (i+1,0)) 
        else:
            plt.subplot2grid((5,5), (i,j+1)) 
        plt.plot(score_dict['learner']) 
        plt.title("Score of Learner") 
        plt.show() 
num_actors = 10

plot_util = Plot_inline.remote() 
actor = Actor.remote(num_actors, plot_util) 
print(ray.get(actor.gen_data.remote())) 
learner = Learner(plot_util)  
learner.train()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11247372109320253, 'fraction_numerical': 0.013314646110721794, 'mean_word_length': 2.503067484662577, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '608886', 'license': 'MIT', 'n_tokens_mistral': 1271, 'n_tokens_neox': 1341, 'n_words': 239, 'path': 'Ray_tutorial/4. Visualization_with_Ray.ipynb', 'repo_name': 'kyunghoon-jung/MacaronRL', 'size': '2854'}