【Seaborn繪圖】深度強化學習實驗中的paper繪圖方法

來源:知乎(zhuanlan.zhihu.com/p/75477750)

編輯: DeepRL

強化學習實驗中的繪圖技巧-使用seaborn繪製paper中的圖片,使用seaborn繪製折線圖時參數數據可以傳遞ndarray或者pandas,不同的源數據對應的其他參數也略有不同.

1. ndarray

先看一個小例子

def getdata():    
    basecond = [[18, 20, 19, 18, 13, 4, 1],                
                [20, 17, 12, 9, 3, 0, 0],               
                [20, 20, 20, 12, 5, 3, 0]]


    cond1 = [[18, 19, 18, 19, 20, 15, 14],             
             [19, 20, 18, 16, 20, 15, 9],             
             [19, 20, 20, 20, 17, 10, 0],             
             [20, 20, 20, 20, 7, 9, 1]]


    cond2 = [[20, 20, 20, 20, 19, 17, 4],            
             [20, 20, 20, 20, 20, 19, 7],            
             [19, 20, 20, 19, 19, 15, 2]]


    cond3 = [[20, 20, 20, 20, 19, 17, 12],           
             [18, 20, 19, 18, 13, 4, 1],            
             [20, 19, 18, 17, 13, 2, 0],            
             [19, 18, 20, 20, 15, 6, 0]]


    return basecond, cond1, cond2, cond3

數據維度都爲(3,7)或(4, 7) 

第一個維度表示每個時間點採樣不同數目的數據(可認爲是每個x對應多個不同y值) 第二個維度表示不同的時間點(可認爲是x軸對應的x值)

data = getdata()
fig = plt.figure()
xdata = np.array([0, 1, 2, 3, 4, 5, 6])/5
linestyle = ['-', '--', ':', '-.']
color = ['r', 'g', 'b', 'k']
label = ['algo1', 'algo2', 'algo3', 'algo4']


for i in range(4):    
    sns.tsplot(time=xdata, data=data[i], color=color[i], linestyle=linestyle[i], condition=label[i])

sns.tsplot 用來畫時間序列圖

time參數表示對應的時間軸(ndarray),即x軸,data即要求繪製的數據,上述例子爲(3, 7)或(4, 7),color爲每條線的顏色,linestyle爲每條線的樣式,condition爲每條線的標記.

plt.ylabel("Success Rate", fontsize=25)
plt.xlabel("Iteration Number", fontsize=25)
plt.title("Awesome Robot Performance", fontsize=30)
plt.show()

1.2 繪圖建議

  • 你的程序代碼需要使用一個額外的文件記錄結果,例如csv或pkl文件,而不是直接產生最終的繪圖結果.這種方式下,你能運行程序代碼一次,然後以不同的方式去繪製結果,記錄超出您認爲嚴格必要的內容可能是一個好主意,因爲您永遠不知道哪些信息對於瞭解發生的事情最有用.注意文件的大小,但通常最好記錄以下內容:每次迭代的平均reward或loss,一些採樣的軌跡,有用的輔助指標(如貝爾曼誤差和梯度)

  • 你需要有一個單獨的腳本去加載一個或多個記錄文件來繪製圖像,如果你使用不同的超參數或隨機種子運行算法多次,一起加載所有的數據(也許來自不同的文件)並畫在一起是個好主意,使用自動生成的圖例和顏色模式使分辨不同的方法變得容易.

  • 深度強化學習方法,往往在不同的運行中有巨大的變化,因此使用不同的隨機種子運行多次是一個好主意,在繪製多次運行的結果時,在一張圖上繪製不同運行次的結果,通過使用不同粗細和顏色的線來分辨.在繪製不同的方法時,你將發現將他們總結爲均值和方差圖是容易的,然而分佈並不總是遵循正態曲線,所以至少在初始時有明顯的感覺對比不同隨機種子的性能.

1.3 實驗繪圖流程

下面以模仿學習的基礎實驗爲例

means = []
stds = []
#使用不同的隨機種子表示運行多次實驗
for seed in range(SEED_NUM):    
    tf.set_random_seed(seed*10)  
    np.random.seed(seed*10)  
    mean = []    
    std = []


    #構建神經網絡模型
    model = tf.keras.Sequential()    
    model.add(layers.Dense(64, activation="relu"))    
    model.add(layers.Dense(64, activation="relu"))    
    model.add(layers.Dense(act_dim, activation="tanh"))     
    model.compile(optimizer=tf.train.AdamOptimizer(0.0001), loss="mse", metrics=['mae'])      
    #迭代次數
    for iter in range(ITERATION):        
        print("iter:", iter)        
        #訓練模型
        model.fit(train, label, batch_size=BATCH_SIZE, epochs=EPOCHS)


        #測試,通過與環境交互n次而成,即n趟軌跡
        roll_reward = []      
        for roll in range(NUM_ROLLOUTS):        
            s = env.reset()          
            done = False           
            reward = 0           
            step = 0   
            #以下循環表示一趟軌跡
            while not done:              
                a = model.predict(s[np.newaxis, :])        
                s, r, done, _ = env.step(a)             
                reward += r               
                step += 1 
                if step >= max_steps: 
                    break
            #記錄每一趟的總回報值
            roll_reward.append(reward)      
          #n趟回報的平均值和方差作爲這次迭代的結果記錄
          mean.append(np.mean(roll_reward))     
          std.append(np.std(roll_reward))  
    #記錄每一次實驗,矩陣的一行表示一次實驗每次迭代結果
    means.append(mean)    
    stds.append(std)

接着需要保存數據爲pkl文件

d = {"mean": means, "std": stds}
with open(os.path.join("test_data", "behavior_cloning_" + ENV_NAME+".pkl"), "wb") as f:
    pickle.dump(d, f, pickle.HIGHEST_PROTOCOL)

繪圖的程序代碼比較簡單

file = "behavior_cloning_" + ENV_NAME+".pkl"
    with open(os.path.join("test_data", file), "rb") as f:
        data = pickle.load(f)

    x1 = data["mean"]

    file = "dagger_" + ENV_NAME+".pkl"
    with open(os.path.join("test_data", file), "rb") as f:
        data = pickle.load(f)

    x2 = data["mean"]

    time = range(10)

    sns.set(style="darkgrid", font_scale=1.5)
    sns.tsplot(time=time, data=x1, color="r", condition="behavior_cloning")
    sns.tsplot(time=time, data=x2, color="b", condition="dagger")

    plt.ylabel("Reward")
    plt.xlabel("Iteration Number")
    plt.title("Imitation Learning")

    plt.show()

有時我們需要對曲線進行平滑

def smooth(data, sm=1):
    if sm > 1:
        smooth_data = []
        for d in data:
            y = np.ones(sm)*1.0/sm
            d = np.convolve(y, d, "same")

            smooth_data.append(d)

    return smooth_data

sm表示滑動窗口大小,爲2*k+1,

smoothed_y[t] = average(y[t-k], y[t-k+1], ..., y[t+k-1], y[t+k])

2.pandas

sns.tsplot可以使用pandas源數據作爲數據輸入,當使用pandas作爲數據時,time,value,condition,unit選項將爲pandas數據的列名.

其中time選項給出使用該列Series作爲x軸數據,value選項表示使用該Series作爲y軸數據,用unit來分辨這些數據是哪一次採樣(每個x對應多個y),用condition選項表示這些數據來自哪一條曲線.

在openai 的spinning up中,將每次迭代的數據保存到了txt文件中,類似如下:

可以使用pd.read_table讀取這個以"\t"分割的文件形成pandas

algo = ["ddpg_" + ENV, "td3_" + ENV, "ppo_" + ENV, "trpo_" + ENV, "vpg_" + ENV, "sac_" + ENV]
    data = []
    for i in range(len(algo)):
        for seed in range(SEED_NUM):
            file = os.path.join(os.path.join(algo[i], algo[i] + "_s" + str(seed*10)), "progress.txt")

            pd_data = pd.read_table(file)
            pd_data.insert(len(pd_data.columns), "Unit", seed)
            pd_data.insert(len(pd_data.columns), "Condition", algo[i])

            data.append(pd_data)

    data = pd.concat(data, ignore_index=True)

    sns.set(style="darkgrid", font_scale=1.5)
    sns.tsplot(data=data, time="TotalEnvInteracts", value="AverageEpRet", condition="Condition", unit="Unit")

    #數據大時使用科學計數法
    xscale = np.max(data["TotalEnvInteracts"]) > 5e3
    if xscale:
        plt.ticklabel_format(style='sci', axis='x', scilimits=(0, 0))

    plt.legend(loc='best').set_draggable(True)
    plt.tight_layout(pad=0.5)
    plt.show()

程序參考了spinning up 的代碼邏輯github.com/openai/spinn

繪製效果如下:

完整代碼:https://github.com/feidieufo/homework/tree/master/hw1

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章