Sunday, 1 January 2023

RLlib: Collecting metrics for different variation of the same experiment

I have a multi-agent reinforcement learning experiment that I'm running with RLlib. I would like to do a certain measurement, and I'm not sure which tool to use and how.

I wrote a multi-agent environment implementing a certain game for two agents. I train two PPO policies on that environment for 200 training iterations, while collecting metrics about the agents' performances in each iteration. As the training iterations advance, the mean reward rises until it reaches a plateau. I measure other interesting metrics besides the reward, one of them being "Metric X".

Now, when writing this environment, one of the decisions I make is what kind of data I expose to the agent in their observations, and how that data is expressed. I would like to compare the results I get for Metric X for different ways that I might represent the observation.

I thought up of 4 different ways for setting up the observation. Let's call these 4 "arrangements". Right now I switch between the 4 arrangements by commenting out different sections of the code that calculates the observation. This is clunky, of course.

I would like to do many runs of 200 training iterations on this environment, under each of the 4 arrangements. For each arrangement, I'd like to see what values it produces for Metric X on the 200th training iteration. I'm not just looking for which arrangement gives me the highest Metric X, and not even the mean Metric X for the arrangement. I want to get a list of all the Metric X results for each of these arrangements, so I may find the mean, standard deviation and plot histograms of them.

What tool or framework or method should I use to collect this information? Is Ray Tune fit for this job? I need some way to programmatically tell Ray to sometimes include some values in the observation and sometimes not to. I need to run Ray many times and have these metrics automatically collected and aggregated by arrangement. I could write logic that does it, but I want to know how this is usually dne.



from RLlib: Collecting metrics for different variation of the same experiment

How to enable analytics for dynamic pages (Vue.js)

I'm building a website where users can create new pages with dynamic URLs. I would like to add traffic analytics for each of these pages individually and allow users to view a dashboard of the data collected for the page they have created (just view, they shouldn't be able to edit the dashboard they are given).

If possible, this should work in Vue.js, but anything that works with vanilla JS should be fine too.

Is this possible with a tool like Google Analytics or a similar suite? Is this expensive?



from How to enable analytics for dynamic pages (Vue.js)

Section snapping whilst scrolling

I'm trying to implement page/section snapping as you scroll page to page, for some reason the class="outer" seems to be interfering with the first page title, button and the nav bar? The nav bar was functional before I added the classes "outer" and "page" the title and button also remained on the first page and did not pass through to the other pages. anyone know what this problem is? have a feeling it's something simple

html, body {
    margin: 0;
    height:100%;
    width:100%;
    padding:0;
}


@media (min-height: 30em) {
  .section__content > * {
    opacity: 0;
    transform: translate3d(0, 4rem, 0);
    transition: opacity 800ms var(--delay),
      transform 800ms cubic-bezier(0.13, 0.07, 0.26, 0.99) var(--delay);
  }
}

.is-visible .section__content > * {
  opacity: 1;
  transform: translate3d(0, 1rem, 0);
}
.is-visible .section__img {
  opacity: 0.75;
}

section {
    display: block;
    background: #CFF;
    height:100%;
    width:100%;
    box-sizing:border-box;
    scroll-snap-align: center;
    
}
.background1 {

background: url("IMG-7323.GIF") no-repeat center center ;
background-size: cover; 
max-width: 100%;
max-height: 100%;
height: 100vh;
width: 100vw;
}

.outer {
  overflow-y:auto;
  scroll-snap-type: y mandatory;
  height: 100vh;
}

.page {
  scroll-snap-align: start; height: 100vh;
}

#one {
    background: #111816;
    color: #fff;
    
}



/* Title section 1 */
.glow-on-hover {
    width: 220px;
    height: 35px;
    border: none;
    outline: none;
    color: rgb(0, 0, 0);
    font-weight: bold;
    font-size: 20px;
    background: #111;
    cursor: pointer;
    position: relative;
    z-index: 0;
    border-radius: 10px;
  }

  .glow-on-hover:before {
    content: "";
    background: linear-gradient(
      45deg,
      #ffffff,
      #969594,
      #ffffff,
      #969594,
      #ffffff,
      #969594,
      #ffffff,
      #969594,
      #ffffff
    );
    position: absolute;
    top: -2px;
    left: -2px;
    background-size: 400%;
    z-index: -1;
    filter: blur(5px);
    width: calc(100% + 4px);
    height: calc(100% + 4px);
    animation: glowing 20s linear infinite;
    opacity: 0;
    transition: opacity 0.3s ease-in-out;
    border-radius: 10px;
  }

  .glow-on-hover:active {
    color: #000;
  }

  .glow-on-hover:active:after {
    background: transparent;
  }

  .glow-on-hover:hover:before {
    opacity: 1;
  }

  .glow-on-hover:after {
    z-index: -1;
    content: "";
    position: absolute;
    width: 100%;
    height: 100%;
    background: rgb(150, 167, 204);
    left: 0;
    top: 0;
    border-radius: 10px;
  }

  @keyframes glowing {
    0% {
      background-position: 0 0;
    }
    50% {
      background-position: 400% 0;
    }
    100% {
      background-position: 0 0;
    }
  }

  h1 {
    position: relative;
    font-family: TaylorGothic;
    font-size: calc(20px + 5vw);
    font-weight: 700;
    color: #fff;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    text-shadow: 0 0 0.15em #1da9cc;
    user-select: none;
    white-space: nowrap;
    filter: blur(0.007em);
    animation: shake 2.5s  infinite linear forwards;
}

@font-face {
  font-family: TaylorGothic;
  src: url(TaylorGothic.woff2);
}

@keyframes shake {
    5%, 15%, 25%, 35%, 55%, 65%, 75%, 95% {
        filter: blur(0.018em);
        transform: translateY(0.018em) rotate(0deg);
    }

    10%, 30%, 40%, 50%, 70%, 80%, 90% {
        filter: blur(0.01em);
        transform: translateY(-0.018em) rotate(0deg);
    }

    20%, 60% {
        filter: blur(0.03em);
        transform: translate(-0.018em, 0.018em) rotate(0deg);
    }

    45%, 85% {
        filter: blur(0.03em);
        transform: translate(0.018em, -0.018em) rotate(0deg);
    }

    100% {
        filter: blur(0.007em);
        transform: translate(0) rotate(-0.5deg);
    }
}

@keyframes crack1 {
    0%, 95% {
        transform: translate(-50%, -50%);
    }

    100% {
        transform: translate(-51%, -48%);
    }
}

@keyframes crack2 {
    0%, 95% {
        transform: translate(-50%, -50%);
    }

    100% {
        transform: translate(-49%, -53%);
    }
}

  /* for the heading and the button alignment*/

  
  .btn-centering {
    flex-grow: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }


/*  section one end */



#two {
    background: #123037;
    color: #fff;
    font-size: 30px;
}
#three {
    background: #74BE98;
    font-size: 30px;
}
#four {
    background: #BED28D;
    font-size: 30px;
}
#five {
    background: #95211D;
    color: #fff;
    font-size: 30px;
}
nav {
    position: fixed;
}
nav a {
    display: block;
    font-size: 12px;
    color: #FFF;
    text-align: center;
    background: #000;
    padding: 10px;
    margin: 3px;
}
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="styles.css">    <title></title>

        <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
    
    
    
    
    
    <script>
        $(function() {
            $('a[href*=#]:not([href=#])').click(function() {
                if (location.pathname.replace(/^\//, '') == this.pathname.replace(/^\//, '') && location.hostname == this.hostname) {
                    var target = $(this.hash);
                    target = target.length ? target : $('[name=' + this.hash.slice(1) + ']');
                    if (target.length) {
                        $('html,body').animate({
                            scrollTop: target.offset().top
                        }, 1000);
                        return false;
                    }
                }
            });
        });
    </script>


</head>
<body>
 <nav> 
 <a href="#one">one</a>
 <a href="#two">two</a>
 <a href="#three">three</a>
 <a href="#four">four</a>
 <a href="#five">five</a>
</nav>
  
    

<div class="outer"> 
    <section id="one" > 

        <div class="page">

        <div class="background1"></div>

<!-- Title -->
           
        <div class="btn-centering">
            <h1 data-text="black mirror"><span>Ghosted</span></h1>
            <button class="glow-on-hover" onclick="location.href='products.html'" type="button">
            View Products</button></div>
            
<!-- Socail media buttons --> 




    </section>
    <section id="two">Page 2
      <div class="page"></div>

    </section>
    <section id="three">Page 3
      <div class="page"></div>
    </section>
    <section id="four">Page 4
      <div class="page"></div>
    </section>
    <section id="five">Page 5
      <div class="page"></div>
    </section>
 </div>
 
      
</body>
</html>


from Section snapping whilst scrolling