<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.8.5">Jekyll</generator><link href="https://blog.konpat.me/feed.xml" rel="self" type="application/atom+xml" /><link href="https://blog.konpat.me/" rel="alternate" type="text/html" /><updated>2019-05-03T10:08:10+07:00</updated><id>https://blog.konpat.me/feed.xml</id><title type="html">Konpat’s Record of Struggles</title><subtitle>A graduate student in Machine Learning seeking revolutionary intelligent machines.</subtitle><author><name>Konpat Preechakul</name></author><entry><title type="html">Pickling Pytorch views is pickling the whole underlying memory</title><link href="https://blog.konpat.me/dev/2019/03/11/pickling-pytorch-view-pickle-its-underlying-memory.html" rel="alternate" type="text/html" title="Pickling Pytorch views is pickling the whole underlying memory" /><published>2019-03-11T00:00:00+07:00</published><updated>2019-03-11T00:00:00+07:00</updated><id>https://blog.konpat.me/dev/2019/03/11/pickling-pytorch-view-pickle-its-underlying-memory</id><content type="html" xml:base="https://blog.konpat.me/dev/2019/03/11/pickling-pytorch-view-pickle-its-underlying-memory.html">&lt;p&gt;It is important at the time of pickling to know what we are really saving to disks. Saving Pytorch tensors is most likely saving its underlying storage. This could be confused with &lt;em&gt;views&lt;/em&gt; because many views could share the same underlying storage. The view could be very narrow, but its underlying storage could still be very large. Saving this view to disks would result in a large file as well.&lt;/p&gt;

&lt;p&gt;For example:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;kn&quot;&gt;import&lt;/span&gt; &lt;span class=&quot;nn&quot;&gt;torch&lt;/span&gt;

&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randn&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;torch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;save&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;],&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;'saved.pt'&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;highlighter-rouge&quot;&gt;saved.pt&lt;/code&gt; would have the size of 100 floats instead of one. To really save just the view portion of the storage, we need to create a distinct storage containing only the viewed portion of the old one. This could be done using &lt;code class=&quot;highlighter-rouge&quot;&gt;x[0].clone()&lt;/code&gt;.&lt;/p&gt;</content><author><name>Konpat Preechakul</name></author><category term="pytorch" /><summary type="html">It is important at the time of pickling to know what we are really saving to disks. Saving Pytorch tensors is most likely saving its underlying storage. This could be confused with views because many views could share the same underlying storage. The view could be very narrow, but its underlying storage could still be very large. Saving this view to disks would result in a large file as well.</summary></entry><entry><title type="html">Setting up LXC with Intel GPU (Proxmox), keyboard, mouse and audio</title><link href="https://blog.konpat.me/dev/2019/03/11/setting-up-lxc-for-intel-gpu-proxmox.html" rel="alternate" type="text/html" title="Setting up LXC with Intel GPU (Proxmox), keyboard, mouse and audio" /><published>2019-03-11T00:00:00+07:00</published><updated>2019-03-11T00:00:00+07:00</updated><id>https://blog.konpat.me/dev/2019/03/11/setting-up-lxc-for-intel-gpu-proxmox</id><content type="html" xml:base="https://blog.konpat.me/dev/2019/03/11/setting-up-lxc-for-intel-gpu-proxmox.html">&lt;p&gt;The goal is to create a linux container with Proxmox that utilizes integrated Intel GPU. Additional requirements are mouse and keyboard must work also with audio.&lt;/p&gt;

&lt;p&gt;There are some specificities in this guide. I use &lt;strong&gt;Xubuntu&lt;/strong&gt; (Xfce) as the desktop environment it might be somewhat different from others, but I hope in overall it should be transferable.&lt;/p&gt;

&lt;p&gt;Let’s start by assuming that we have created and installed our desktop environment on a new container already after which we can now begin.&lt;/p&gt;

&lt;h1 id=&quot;container-with-gpu&quot;&gt;Container with GPU&lt;/h1&gt;

&lt;p&gt;You should be well familiar with &lt;code class=&quot;highlighter-rouge&quot;&gt;lxc.cgroup.devices.allow&lt;/code&gt; we need to declare it for all devices we want the container to have access to be it GPU, keyboard, mouse or audio.&lt;/p&gt;

&lt;p&gt;For example, if you want to grant some access for container number &lt;code class=&quot;highlighter-rouge&quot;&gt;123&lt;/code&gt;, you go to &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/pve/lxc/123.conf&lt;/code&gt; and adjust the configurations.&lt;/p&gt;

&lt;p&gt;The overall limitation of using GPU inside the container boils down to this: we install the GPU driver on the host, allowing the container to access to the device, and reinstall the GPU driver on the container as well. This is because the container has no access to change the kernel modules, our driver module must already be loaded by the host.&lt;/p&gt;

&lt;p&gt;In my case, the Intel GPU driver is already loaded in the Proxmox host under the name of &lt;code class=&quot;highlighter-rouge&quot;&gt;i915&lt;/code&gt; kernel module. You can see for yourself using &lt;code class=&quot;highlighter-rouge&quot;&gt;lspci -v&lt;/code&gt;. Find the Intel GPU and see its loaded kernel module. Please note that &lt;code class=&quot;highlighter-rouge&quot;&gt;i915&lt;/code&gt; seems to be the module name for all GPUs.&lt;/p&gt;

&lt;h2 id=&quot;granting-the-container-access&quot;&gt;Granting the container access&lt;/h2&gt;

&lt;p&gt;What then needs to be granted access to the container? My experience results in this:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;/dev/dri/card0&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;/dev/dri/renderD128&lt;/code&gt;&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;/dev/fb0&lt;/code&gt;. This the frame buffer for &lt;code class=&quot;highlighter-rouge&quot;&gt;card0&lt;/code&gt;.&lt;/li&gt;
  &lt;li&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;/dev/tty7&lt;/code&gt;. Actually, you can use any (that is not currently used). To my understanding this is like allowing the container to access our &lt;em&gt;monitor&lt;/em&gt;, I guess.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To grant the container access, we need to have their &lt;em&gt;major&lt;/em&gt; and &lt;em&gt;minor&lt;/em&gt; numbers. Which could be obtained thus:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@desktop:/dev# ls -l /dev/dri/card0
crw-rw---- 1 root video 226, 0 Mar 11 00:53 /dev/dri/card0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Device&lt;/th&gt;
      &lt;th&gt;Major&lt;/th&gt;
      &lt;th&gt;Minor&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;/dev/dri/card0&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;226&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;/dev/dri/renderD128&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;226&lt;/td&gt;
      &lt;td&gt;128&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;/dev/fb0&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;29&lt;/td&gt;
      &lt;td&gt;0&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;/dev/tty7&lt;/code&gt;&lt;/td&gt;
      &lt;td&gt;4&lt;/td&gt;
      &lt;td&gt;7&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;So we have the first change we need to make to the &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/pve/lxc/&amp;lt;id&amp;gt;.conf&lt;/code&gt; should be:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;lxc.cgroup.devices.allow: c 226:0 rwm
lxc.cgroup.devices.allow: c 226:128 rwm
lxc.cgroup.devices.allow: c 4:7 rwm
lxc.cgroup.devices.allow: c 29:0 rwm
lxc.mount.entry: /dev/dri/card0 dev/dri/card0 none bind,optional,create=file
lxc.mount.entry: /dev/dri/renderD128 dev/dri/renderD128 none bind,optional,create=file
lxc.mount.entry: /dev/tty7 dev/tty7 none bind,optional,create=file
lxc.mount.entry: /dev/fb0 dev/fb0 none bind,optional,create=file

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h3 id=&quot;explanations&quot;&gt;Explanations&lt;/h3&gt;

&lt;p&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;lxc.cgroup.devices.allow: c 226:0 rwm&lt;/code&gt; means allowing the container to &lt;code class=&quot;highlighter-rouge&quot;&gt;rwm&lt;/code&gt; (read/write/mount) the device which has the major number of 226 and minor number of 0. You can use a wildcard here e.g. &lt;code class=&quot;highlighter-rouge&quot;&gt;c 226:* rwm&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;Granting the permission alone is not enough if the device is not &lt;em&gt;present&lt;/em&gt; in the container’s &lt;code class=&quot;highlighter-rouge&quot;&gt;/dev&lt;/code&gt; directory. The second part is just creating corresponding files in the container’s &lt;code class=&quot;highlighter-rouge&quot;&gt;dev&lt;/code&gt;. If you want to create a whole directory (and everything within it) you could use &lt;code class=&quot;highlighter-rouge&quot;&gt;create=dir&lt;/code&gt; option instead i.e. &lt;code class=&quot;highlighter-rouge&quot;&gt;lxc.mount.entry: /dev/dri dev/dri none bind,optional,create=dir&lt;/code&gt;. This could be problematic if you have more than one GPU. Allowing the container to see a GPU meant not to be used by it is a bad idea because it leads to many problems down the line. For example, in my case, I also have an Nvidia card. The container’s Xorg tries to utilize both GPUs via Nvidia’s Optimus technology which might not be the thing you want.&lt;/p&gt;

&lt;p&gt;Please note that &lt;code class=&quot;highlighter-rouge&quot;&gt;dev/tty7&lt;/code&gt; is the correct container’s path with leading &lt;code class=&quot;highlighter-rouge&quot;&gt;/&lt;/code&gt; it won’t work.&lt;/p&gt;

&lt;p&gt;The host’s TTY number could be any as said, but the container’s TTY needs to be &lt;code class=&quot;highlighter-rouge&quot;&gt;tty7&lt;/code&gt; unless configured otherwise. It seems that Xorg looks at this particular TTY, if it is not present you will see an error in container’s &lt;code class=&quot;highlighter-rouge&quot;&gt;/var/log/Xorg.0.log&lt;/code&gt;. So it is possible to configure it this way: &lt;code class=&quot;highlighter-rouge&quot;&gt;lxc.mount.entry: /dev/ttyN dev/tty7&lt;/code&gt; where &lt;code class=&quot;highlighter-rouge&quot;&gt;N&lt;/code&gt; is the number you like.&lt;/p&gt;

&lt;p&gt;You can now stop and start your container:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pct stop &amp;lt;id&amp;gt;
pct start &amp;lt;id&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You should see the monitor displaying your desktop environment albeit keyboards and mouses might not work yet.&lt;/p&gt;

&lt;p&gt;Many would suggest installing the Intel driver for accelerated video decoding on the container as well:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt install i965-va-driver
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;switching-between-ttys&quot;&gt;Switching between TTY’s&lt;/h2&gt;

&lt;p&gt;You can use &lt;code class=&quot;highlighter-rouge&quot;&gt;ctrl+alt+f&amp;lt;number&amp;gt;&lt;/code&gt; to switch to &lt;code class=&quot;highlighter-rouge&quot;&gt;TTY&amp;lt;number&amp;gt;&lt;/code&gt;. This might not work 100% if the desktop manager on the current TTY ignore these keys.&lt;/p&gt;

&lt;h2 id=&quot;preventing-the-screen-tearing&quot;&gt;Preventing the screen tearing&lt;/h2&gt;

&lt;p&gt;Using Intel GPU could see &lt;em&gt;tearing&lt;/em&gt; artifacts while scrolling. The feeling is like playing games without vertical sync. If you don’t encounter this problem, feel free to skip.&lt;/p&gt;

&lt;p&gt;File: &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/X11/xorg.conf.d/20-intel.conf&lt;/code&gt;&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Section &quot;Device&quot;
    Identifier &quot;Intel Graphics&quot;
    Driver &quot;intel&quot;
    Option &quot;TearFree&quot; &quot;true&quot;
EndSection
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Thanks to &lt;a href=&quot;https://wiki.archlinux.org/index.php/intel_graphics&quot;&gt;https://wiki.archlinux.org/index.php/intel_graphics&lt;/a&gt;&lt;/p&gt;

&lt;h1 id=&quot;keyboard-and-mouse-in-lxc&quot;&gt;Keyboard and mouse in LXC&lt;/h1&gt;

&lt;p&gt;Keyboard and mouse are &lt;code class=&quot;highlighter-rouge&quot;&gt;/dev/input&lt;/code&gt; devices even though they are connected via USB ports. It is easy misled by &lt;code class=&quot;highlighter-rouge&quot;&gt;/dev/usb&lt;/code&gt; but it has nothing to do with it. You don’t need to grant access to &lt;code class=&quot;highlighter-rouge&quot;&gt;/dev/usb&lt;/code&gt; to make keyboard and mouse work.&lt;/p&gt;

&lt;p&gt;We do the same thing as before using:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;ls -l /dev/input
total 0
drwxr-xr-x 2 root root     180 Mar 10 17:05 by-id
drwxr-xr-x 2 root root     200 Mar 10 17:05 by-path
crw-rw---- 1 root input 13, 64 Mar 10 17:05 event0
crw-rw---- 1 root input 13, 65 Mar 10 17:05 event1
crw-rw---- 1 root input 13, 74 Mar 10 17:05 event10
crw-rw---- 1 root input 13, 75 Mar 10 17:05 event11
... a lot more ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I personally grant and map them all to the container using, update the &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/pve/lxc/&amp;lt;id&amp;gt;.conf&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;lxc.cgroup.devices.allow = c 13:* rwm 
lxc.mount.entry: /dev/input dev/input none bind,optional,create=dir
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Next we need to tell the Xorg to use these input devices also telling which driver we want to use for each. I have found &lt;code class=&quot;highlighter-rouge&quot;&gt;evdev&lt;/code&gt; driver to work well in my case both mouse and keyboard.&lt;/p&gt;

&lt;p&gt;To install the driver in the container:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt install xserver-xorg-input-evdev
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To tell the Xorg which devices to load we need to know which &lt;code class=&quot;highlighter-rouge&quot;&gt;/dev/input/eventN&lt;/code&gt; ‘s are related to our mouse and keyboard. This could be done using &lt;code class=&quot;highlighter-rouge&quot;&gt;evtest&lt;/code&gt;. You can install the program on the host or on the container:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt install evtest
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Using it would result:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@desktop:/dev# evtest
No device specified, trying to scan all of /dev/input/event*
Available devices:
/dev/input/event0:	Sleep Button
/dev/input/event1:	Power Button
/dev/input/event2:	Power Button
/dev/input/event3:	Logitech USB Receiver
/dev/input/event4:	Logitech USB Receiver
/dev/input/event5:	Microsoft Microsoft® Nano Transceiver v2.0
/dev/input/event6:	Microsoft Microsoft® Nano Transceiver v2.0
/dev/input/event7:	Microsoft Microsoft® Nano Transceiver v2.0
/dev/input/event8:	Video Bus
/dev/input/event9:	PC Speaker
/dev/input/event10:	HDA NVidia HDMI/DP,pcm=3
/dev/input/event11:	HDA NVidia HDMI/DP,pcm=7
/dev/input/event12:	HDA NVidia HDMI/DP,pcm=8
/dev/input/event13:	HDA NVidia HDMI/DP,pcm=9
/dev/input/event14:	HDA Intel PCH Front Mic
/dev/input/event15:	HDA Intel PCH Rear Mic
/dev/input/event16:	HDA Intel PCH Line
/dev/input/event17:	HDA Intel PCH Line Out
/dev/input/event18:	HDA Intel PCH Front Headphone
/dev/input/event19:	HDA Intel PCH HDMI/DP,pcm=3
/dev/input/event20:	HDA Intel PCH HDMI/DP,pcm=7
/dev/input/event21:	HDA Intel PCH HDMI/DP,pcm=8
/dev/input/event22:	HDA Intel PCH HDMI/DP,pcm=9
/dev/input/event23:	HDA Intel PCH HDMI/DP,pcm=10
Select the device event number [0-23]: 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The mouse is Logitech in this case, and the keyboard is Microsoft. I could tell Xorg to load them all. However, if you are in doubt you can always test it by inputting the number and try typing or moving it to see if it triggers any event.&lt;/p&gt;

&lt;p&gt;In container, edit the file &lt;code class=&quot;highlighter-rouge&quot;&gt;/usr/share/X11/xorg.conf.d/10-lxc-input.conf&lt;/code&gt;:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Section &quot;InputDevice&quot;
    Identifier &quot;event3&quot;
    Option &quot;Device&quot; &quot;/dev/input/event3&quot;
    Option &quot;AutoServerLayout&quot; &quot;true&quot;
    Driver &quot;evdev&quot;
EndSection

Section &quot;InputDevice&quot;
    Identifier &quot;event4&quot;
    Option &quot;Device&quot; &quot;/dev/input/event5&quot;
    Option &quot;AutoServerLayout&quot; &quot;true&quot;
    Driver &quot;evdev&quot;
EndSection

... for any event you want ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Restart the container again. Mouse and keyboard should now work.&lt;/p&gt;

&lt;h1 id=&quot;audio-in-lxc&quot;&gt;Audio in LXC&lt;/h1&gt;

&lt;p&gt;Most of the configurations in this guide need some understanding of the linux hardware and software stack which I am lacking. But none is worse in the case of audio. This is convoluted. I just managed to make it work, but don’t expect my explanation to be correct.&lt;/p&gt;

&lt;p&gt;I think a good starting point if you are interested in keywords in linux audio stack is: &lt;a href=&quot;https://www.cnblogs.com/little-ant/p/4016180.html&quot;&gt;https://www.cnblogs.com/little-ant/p/4016180.html&lt;/a&gt;. This is not the original post, but it is a working link.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Disclaimer: I have seen many approaches to audio in container. In this guide, it will be just one of them.&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;make-audio-work-on-the-host&quot;&gt;Make audio work on the host&lt;/h2&gt;

&lt;p&gt;To be foolproof, I think it is a good start if we can make sound from the host first, and then we will make it work from the container. We will need many tools in &lt;code class=&quot;highlighter-rouge&quot;&gt;alsa-utils&lt;/code&gt; so we first install it on the host.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt install alsa-utils
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, we are going to list the audio devices:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@desktop:/dev# aplay -L
null
    Discard all samples (playback) or generate zero samples (capture)
default:CARD=PCH
    HDA Intel PCH, ALC887-VD Analog
    Default Audio Device
sysdefault:CARD=PCH
    HDA Intel PCH, ALC887-VD Analog
    Default Audio Device
front:CARD=PCH,DEV=0
    HDA Intel PCH, ALC887-VD Analog
    Front speakers
surround21:CARD=PCH,DEV=0
    HDA Intel PCH, ALC887-VD Analog
    2.1 Surround output to Front and Subwoofer speakers
surround40:CARD=PCH,DEV=0
    HDA Intel PCH, ALC887-VD Analog
    4.0 Surround output to Front and Rear speakers
surround41:CARD=PCH,DEV=0
    HDA Intel PCH, ALC887-VD Analog
    4.1 Surround output to Front, Rear and Subwoofer speakers
surround50:CARD=PCH,DEV=0
    HDA Intel PCH, ALC887-VD Analog
    5.0 Surround output to Front, Center and Rear speakers
surround51:CARD=PCH,DEV=0
    HDA Intel PCH, ALC887-VD Analog
    5.1 Surround output to Front, Center, Rear and Subwoofer speakers
surround71:CARD=PCH,DEV=0
    HDA Intel PCH, ALC887-VD Analog
    7.1 Surround output to Front, Center, Side, Rear and Woofer speakers
hdmi:CARD=PCH,DEV=0
    HDA Intel PCH, HDMI 0
    HDMI Audio Output
... many more ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It is unclear to know which is responsible for the output we are listening to. In my settings, I’m connecting a monitor via an HDMI cable, so I’m looking for HDMI in particular.&lt;/p&gt;

&lt;p&gt;To know which one, we need test each output by producing some noise. This could be done using &lt;code class=&quot;highlighter-rouge&quot;&gt;speaker-test&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;You might need to test all of them, but the command is something like:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;speaker-test -D &amp;lt;name&amp;gt; -c 2
# for example
speaker-test -D hdmi:CARD=PCH,DEV=0 -c 2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;One of them would produce noise, and you now know which one it is, and also know that the audio works.&lt;/p&gt;

&lt;h2 id=&quot;make-audio-work-on-the-container&quot;&gt;Make audio work on the container&lt;/h2&gt;

&lt;p&gt;At the container’s side, we are looking for &lt;code class=&quot;highlighter-rouge&quot;&gt;/dev/snd&lt;/code&gt; which has the major number of 116. We would map them all to the container.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;root@desktop:/dev# ls -l /dev/snd
total 0
drwxr-xr-x 2 root root       80 Mar 10 17:05 by-path
crw-rw---- 1 root audio 116,  8 Mar 10 17:05 controlC0
crw-rw---- 1 root audio 116,  2 Mar 10 17:05 controlC1
crw-rw---- 1 root audio 116, 17 Mar 10 17:05 hwC0D0
crw-rw---- 1 root audio 116, 18 Mar 10 17:05 hwC0D2
crw-rw---- 1 root audio 116,  7 Mar 10 17:05 hwC1D0
crw-rw---- 1 root audio 116, 10 Mar 10 17:05 pcmC0D0c
crw-rw---- 1 root audio 116,  9 Mar 10 17:05 pcmC0D0p
crw-rw---- 1 root audio 116, 16 Mar 10 17:05 pcmC0D10p
... many more ...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Please note that if the audio producer in the container is not root, let’s say &lt;code class=&quot;highlighter-rouge&quot;&gt;joe&lt;/code&gt;, you need to add &lt;code class=&quot;highlighter-rouge&quot;&gt;joe&lt;/code&gt; to &lt;code class=&quot;highlighter-rouge&quot;&gt;audio&lt;/code&gt; group using, at the container:&lt;/p&gt;

&lt;div class=&quot;language-shell highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nb&quot;&gt;sudo &lt;/span&gt;usermod &lt;span class=&quot;nt&quot;&gt;-aG&lt;/span&gt; audio joe
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;At the host, we need to update the container configuration again:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;lxc.cgroup.devices.allow = c 116:* rwm 
lxc.mount.entry: /dev/snd dev/snd none bind,optional,create=dir
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After restarting the container, test if the audio devices are available:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;aplay -L
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You should see the very same output as the root’s one.&lt;/p&gt;

&lt;p&gt;Finally, we tell the Pulse audio in the container to manually look for &lt;em&gt;alsa-sink&lt;/em&gt; on a specific device we have tested. Modify the file &lt;code class=&quot;highlighter-rouge&quot;&gt;/etc/pulse/default.pa&lt;/code&gt; by looking for &lt;code class=&quot;highlighter-rouge&quot;&gt;load-module module-also-sink&lt;/code&gt;. You might see it commented, uncomment it, and update it so:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;load-module module-alsa-sink device=&amp;lt;name&amp;gt;
# for example
load-module module-alsa-sink device=hdmi:CARD=PCH,DEV=0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;After that you might need to reload the pulse audio, in the container:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;pulseaudio -k
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Or restart the container should yield the same result. Your audio should now work. You can go to &lt;strong&gt;PulseAudio&lt;/strong&gt; app and see if it the audio device is recognized.&lt;/p&gt;

&lt;p&gt;However, it is possible that the device is muted (by some external means). To guarantee it is not, we run, in the container:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;alsamixer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You should see the following screen:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/articles/setting-up-lxc-for-intel-gpu-proxmox/1552279415943.png&quot; alt=&quot;1552279415943&quot; /&gt;&lt;/p&gt;

&lt;p&gt;If you see any of them to be &lt;strong&gt;MM&lt;/strong&gt; which is muted. You need to make it not by selecting it and press &lt;strong&gt;M&lt;/strong&gt;. You’ll see the following screen:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/articles/setting-up-lxc-for-intel-gpu-proxmox/1552279220123.png&quot; alt=&quot;1552279220123&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Nothing is muted now.&lt;/p&gt;</content><author><name>Konpat Preechakul</name></author><category term="proxmox" /><category term="linux" /><summary type="html">The goal is to create a linux container with Proxmox that utilizes integrated Intel GPU. Additional requirements are mouse and keyboard must work also with audio.</summary></entry><entry><title type="html">Approximately Optimal Approximate Reinforcement Learning (Kakade &amp;amp; Langford, 2002)</title><link href="https://blog.konpat.me/academic/2019/03/09/kakade-2002.html" rel="alternate" type="text/html" title="Approximately Optimal Approximate Reinforcement Learning (Kakade &amp; Langford, 2002)" /><published>2019-03-09T00:00:00+07:00</published><updated>2019-03-09T00:00:00+07:00</updated><id>https://blog.konpat.me/academic/2019/03/09/kakade-2002</id><content type="html" xml:base="https://blog.konpat.me/academic/2019/03/09/kakade-2002.html">&lt;p&gt;In this article, we will try to retell the paper in a simpler way by which it is easier to follow. At the moment, we will only focus on the first part of the paper which tries to give an answer to the following question:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Is there a way to guarantee policy improvement?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And the answer is &lt;strong&gt;yes&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In order to do show we need 3 ingredients:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Policy performance measurement&lt;/li&gt;
  &lt;li&gt;Policy improvement algorithm&lt;/li&gt;
  &lt;li&gt;Improved policy performance estimation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The overall idea is that if we can give the &lt;em&gt;lower bound&lt;/em&gt; to the improved policy performance and we can show that it is &amp;gt; 0, we thus guarantee policy improvement.&lt;/p&gt;

&lt;p&gt;So the path forward is to show you approaches to estimate the improved policy performance.&lt;/p&gt;

&lt;h3 id=&quot;basics&quot;&gt;Basics&lt;/h3&gt;

&lt;p&gt;&lt;script type=&quot;math/tex&quot;&gt;V_\pi(s)&lt;/script&gt; is a state-value function.&lt;/p&gt;

&lt;p&gt;&lt;script type=&quot;math/tex&quot;&gt;Q_\pi(s, a)&lt;/script&gt; is a action-value function.&lt;/p&gt;

&lt;p&gt;&lt;script type=&quot;math/tex&quot;&gt;A_\pi(s, a) = Q_\pi(s, a) - V_\pi(s)&lt;/script&gt; is an advantage function.&lt;/p&gt;

&lt;h2 id=&quot;policy-performance&quot;&gt;Policy performance&lt;/h2&gt;

&lt;p&gt;We first define the policy performance as an average performance over state states.&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\eta_D(\pi) = \mathrm{E}_{s \sim D} \left[ V_\pi(s) \right]&lt;/script&gt;

&lt;p&gt;where the start state distribution is &lt;script type=&quot;math/tex&quot;&gt;D&lt;/script&gt;. In the paper, this &lt;script type=&quot;math/tex&quot;&gt;D&lt;/script&gt; could be substituted with other distribution at will under the notion of &lt;strong&gt;restart distribution&lt;/strong&gt; but we don’t care about it that much here. Let’s say that it is under &lt;em&gt;some&lt;/em&gt; start state distribution.&lt;/p&gt;

&lt;h2 id=&quot;conservative-greedy-policy-improvement&quot;&gt;Conservative greedy policy improvement&lt;/h2&gt;

&lt;p&gt;The usual policy improvement is to alter the current policy to be &lt;script type=&quot;math/tex&quot;&gt;\mathrm{argmax}_a A(s, a)&lt;/script&gt; for all &lt;script type=&quot;math/tex&quot;&gt;s&lt;/script&gt;. Here we look for a more general case allowing us to transform the policy in a more granular way using &lt;script type=&quot;math/tex&quot;&gt;\alpha&lt;/script&gt; as a parameter.&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\pi_{new} = (1-\alpha)\pi + \alpha\pi'&lt;/script&gt;

&lt;p&gt;where &lt;script type=&quot;math/tex&quot;&gt;\pi'&lt;/script&gt; is a greedy improvement of &lt;script type=&quot;math/tex&quot;&gt;\pi&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;So our goal is to guarantee the improvement of policy under the conservative greedy improvement that is:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\eta(\pi_{new}) - \eta(\pi) &gt; 0
\label{eq:eta}&lt;/script&gt;

&lt;p&gt;That is at any moment we need to find &lt;script type=&quot;math/tex&quot;&gt;\alpha&lt;/script&gt; that satisfies the above inequation. In other words, how small should &lt;script type=&quot;math/tex&quot;&gt;\alpha&lt;/script&gt; be that it still improves the policy.&lt;/p&gt;

&lt;h2 id=&quot;improved-policy-performance-estimation&quot;&gt;Improved policy performance estimation&lt;/h2&gt;

&lt;p&gt;As you see from &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:eta}&lt;/script&gt;, we need to get the improved policy performance &lt;script type=&quot;math/tex&quot;&gt;\eta(\pi_{new})&lt;/script&gt;, but we want to get it cheaply because we might need to fine tune it for the right &lt;script type=&quot;math/tex&quot;&gt;\alpha&lt;/script&gt;. This not viable to just rerun the policy evaluation (on a new set of experience from &lt;script type=&quot;math/tex&quot;&gt;\pi_{new}​&lt;/script&gt;), it is just too slow. We need to estimate its lower bound.&lt;/p&gt;

&lt;p&gt;In the paper, the author shows two ways for estimation:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Using Taylor’s series to the first order. Unfortunately this approach does get us any closer to the lower bound of the estimation. But it is a useful starting point anyway.&lt;/li&gt;
  &lt;li&gt;Using the author’s proposed approach. This gives a lower bound.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&quot;using-taylors-series-to-approximate&quot;&gt;Using Taylor’s series to approximate&lt;/h3&gt;

&lt;p&gt;If we write &lt;script type=&quot;math/tex&quot;&gt;\eta(\pi)&lt;/script&gt; using Taylor’s expansion to the first degree we will get:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\eta(\pi+x) = \eta(\pi) + x \nabla_\pi \eta(\pi) + \mathrm{O}(x^2)
\label{eq:eta_x}&lt;/script&gt;

&lt;p&gt;Here we have an approximation error in the order of &lt;script type=&quot;math/tex&quot;&gt;\mathrm{O}(x^2)&lt;/script&gt; albeit not knowing its constant factor.&lt;/p&gt;

&lt;p&gt;Since our policy improvement is not exactly in the form of aforementioned &lt;script type=&quot;math/tex&quot;&gt;x​&lt;/script&gt;, we rather want it to be in the form of &lt;script type=&quot;math/tex&quot;&gt;\alpha​&lt;/script&gt; (recall the conservative policy improvement).&lt;/p&gt;

&lt;p&gt;So we want to get the estimate of something like:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\eta_\pi(\alpha) = \eta((1-\alpha)\pi + \alpha \pi') = \eta(\pi) + \alpha \nabla_\alpha \eta(\pi) + \mathrm{O}(\alpha^2)
\label{eq:eta_alpha}&lt;/script&gt;

&lt;p&gt;From &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:eta_x}&lt;/script&gt;, the only problematic part is the second term (first derivative), we want &lt;script type=&quot;math/tex&quot;&gt;\nabla_\alpha&lt;/script&gt; not &lt;script type=&quot;math/tex&quot;&gt;\nabla_\pi&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;We now begin to derive the &lt;script type=&quot;math/tex&quot;&gt;\nabla_\alpha \eta(\pi)&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;The gradient of policy performance was first derived in Sutton’s 1999, policy gradient theorem. We would put it here without further ado:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{aligned}
\nabla_\pi \eta(\pi) &amp;= \sum_{s, a} d_\pi(s) Q_\pi(s, a) \nabla \pi(a|s) \\
&amp;= \sum_{s, a} d_\pi(s) A_\pi(s, a) \nabla \pi(a|s) 
\end{aligned}
\label{eq:policy_gradient}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;where &lt;script type=&quot;math/tex&quot;&gt;d_\pi(s)&lt;/script&gt; is a discounted state visitation probability. For completeness:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;d_\pi(s) = \sum_{t=0}^\infty \gamma^t \mathrm{P}(s_t=s, \pi)&lt;/script&gt;

&lt;p&gt;where &lt;script type=&quot;math/tex&quot;&gt;\mathrm{P}(s_t=s, \pi)&lt;/script&gt; is the probability of visiting state &lt;script type=&quot;math/tex&quot;&gt;s&lt;/script&gt; after taking &lt;script type=&quot;math/tex&quot;&gt;t&lt;/script&gt; steps under a policy &lt;script type=&quot;math/tex&quot;&gt;\pi&lt;/script&gt;. Please note that &lt;script type=&quot;math/tex&quot;&gt;d_\pi&lt;/script&gt; is not a probability distribution (it does not sum to &lt;script type=&quot;math/tex&quot;&gt;1&lt;/script&gt;), but we can make it so by multiplying &lt;script type=&quot;math/tex&quot;&gt;1-\gamma&lt;/script&gt; to it (since &lt;script type=&quot;math/tex&quot;&gt;\sum_{i=0}^\infty \gamma^i = \frac{1}{1-\gamma}&lt;/script&gt;).&lt;/p&gt;

&lt;p&gt;From &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:policy_gradient}&lt;/script&gt;, we substitute &lt;script type=&quot;math/tex&quot;&gt;\nabla_\pi&lt;/script&gt; with &lt;script type=&quot;math/tex&quot;&gt;\nabla_\alpha&lt;/script&gt;, we also write &lt;script type=&quot;math/tex&quot;&gt;\pi&lt;/script&gt; as a function of &lt;script type=&quot;math/tex&quot;&gt;\alpha&lt;/script&gt;:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{align}
\nabla_\alpha \eta(\pi) &amp;= \sum_{s, a} d_\pi(s) A_\pi(s, a) \nabla_\alpha \left[ (1-\alpha) \pi + \alpha \pi' \right]
\label{eq:eta_alpha1}
\end{align} %]]&gt;&lt;/script&gt;

&lt;p&gt;Consider &lt;script type=&quot;math/tex&quot;&gt;\nabla_\alpha \left[ (1-\alpha) \pi + \alpha \pi' \right]&lt;/script&gt;:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\nabla_\alpha \left[ (1-\alpha) \pi + \alpha \pi' \right] = -\pi + \pi'
\label{eq:pi_grad}&lt;/script&gt;

&lt;p&gt;We substitute &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:pi_grad}&lt;/script&gt; into &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:eta_alpha1}&lt;/script&gt; followed by some algebra:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{aligned}
\nabla_\alpha \eta(\pi) 
&amp;= \sum_{s, a} d_\pi(s) A_\pi(s, a) (-\pi + \pi') \\
&amp;= - \sum_{s, a} d_\pi(s) A_\pi(s, a) \pi(a|s) + \sum_{s,a} d_\pi(s) A_\pi(s, a) \pi'(a|s) \\
&amp;= - \sum_{s} d_\pi(s) \cancel{\sum_a A_\pi(s, a) \pi(a|s)} + \sum_{s,a} d_\pi(s) A_\pi(s, a) \pi'(a|s) \\
&amp;= \sum_{s,a} d_\pi(s) A_\pi(s, a) \pi'(a|s)
\end{aligned}
\label{eq:eta_grad}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;This gradient can be computed without the need to further interact with the environment. We just need to change &lt;script type=&quot;math/tex&quot;&gt;\pi&lt;/script&gt; to &lt;script type=&quot;math/tex&quot;&gt;\pi'&lt;/script&gt; and then rerun on the previous experience.&lt;/p&gt;

&lt;h4 id=&quot;policy-advantage&quot;&gt;Policy advantage&lt;/h4&gt;

&lt;p&gt;The quantity in &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:eta_grad}&lt;/script&gt; is closely related to &lt;strong&gt;policy advantage&lt;/strong&gt; which defines:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\mathbb{A}_\pi(\tilde{\pi}) = \mathrm{E}_{s \sim d_\pi} \mathrm{E}_{a \sim \tilde{\pi}} A_\pi(s, a)
\label{eq:policy_adv}&lt;/script&gt;

&lt;p&gt;Since it obeys the expectation, it uses a normalized distribution. Hence:
&lt;script type=&quot;math/tex&quot;&gt;\mathbb{A}_\pi(\tilde{\pi}) = (1-\gamma) \nabla_\alpha \eta(\pi)&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;Intuitively, the policy advantage tells us how much &lt;script type=&quot;math/tex&quot;&gt;\tilde{\pi}&lt;/script&gt; tries to take large advantages (be greedy). If &lt;script type=&quot;math/tex&quot;&gt;\tilde{\pi} = \pi&lt;/script&gt;, this quantity is &lt;script type=&quot;math/tex&quot;&gt;0&lt;/script&gt;. It is maximized when &lt;script type=&quot;math/tex&quot;&gt;\pi'&lt;/script&gt; is a greedy policy wrt. &lt;script type=&quot;math/tex&quot;&gt;\pi&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;Don’t be confused! &lt;script type=&quot;math/tex&quot;&gt;\mathbb{A}_\pi&lt;/script&gt; is a policy advantage which looks at all states, but &lt;script type=&quot;math/tex&quot;&gt;A_\pi&lt;/script&gt; is an advantage function looks at a particular state and action.&lt;/p&gt;

&lt;h4 id=&quot;taylors-expansion-of-policy-performance&quot;&gt;Taylor’s expansion of policy performance&lt;/h4&gt;

&lt;p&gt;We now get:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{aligned}
\eta(\pi_{new}) 
&amp;= \eta(\pi) + \alpha \nabla_\alpha \eta(\pi) + \mathrm{O}(\alpha^2) \\
&amp;= \eta(\pi) + \frac{\alpha}{1-\gamma} \mathbb{A}_\pi(\pi') + \mathrm{O}(\alpha^2)
\end{aligned}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;Now, we can draw some conclusion from the above equation:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;With policy improvement the second term (first derivative) is positive (if the policy is not optimal).&lt;/li&gt;
  &lt;li&gt;If &lt;script type=&quot;math/tex&quot;&gt;\alpha&lt;/script&gt; is small enough, the second term will dominate the third term (second derivative) resulting in policy improvement.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The only problem is that we don’t know what &lt;script type=&quot;math/tex&quot;&gt;\alpha&lt;/script&gt; is to guarantee the policy improvement.  We now turn to a different approach.&lt;/p&gt;

&lt;h3 id=&quot;using-the-authors-approach&quot;&gt;Using the author’s approach&lt;/h3&gt;

&lt;p&gt;In order to guarantee policy improvement, we need to show that &lt;script type=&quot;math/tex&quot;&gt;\eta_\pi(\pi_{new}) - \eta_\pi(\pi) &gt; 0&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;We first rewrite it in a different form.&lt;/p&gt;

&lt;h4 id=&quot;lemma-61&quot;&gt;Lemma 6.1&lt;/h4&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\eta_\pi(\tilde{\pi}) - \eta_\pi(\pi) = \frac{1}{1-\gamma} \mathrm{E}_{a,s \sim \tilde{\pi}, d_{\tilde{\pi}}} \left[ A_\pi(s, a) \right]&lt;/script&gt;

&lt;p&gt;&lt;strong&gt;Proof:&lt;/strong&gt;&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation*}
\begin{aligned}
&amp; \frac{1}{1-\gamma} \mathrm{E}_{a,s \sim \tilde{\pi}, d_{\tilde{\pi}}} \left[ A_\pi(s, a) \right] \\
&amp;= \mathrm{E}_{s_0, a_0, s_1, a_1, \dots \sim \tilde{\pi}} \left[ A_\pi(s_0, a_0) + \gamma A_\pi(s_1, a_1) + \dots  \right] \\
&amp;= \mathrm{E}_{s_0, a_0, s_1, a_1, \dots \sim \tilde{\pi}} \left[ r_1 + \cancel{\gamma V_1} - V_0 + \gamma r_2 + \cancel{\gamma^2 V_2} - \cancel{\gamma V_1} + \dots \right] \\
&amp;= \mathrm{E}_{s_0, a_0, s_1, a_1, \dots \sim \tilde{\pi}} \left[ \sum_{t=0}^\infty \gamma^t r_{t+1} - V_\pi(s_0)  \right] \\
&amp;= \mathrm{E}_{s_0 \sim \tilde{\pi}} \left[ V_{\tilde{\pi}} - V_\pi(s_0)  \right] \\
&amp;= \eta_\pi(\tilde{\pi}) - \eta_\pi(\pi)
\end{aligned}
\end{equation*} %]]&gt;&lt;/script&gt;

&lt;p&gt;With Lemma 6.1 we now have:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{aligned}
\eta_\pi(\pi_{new}) - \eta_\pi(\pi) 
&amp;= \frac{1}{1-\gamma} \mathrm{E}_{a,s \sim \pi_{new}, d_{\pi_{new}}} \left[ A_\pi(s, a) \right] \\
&amp;= \sum_{t=0}^\infty \gamma^t \mathrm{E}_{s \sim P(s_t, \pi_{new})} \mathrm{E}_{a \sim \pi_{new}} \left[ A_\pi(s, a) \right] 
\end{aligned}
\label{eq:eta_delta}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;where &lt;script type=&quot;math/tex&quot;&gt;P(s_t, \pi_{new})&lt;/script&gt; is the probability of visiting state &lt;script type=&quot;math/tex&quot;&gt;s_t&lt;/script&gt; at time &lt;script type=&quot;math/tex&quot;&gt;t&lt;/script&gt; under policy &lt;script type=&quot;math/tex&quot;&gt;\pi_{new}&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;Evidently, we do have &lt;script type=&quot;math/tex&quot;&gt;P(s_t, \pi)&lt;/script&gt; but we do not have &lt;script type=&quot;math/tex&quot;&gt;P(s_t, \pi_{new})&lt;/script&gt;. A way forward is to estimate the equation &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:eta_delta}&lt;/script&gt; with all we have. Since the deviation from our estimate comes from the mismatch between &lt;script type=&quot;math/tex&quot;&gt;P(s_t, \pi_{new})&lt;/script&gt; and &lt;script type=&quot;math/tex&quot;&gt;P(s_t, \pi)&lt;/script&gt;, intuitively, a small &lt;script type=&quot;math/tex&quot;&gt;\alpha&lt;/script&gt; should result in a small mismatch and vice versa. This implies that &lt;script type=&quot;math/tex&quot;&gt;P(s_t, \pi_{new})&lt;/script&gt; must share some roots with &lt;script type=&quot;math/tex&quot;&gt;P(s_t, \pi)&lt;/script&gt; which part we can work with. This allows us to get an informed estimate and put an upper bound to the part we cannot work with.&lt;/p&gt;

&lt;h4 id=&quot;the-two-parts&quot;&gt;The two parts&lt;/h4&gt;

&lt;p&gt;Consider the policy &lt;script type=&quot;math/tex&quot;&gt;\pi_{new}​&lt;/script&gt;, we know from its definition that it is a compound policy. Another way to look at it is we have two policies: &lt;script type=&quot;math/tex&quot;&gt;\pi​&lt;/script&gt; an &lt;script type=&quot;math/tex&quot;&gt;\pi'​&lt;/script&gt;. With probability of &lt;script type=&quot;math/tex&quot;&gt;\alpha​&lt;/script&gt; we will select an action according to &lt;script type=&quot;math/tex&quot;&gt;\pi'​&lt;/script&gt;, and probability of &lt;script type=&quot;math/tex&quot;&gt;1-\alpha​&lt;/script&gt; we will select an action from &lt;script type=&quot;math/tex&quot;&gt;\pi​&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;At time &lt;script type=&quot;math/tex&quot;&gt;t&lt;/script&gt;,&lt;/strong&gt; we define our two parts as:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Part one: we follow &lt;script type=&quot;math/tex&quot;&gt;\pi&lt;/script&gt; from &lt;script type=&quot;math/tex&quot;&gt;t=0&lt;/script&gt; until now.&lt;/li&gt;
  &lt;li&gt;Part two: at some point we selected an action from &lt;script type=&quot;math/tex&quot;&gt;\pi'&lt;/script&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;If we has been following &lt;script type=&quot;math/tex&quot;&gt;\pi&lt;/script&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The probability is &lt;script type=&quot;math/tex&quot;&gt;P(\text{follow } \pi) = (1-\alpha)^t = 1 - \rho_t​&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;The expected advantage function for this part is:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\begin{equation*}
(1-\rho_t) \mathrm{E}_{s \sim P(s_t|\text{follow }\pi)} \mathrm{E}_{a \sim \pi_{new}} \left[ A_\pi(s, a) \right]
\end{equation*}&lt;/script&gt;

&lt;p&gt;&lt;strong&gt;If we has followed &lt;script type=&quot;math/tex&quot;&gt;\pi'&lt;/script&gt; at any point prior &lt;script type=&quot;math/tex&quot;&gt;t&lt;/script&gt;.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The probability is &lt;script type=&quot;math/tex&quot;&gt;P(\text{not follow } \pi) = \rho_t = 1-(1-\alpha)^t​&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;The expected advantage function for this part is:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\begin{equation*}
\rho_t \mathrm{E}_{s \sim P(s_t|\text{not follow }\pi)} \mathrm{E}_{a \sim \pi_{new}} \left[ A_\pi(s, a) \right]
\end{equation*}&lt;/script&gt;

&lt;p&gt;We can define the &lt;em&gt;upper&lt;/em&gt; bound of this value to be:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{align}
\mathrm{E}_{s \sim P(s_t|\text{not follow }\pi)} \mathrm{E}_{a \sim \pi_{new}} \left[ A_\pi(s, a) \right] 
&amp;\leq \max_s \left\vert \mathrm{E}_{a \sim \pi_{new}} \left[ A_\pi(s, a) \right] \right\vert \\
&amp;\leq \max_s \left\vert \mathrm{E}_{a \sim \pi'} \left[ A_\pi(s, a) \right] \right\vert \\
&amp;= \epsilon
\end{align} %]]&gt;&lt;/script&gt;

&lt;p&gt;This is obvious we just use the &lt;script type=&quot;math/tex&quot;&gt;\max&lt;/script&gt; here which literally cannot be exceeded. As you shall see later on, the smaller the &lt;script type=&quot;math/tex&quot;&gt;\epsilon&lt;/script&gt; the tighter our estimate would be.&lt;/p&gt;

&lt;p&gt;The total expected advantage function at time &lt;script type=&quot;math/tex&quot;&gt;t&lt;/script&gt; is then the sum of both:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{aligned}
\mathrm{E}_{s \sim P(s_t, \pi_{new})} \mathrm{E}_{a \sim \pi_{new}} \left[ A_\pi(s, a) \right]
&amp;= (1-\rho_t) \mathrm{E}_{s \sim P(s_t|\text{follow }\pi)} \mathrm{E}_{a \sim \pi_{new}} \left[ A_\pi(s, a) \right] \\ 
&amp; \quad + \rho_t \mathrm{E}_{s \sim P(s_t|\text{not follow }\pi)} \mathrm{E}_{a \sim \pi_{new}} \left[ A_\pi(s, a) \right] \\
&amp; \geq \alpha (1-\rho_t) \mathrm{E}_{s \sim P(s_t|\text{follow }\pi)} \mathrm{E}_{a \sim \pi_{new}} \left[ A_\pi(s, a) \right] \\ 
&amp; \quad - \alpha \rho_t \epsilon
\end{aligned}
\label{eq:two_paths}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;Furthermore, we can show that &lt;script type=&quot;math/tex&quot;&gt;\mathrm{E}_{a \sim \pi_{new}} \left[ A_\pi(s, a) \right] = \alpha \mathrm{E}_{a \sim \pi'} \left[ A_\pi(s, a) \right]&lt;/script&gt;:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation} 
\begin{aligned}
\mathrm{E}_{a \sim \pi_{new}} \left[ A_\pi(s, a) \right]
&amp;= \sum_a ((1-\alpha) \pi(a|s) + \alpha \pi(a|s)) A_\pi(s, a) \\
&amp;= (1-\alpha) \cancel{\sum_a \pi(a|s) A_\pi(s, a)} + \alpha \sum_a \pi'(a|s) A_\pi(s, a) \\
&amp;= \alpha \sum_a \pi'(a|s) A_\pi(s, a)
\end{aligned}
\label{eq:pi'_a}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;Substitute &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:pi'_a}&lt;/script&gt; into &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:two_paths}&lt;/script&gt;:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{aligned}
\mathrm{E}_{s \sim P(s_t, \pi_{new})} \mathrm{E}_{a \sim \pi_{new}} \left[ A_\pi(s, a) \right]
&amp;\geq \alpha (1-\rho_t) \mathrm{E}_{s \sim P(s_t|\text{follow }\pi)} \mathrm{E}_{a \sim \pi'} \left[ A_\pi(s, a) \right] \\ 
&amp; \quad - \alpha \rho_t \epsilon
\end{aligned}\label{eq:two_paths2}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;This is just for a time frame &lt;script type=&quot;math/tex&quot;&gt;t&lt;/script&gt;. After all, we still need to incorporate it into the whole trajectories which extends from &lt;script type=&quot;math/tex&quot;&gt;t=0&lt;/script&gt; to &lt;script type=&quot;math/tex&quot;&gt;t=\infty&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;Apply to all time steps&lt;/p&gt;

&lt;p&gt;Substitute &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:two_paths2}&lt;/script&gt; into &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:eta_delta}&lt;/script&gt;:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{aligned}
\eta(\pi_{new}) - \eta(\pi)
&amp;\geq \alpha \sum_{t=0}^\infty \gamma^t (1-\rho_t) \mathrm{E}_{s \sim P(s_t|\text{follow }\pi)} \mathrm{E}_{a \sim \pi'} \left[ A_\pi(s, a) \right] \\ 
&amp; \quad - \alpha \epsilon \sum_{t=0}^\infty \gamma^t \rho_t 
\end{aligned}
\label{eq:two_parts3}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;Looking more carefully at the first term, &lt;script type=&quot;math/tex&quot;&gt;\rho_t&lt;/script&gt; depends on &lt;script type=&quot;math/tex&quot;&gt;\alpha&lt;/script&gt; which is something we want to find (remember we want to find the policy improving &lt;script type=&quot;math/tex&quot;&gt;\alpha&lt;/script&gt;). With this form, solving to find &lt;script type=&quot;math/tex&quot;&gt;\alpha&lt;/script&gt; will be very hard because it is not in a closed form. We want the $\sum$ term to be a constant independent of &lt;script type=&quot;math/tex&quot;&gt;\alpha&lt;/script&gt;. In this way, solving to find &lt;script type=&quot;math/tex&quot;&gt;\alpha&lt;/script&gt; becomes trivial.&lt;/p&gt;

&lt;p&gt;To realize this, we further substitute &lt;script type=&quot;math/tex&quot;&gt;\epsilon&lt;/script&gt; into &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:two_parts3}&lt;/script&gt;:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{aligned}
\eta(\pi_{new}) - \eta(\pi)
&amp;\geq \alpha \sum_{t=0}^\infty \gamma^t \mathrm{E}_{s \sim P(s_t|\text{follow }\pi)} \mathrm{E}_{a \sim \pi'} \left[ A_\pi(s, a) \right] \\ 
&amp; \quad - \alpha \sum_{t=0}^\infty \gamma^t \rho_t \mathrm{E}_{s \sim P(s_t|\text{follow }\pi)} \mathrm{E}_{a \sim \pi'} \left[ A_\pi(s, a) \right] \\
&amp; \quad - \alpha \epsilon \sum_{t=0}^\infty \gamma^t \rho_t \\
&amp;\geq \alpha \sum_{t=0}^\infty \gamma^t \mathrm{E}_{s \sim P(s_t|\text{follow }\pi)} \mathrm{E}_{a \sim \pi'} \left[ A_\pi(s, a) \right] \\ 
&amp; \quad - \alpha \epsilon \sum_{t=0}^\infty \gamma^t \rho_t \\
&amp; \quad - \alpha \epsilon \sum_{t=0}^\infty \gamma^t \rho_t \\
&amp;= \alpha \sum_{t=0}^\infty \gamma^t \mathrm{E}_{s \sim P(s_t|\text{follow }\pi)} \mathrm{E}_{a \sim \pi'} \left[ A_\pi(s, a) \right] \\ 
&amp; \quad - 2\alpha \epsilon \sum_{t=0}^\infty \gamma^t \rho_t \\
\end{aligned}
\label{eq:two_parts4}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;Consider &lt;script type=&quot;math/tex&quot;&gt;\sum_{t=0}^\infty \gamma^t \mathrm{E}_{s \sim P(s_t \vert \text{follow }\pi)} \mathrm{E}_{a \sim \pi'} \left[ A_\pi(s, a) \right]​&lt;/script&gt;, this is in fact the unnormalized policy advantage (see &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:policy_adv}​&lt;/script&gt;). It equals to &lt;script type=&quot;math/tex&quot;&gt;\frac{1}{1-\gamma} \mathbb{A}_\pi(\pi')​&lt;/script&gt;.&lt;/p&gt;

&lt;p&gt;Now consider the &lt;script type=&quot;math/tex&quot;&gt;\sum_{t=0}^\infty \gamma^t \rho_t&lt;/script&gt;, we can substitute its real values and get:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{aligned}
\sum_{t=0}^\infty \gamma^t \rho_t 
&amp;= \sum_{t=0}^\infty \gamma^t (1-(1-\alpha)^t) \\
&amp;= \sum_{t=0}^\infty \gamma^t - \sum_{t=0}^\infty \gamma^t (1-\alpha)^t \\
&amp;= \frac{1}{1-\gamma} - \frac{1}{1-\gamma(1-\alpha)} \\
&amp;= \frac{\gamma\alpha}{(1-\gamma)(1-\gamma(1-\alpha))}
\end{aligned}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;Substitute them into &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:two_parts4}&lt;/script&gt;:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{aligned}
\eta(\pi_{new}) - \eta(\pi)
&amp;\geq \frac{\alpha}{1-\gamma} \mathbb{A}_\pi(\pi') \\ 
&amp; \quad - 2\alpha \epsilon \left[ \frac{\gamma\alpha}{(1-\gamma)(1-\gamma(1-\alpha))} \right] \\
&amp;= \frac{\alpha}{1-\gamma} \left[ \mathbb{A}_\pi(\pi') 
- \frac{2\epsilon\gamma\alpha}{1-\gamma(1-\alpha)} \right]
\end{aligned}
\label{eq:two_parts5}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;We call equation &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:two_parts5}&lt;/script&gt; &lt;strong&gt;theorem 4.1&lt;/strong&gt;.&lt;/p&gt;

&lt;h4 id=&quot;finding-the-right-step&quot;&gt;Finding the right step&lt;/h4&gt;

&lt;p&gt;Finally, we want to guarantee the policy improvement by selecting a proper &lt;script type=&quot;math/tex&quot;&gt;\alpha&lt;/script&gt;. We then need to solve for &lt;script type=&quot;math/tex&quot;&gt;\alpha&lt;/script&gt;:&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{aligned}
\eta(\pi_{new}) - \eta(\pi)
&amp;\geq \frac{\alpha}{1-\gamma} \left[ \mathbb{A}_\pi(\pi') 
- \frac{2\epsilon\gamma\alpha}{1-\gamma(1-\alpha)} \right] 
\gt 0
\end{aligned}
\label{eq:two_parts6}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;This &lt;script type=&quot;math/tex&quot;&gt;\alpha&lt;/script&gt; would be guaranteed to improve the policy because we calculate it from the pessimistic estimate (its lower bound).&lt;/p&gt;</content><author><name>Konpat Preechakul</name></author><category term="rl" /><summary type="html">In this article, we will try to retell the paper in a simpler way by which it is easier to follow. At the moment, we will only focus on the first part of the paper which tries to give an answer to the following question:</summary></entry><entry><title type="html">NFS file attribution caching causes reading inconsistency in multi-producer scenario</title><link href="https://blog.konpat.me/dev/2019/02/17/nfs-read-inconsistencies.html" rel="alternate" type="text/html" title="NFS file attribution caching causes reading inconsistency in multi-producer scenario" /><published>2019-02-17T00:00:00+07:00</published><updated>2019-02-17T00:00:00+07:00</updated><id>https://blog.konpat.me/dev/2019/02/17/nfs-read-inconsistencies</id><content type="html" xml:base="https://blog.konpat.me/dev/2019/02/17/nfs-read-inconsistencies.html">&lt;p&gt;With two producers e.g. local and remote producers, the changes made locally might need time to be acknowledged by the remote.&lt;/p&gt;

&lt;p&gt;Even without file caching this could still be a problem, I experience this first-hand while using Python. I think Python might use some kind of file attribute to determine file updates. NFS has this which is called “attribute caching”.&lt;/p&gt;

&lt;p&gt;If you mount NFS with the option &lt;code class=&quot;highlighter-rouge&quot;&gt;actimeo&lt;/code&gt;, it enables this attribute caching mechanism. To disable it consider using &lt;code class=&quot;highlighter-rouge&quot;&gt;noac&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;There is a &lt;a href=&quot;https://blogs.sap.com/2015/11/20/performance-impact-of-disabling-nfs-attribute-caching/&quot;&gt;mention&lt;/a&gt; about performance degradation of &lt;code class=&quot;highlighter-rouge&quot;&gt;noac&lt;/code&gt; option. The source suggests that &lt;code class=&quot;highlighter-rouge&quot;&gt;actimeo=0&lt;/code&gt; has lower performance impact comparing to &lt;code class=&quot;highlighter-rouge&quot;&gt;noac&lt;/code&gt; .&lt;/p&gt;

&lt;p&gt;Personally, I see &lt;code class=&quot;highlighter-rouge&quot;&gt;noac&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;actimeo=0&lt;/code&gt; to be too much a drag on performance. I now use &lt;code class=&quot;highlighter-rouge&quot;&gt;actimeo=3&lt;/code&gt; (3 seconds) and see a much lower drag.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://www.digitalocean.com/community/tutorials/how-to-set-up-an-nfs-mount-on-ubuntu-16-04&quot;&gt;Reference&lt;/a&gt; NFS mounting configuration in fstab:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;203.0.113.0:/home       /nfs/home      nfs auto,nofail,noatime,nolock,intr,tcp,actimeo=1800 0 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href=&quot;https://linux.die.net/man/5/nfs&quot;&gt;&lt;strong&gt;NFS client documentation&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;</content><author><name>Konpat Preechakul</name></author><category term="nfs" /><summary type="html">With two producers e.g. local and remote producers, the changes made locally might need time to be acknowledged by the remote.</summary></entry><entry><title type="html">Vim conflicting with VSCode</title><link href="https://blog.konpat.me/dev/2019/02/17/vim-conflicting-ctrl-d-with-vscode.html" rel="alternate" type="text/html" title="Vim conflicting &lt;Ctrl-d&gt; with VSCode" /><published>2019-02-17T00:00:00+07:00</published><updated>2019-02-17T00:00:00+07:00</updated><id>https://blog.konpat.me/dev/2019/02/17/vim-conflicting-ctrl-d-with-vscode</id><content type="html" xml:base="https://blog.konpat.me/dev/2019/02/17/vim-conflicting-ctrl-d-with-vscode.html">&lt;p&gt;VSCode &lt;strong&gt;Vim&lt;/strong&gt; extension binds &lt;code class=&quot;highlighter-rouge&quot;&gt;&amp;lt;Ctrl-d&amp;gt;&lt;/code&gt; for its own use. This keymap is used by VSCode for “selecting next word occurrence” in a multi-cursor fashion. If you like VSCode to handle this keymap (and others of your choice) you could do so via &lt;code class=&quot;highlighter-rouge&quot;&gt;vim.handleKeys&lt;/code&gt; option.&lt;/p&gt;

&lt;p&gt;The following table is copied and pasted from the &lt;a href=&quot;https://github.com/VSCodeVim/Vim#vscodevim-settings&quot;&gt;project&lt;/a&gt;:&lt;/p&gt;

&lt;table&gt;
  &lt;thead&gt;
    &lt;tr&gt;
      &lt;th&gt;Setting&lt;/th&gt;
      &lt;th&gt;Description&lt;/th&gt;
      &lt;th&gt;Type&lt;/th&gt;
      &lt;th&gt;Default Value&lt;/th&gt;
    &lt;/tr&gt;
  &lt;/thead&gt;
  &lt;tbody&gt;
    &lt;tr&gt;
      &lt;td&gt;vim.handleKeys&lt;/td&gt;
      &lt;td&gt;Delegate configured keys to be handled by VSCode instead of by the VSCodeVim extension. Any key in &lt;code class=&quot;highlighter-rouge&quot;&gt;keybindings&lt;/code&gt; section of the &lt;a href=&quot;https://github.com/VSCodeVim/Vim/blob/master/package.json&quot;&gt;package.json&lt;/a&gt; that has a &lt;code class=&quot;highlighter-rouge&quot;&gt;vim.use&amp;lt;C-...&amp;gt;&lt;/code&gt; in the when argument can be delegated back to VS Code by setting &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;&amp;lt;C-...&amp;gt;&quot;: false&lt;/code&gt;. Example: to use &lt;code class=&quot;highlighter-rouge&quot;&gt;ctrl+f&lt;/code&gt; for find (native VS Code behaviour): &lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;vim.handleKeys&quot;: { &quot;&amp;lt;C-f&amp;gt;&quot;: false }&lt;/code&gt;.&lt;/td&gt;
      &lt;td&gt;String&lt;/td&gt;
      &lt;td&gt;&lt;code class=&quot;highlighter-rouge&quot;&gt;&quot;&amp;lt;C-d&amp;gt;&quot;: true&lt;/code&gt;&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;Using the &lt;code class=&quot;highlighter-rouge&quot;&gt;vim.handleKeys&lt;/code&gt; option you could delegate the handles to VSCode by setting each to &lt;code class=&quot;highlighter-rouge&quot;&gt;false&lt;/code&gt; like so:&lt;/p&gt;

&lt;div class=&quot;language-json highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s2&quot;&gt;&quot;vim.handleKeys&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
    &lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&quot;&amp;lt;C-d&amp;gt;&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;&lt;span class=&quot;w&quot;&gt; &lt;/span&gt;&lt;span class=&quot;kc&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;w&quot;&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;</content><author><name>Konpat Preechakul</name></author><category term="vscode" /><summary type="html">VSCode Vim extension binds &amp;lt;Ctrl-d&amp;gt; for its own use. This keymap is used by VSCode for “selecting next word occurrence” in a multi-cursor fashion. If you like VSCode to handle this keymap (and others of your choice) you could do so via vim.handleKeys option.</summary></entry><entry><title type="html">Vim navigation between wrapped Lines in VSCode</title><link href="https://blog.konpat.me/dev/2019/02/17/vim-navigation-within-wrapped-lines-in-vscode.html" rel="alternate" type="text/html" title="Vim navigation between wrapped Lines in VSCode" /><published>2019-02-17T00:00:00+07:00</published><updated>2019-02-17T00:00:00+07:00</updated><id>https://blog.konpat.me/dev/2019/02/17/vim-navigation-within-wrapped-lines-in-vscode</id><content type="html" xml:base="https://blog.konpat.me/dev/2019/02/17/vim-navigation-within-wrapped-lines-in-vscode.html">&lt;p&gt;Noticing that long lines might be soft-wrapped automatically, and navigating with &lt;code class=&quot;highlighter-rouge&quot;&gt;j&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;k&lt;/code&gt; would result in jumping across many soft-wrapped lines (but it is in fact a single line). VIM uses &lt;code class=&quot;highlighter-rouge&quot;&gt;g j&lt;/code&gt; and &lt;code class=&quot;highlighter-rouge&quot;&gt;g k&lt;/code&gt; to navigate within the lines instead.&lt;/p&gt;

&lt;p&gt;If you want &lt;code class=&quot;highlighter-rouge&quot;&gt;j&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;k&lt;/code&gt; to be your default navigating keys through the block, one possible way is to remap it to &lt;code class=&quot;highlighter-rouge&quot;&gt;g j&lt;/code&gt; &lt;code class=&quot;highlighter-rouge&quot;&gt;g k&lt;/code&gt; instead. As mentioned in this &lt;a href=&quot;https://stackoverflow.com/questions/46433500/vs-code-navigate-within-a-wrapped-line-vs-jumping-to-next-line&quot;&gt;Stackoverflow thread&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The key mapping for Vim extension for VSCode is done thus:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&quot;vim.normalModeKeyBindingsNonRecursive&quot;: [
    {
        &quot;before&quot;: [
            &quot;j&quot;
        ],
        &quot;after&quot;: [
            &quot;g&quot;,
            &quot;j&quot;
        ]
    },
    {
        &quot;before&quot;: [
            &quot;k&quot;
        ],
        &quot;after&quot;: [
            &quot;g&quot;,
            &quot;k&quot;
        ]
    }
],
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Put it in your &lt;code class=&quot;highlighter-rouge&quot;&gt;settings.json&lt;/code&gt; .&lt;/p&gt;</content><author><name>Konpat Preechakul</name></author><category term="vscode" /><summary type="html">Noticing that long lines might be soft-wrapped automatically, and navigating with j k would result in jumping across many soft-wrapped lines (but it is in fact a single line). VIM uses g j and g k to navigate within the lines instead.</summary></entry><entry><title type="html">Off-policy Importance Sampling</title><link href="https://blog.konpat.me/academic/2019/02/02/off-policy-importance-sampling.html" rel="alternate" type="text/html" title="Off-policy Importance Sampling" /><published>2019-02-02T00:00:00+07:00</published><updated>2019-02-02T00:00:00+07:00</updated><id>https://blog.konpat.me/academic/2019/02/02/off-policy-importance-sampling</id><content type="html" xml:base="https://blog.konpat.me/academic/2019/02/02/off-policy-importance-sampling.html">&lt;p&gt;ขั้นตอนในการเรียนรู้ policy ที่ดีใน reinforcement learning นั้น มักจะประกอบไปด้วยสองส่วน หนึ่ง คือส่วนที่เรียกว่า &lt;strong&gt;prediction&lt;/strong&gt; ก็คือส่วนที่ตอบว่า “ถ้าเราเดินไปตามเส้นทางนี้ แล้วจะดีขนาดไหน” นั่นก็คือ “คาดการณ์” (prediction) ค่าของ &lt;script type=&quot;math/tex&quot;&gt;v_\pi&lt;/script&gt; และหรือ &lt;script type=&quot;math/tex&quot;&gt;q_\pi​&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;อีกส่วนหนึ่งก็คือส่วนที่เรียกว่า &lt;strong&gt;control&lt;/strong&gt; ถ้าเรามีข้อมูลเหล่านี้ (&lt;script type=&quot;math/tex&quot;&gt;v_\pi, q_\pi&lt;/script&gt;) หรือไม่มี จะสามารถหา policy ที่ดีได้อย่างไร ในกรณีของ &lt;a href=&quot;http://www.incompleteideas.net/book/ebook/node46.html&quot;&gt;GPI (Generalized Policy Iteration)&lt;/a&gt; นั้น control (การหา policy ที่ดี) นั้นอาศัยการ prediction ที่ดีมาก่อนด้วย นั่นทำให้ในหลาย ๆ ครั้งเราถือว่า prediction กับ control เหมือนกับสองส่วนที่ขาดจากกันไม่ได้&lt;/p&gt;

&lt;p&gt;ในที่นี้เราพูดถึงโจทย์ prediction เป็นหลัก โดยเฉพาะเราพูดถึงการ predict ค่า &lt;script type=&quot;math/tex&quot;&gt;q_\pi&lt;/script&gt; โดยที่เราไม่มีประสบการณ์จากการเล่น policy &lt;script type=&quot;math/tex&quot;&gt;\pi&lt;/script&gt; เลย  แต่เราได้ประสบการณ์จากาแหล่งอื่น ๆ แทน เราเรียกแหล่งนั้นว่า &lt;strong&gt;behavioral policy&lt;/strong&gt; หรือ &lt;script type=&quot;math/tex&quot;&gt;b&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;จะเป็นไปได้ไหม หรือต้องทำอย่างไรเราถึงจะได้ &lt;script type=&quot;math/tex&quot;&gt;v_\pi&lt;/script&gt; ในเมื่อเรามีแต่ประสบการณ์จาก &lt;script type=&quot;math/tex&quot;&gt;b​&lt;/script&gt;?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;โจทย์นี้มีชื่ออย่างเป็นทางการว่า &lt;strong&gt;Off-policy prediction&lt;/strong&gt; ก็เพราะว่าประสบการณ์ที่เรามีมัน off ไปจาก policy &lt;script type=&quot;math/tex&quot;&gt;\pi&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;ก่อนที่จะไปต่อ กล่าวก่อนว่า off-policy prediction นั้นก็ไม่ได้มีสูตรสำเร็จ แต่ละวิธีก็อาจจะมีจุดแข็งจุดอ่อนของตัวเอง (เหมือนกับทุกอย่างใน RL) แต่เนื่องจาก off-policy prediction นั้นยากกว่า on-policy prediction (กรณีที่ไม่มี &lt;script type=&quot;math/tex&quot;&gt;b​&lt;/script&gt;) มาก ดังนั้นงานวิจัยในด้านนี้ก็ยังไม่เจริญเท่า&lt;/p&gt;

&lt;p&gt;เพราะฉะนั้นในบทความนี้เราก็อาจจะพูดแบบเกริ่น ๆ วิธีที่มีมานานแล้วของการทำ off-policy prediction ไปก่อนซึ่งในที่นี้เราจะเสนอไอเดียที่เรียกว่า Importance Sampling ซึ่งเป็นเทคนิคทางสถิติ ซึ่งเข้าใจได้ง่ายแม้จะไม่ได้เข้าใจ RL มากเท่าไหร่&lt;/p&gt;

&lt;h2 id=&quot;on-policy-prediction&quot;&gt;On-policy prediction&lt;/h2&gt;

&lt;p&gt;ในกรณีที่ &lt;script type=&quot;math/tex&quot;&gt;\pi&lt;/script&gt; คือ &lt;script type=&quot;math/tex&quot;&gt;b&lt;/script&gt; กล่าวคือ &lt;script type=&quot;math/tex&quot;&gt;\pi(a \vert s) = b(a \vert s)&lt;/script&gt; สำหรับทุก ​&lt;script type=&quot;math/tex&quot;&gt;a, s&lt;/script&gt; เราจะได้ว่า เราสามารถแก้โจทย์ prediction ด้วยวิธีการแบบ Monte Carlo นั่นก็คือ&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\mathrm{E}_{r_{t+1}, r_{t+2}, ... \sim \pi} \left[ r_{t+1} + r_{t+2} + ... \right] = v_\pi&lt;/script&gt;

&lt;p&gt;แปลเป็นภาษาไทยก็คือ เราสามารถหาค่า &lt;script type=&quot;math/tex&quot;&gt;v_\pi&lt;/script&gt; ได้ (prediction) ด้วยการใช้ประสบการณ์จำนวนมากมาหาค่า “คาดหวัง” โดยมีเงื่อนไขว่าประสบการณ์จะต้องมาจาก policy &lt;script type=&quot;math/tex&quot;&gt;\pi&lt;/script&gt; เท่านั้น&lt;/p&gt;

&lt;p&gt;ข้อสังเกต: เราทำการ sample &lt;script type=&quot;math/tex&quot;&gt;r&lt;/script&gt; หลายครั้งจนกว่าจะจบ episode&lt;/p&gt;

&lt;p&gt;เพื่อความง่ายเราจะกำหนด &lt;script type=&quot;math/tex&quot;&gt;G_t = r_{t+1} + r_{t+2} + ...​&lt;/script&gt; โดยเราเรียก &lt;script type=&quot;math/tex&quot;&gt;G_t​&lt;/script&gt; ว่า return อาจจะแปลได้ว่า ค่าทดลองการเล่น (จากการเล่น 1 ครั้งจนจบ แล้วรวมรางวัลที่ได้ทั้งหมด)&lt;/p&gt;

&lt;p&gt;โจทย์ในที่นี้สำหรับ off-policy prediction ก็น่าจะเป็น ถ้าเราไม่ได้ &lt;script type=&quot;math/tex&quot;&gt;r_{t+1}, r_{t+2}, ... \sim \pi​&lt;/script&gt; แต่มาจาก &lt;script type=&quot;math/tex&quot;&gt;b​&lt;/script&gt; แทน เป็นไปได้มั้ยที่เราจะยังประมาณค่า &lt;script type=&quot;math/tex&quot;&gt;v_\pi​&lt;/script&gt; ได้เหมือนเดิม&lt;/p&gt;

&lt;h2 id=&quot;off-policy-prediction-โดยใช้-importance-sampling&quot;&gt;Off-policy prediction โดยใช้ Importance Sampling&lt;/h2&gt;

&lt;p&gt;Importance Sampling เป็นวิธีทางสถิติ โดยสามารถแสดงให้เห็นแบบง่าย ๆ ได้ดังนี้&lt;/p&gt;

&lt;p&gt;สมมติว่าเรามีฟังก์ชัน &lt;script type=&quot;math/tex&quot;&gt;f(x)​&lt;/script&gt; เรามีฟังก์ชันความน่าจะเป็น &lt;script type=&quot;math/tex&quot;&gt;p(x)​&lt;/script&gt; และเราต้องการหา “ค่าคาดหวังของ &lt;script type=&quot;math/tex&quot;&gt;f(x)​&lt;/script&gt; ภายใต้ &lt;script type=&quot;math/tex&quot;&gt;p(x)​&lt;/script&gt;” เราจะได้ว่า&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\mathrm{E}_{x \sim p(x)} f(x)&lt;/script&gt;

&lt;p&gt;แต่ว่าถ้าเราไม่ได้ sample &lt;script type=&quot;math/tex&quot;&gt;x​&lt;/script&gt; จาก &lt;script type=&quot;math/tex&quot;&gt;p(x)​&lt;/script&gt; แต่เป็น &lt;script type=&quot;math/tex&quot;&gt;g(x)​&lt;/script&gt; แทนล่ะ ? เราก็ยังหาค่าคาดหวังได้อยู่ดีแหละดังนี้&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{split}
\mathrm{E}_{x \sim p(x)} f(x) &amp;= \sum_x p(x) f(x) \\
&amp;= \sum_x \frac{g(x)}{g(x)} p(x) f(x) \\
&amp;= \sum_x g(x) \frac{p(x)}{g(x)} f(x) \\
&amp;= \mathrm{E}_{x \sim g(x)} \frac{p(x)}{g(x)} f(x) 
\end{split}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;การคูณ &lt;script type=&quot;math/tex&quot;&gt;\frac{g(x)}{g(x)}​&lt;/script&gt; เป็นทริกที่ไม่ได้เปลี่ยนค่าแต่ใด เพราะว่าคูณด้วย &lt;script type=&quot;math/tex&quot;&gt;1​&lt;/script&gt; แต่ว่าช่วยให้เราสามารถเปลี่ยนการ sample ได้ แทนที่จะต้อง sample จาก &lt;script type=&quot;math/tex&quot;&gt;p(x)​&lt;/script&gt; กลายเป็น sample จาก &lt;script type=&quot;math/tex&quot;&gt;g(x)​&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;เราจะได้ว่า หากทุกครั้งที่เรา sample &lt;script type=&quot;math/tex&quot;&gt;x \sim g(x)&lt;/script&gt; แล้วแทนที่จะใช้ค่า &lt;script type=&quot;math/tex&quot;&gt;f(x)&lt;/script&gt; ตรง ๆ เลยเราเอาค่านั้นมาคูณด้วย &lt;script type=&quot;math/tex&quot;&gt;\frac{p(x)}{g(x)}&lt;/script&gt; (เรียกว่า &lt;strong&gt;Importance sampling ratio&lt;/strong&gt;) ก่อน นั่นคือ &lt;script type=&quot;math/tex&quot;&gt;\frac{p(x)}{g(x)} f(x)&lt;/script&gt; เราก็จะได้ค่าคาดหวังอันเดิมได้นั่นเอง แต่นั่นก็แปลว่าเราต้องรู้ด้วยว่า &lt;script type=&quot;math/tex&quot;&gt;g(x)&lt;/script&gt; ของเรานั้นมีค่าเท่าไหร่&lt;/p&gt;

&lt;h3 id=&quot;การใช้งานกับ-reinforcement-learning&quot;&gt;การใช้งานกับ Reinforcement Learning&lt;/h3&gt;

&lt;p&gt;เราจะเริ่มจากกรณีของ on-policy prediction ซึ่งก็คือการ sample &lt;script type=&quot;math/tex&quot;&gt;r&lt;/script&gt; จำนวนมากจาก &lt;script type=&quot;math/tex&quot;&gt;\pi&lt;/script&gt; คราวนี้เราต้องเปลี่ยนเป็น sample จาก &lt;script type=&quot;math/tex&quot;&gt;b&lt;/script&gt; แทน&lt;/p&gt;

&lt;p&gt;แต่มันอาจจะง่ายกว่าถ้าเราลองมองแค่ reward เดียวก่อน&lt;/p&gt;

&lt;p&gt;การจะ sample reward แต่ละอันสิ่งที่เราต้องทำก็คือ&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;ทำการ sample action จาก policy &lt;script type=&quot;math/tex&quot;&gt;\pi(a \vert s)​&lt;/script&gt;&lt;/li&gt;
  &lt;li&gt;ทำการ sample reward จาก reward distribution &lt;script type=&quot;math/tex&quot;&gt;p(r \vert s, a)​&lt;/script&gt;&lt;/li&gt;
  &lt;li&gt;ทำการ sample state ต่อไป (ถ้าต้อง sample reward ต่อไป) จาก state transition probability &lt;script type=&quot;math/tex&quot;&gt;p(s' \vert s, a)​&lt;/script&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;สำหรับ reward แรกในที่นี้ &lt;script type=&quot;math/tex&quot;&gt;r_{t+1}&lt;/script&gt; (สมมติว่าเราเริ่มที่ &lt;script type=&quot;math/tex&quot;&gt;t&lt;/script&gt;) จะได้ว่า&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;r_{t+1} \sim \pi(a_t|s_t) p(r_{t+1}|s_t, a_t)&lt;/script&gt;

&lt;p&gt;สำหรับ reward ต่อไป &lt;script type=&quot;math/tex&quot;&gt;r_{t+2}&lt;/script&gt; ก็จะได้&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;r_{t+2} \sim \pi(a_t|s_t) p(s_{t+1}|s_t, a_t) \pi(a_{t+1}|s_{t+1}) p(r_{t+2}|s_{t+1}, a_{t+1})&lt;/script&gt;

&lt;p&gt;หากเราไม่ได้ sample action จาก &lt;script type=&quot;math/tex&quot;&gt;\pi&lt;/script&gt; แต่เป็นจาก &lt;script type=&quot;math/tex&quot;&gt;b&lt;/script&gt; แทน เราจะเขียนใหม่ได้ว่า&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;r_{t+1} \sim b(a_t|s_t) p(r_{t+1}|s_t, a_t)&lt;/script&gt;

&lt;p&gt;และ&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;r_{t+2} \sim b(a_t|s_t) p(s_{t+1}|s_t, a_t) b(a_{t+1}|s_{t+1}) p(r_{t+2}|s_{t+1}, a_{t+1})&lt;/script&gt;

&lt;p&gt;ถ้าเรามองเฉพาะ reward แรก &lt;script type=&quot;math/tex&quot;&gt;r_{t+1}&lt;/script&gt; แล้วลองเปรียบเทียบกับ กรณี &lt;script type=&quot;math/tex&quot;&gt;f(x), p(x), g(x)&lt;/script&gt; เราจะเห็นว่า:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;script type=&quot;math/tex&quot;&gt;\pi(a_t \vert s_t) p(r_{t+1} \vert s_t, a_t)&lt;/script&gt; ราวกับเป็น &lt;script type=&quot;math/tex&quot;&gt;p(x)&lt;/script&gt; แต่เดิม และ&lt;/li&gt;
  &lt;li&gt;&lt;script type=&quot;math/tex&quot;&gt;b(a_t \vert s_t) p(r_{t+1} \vert s_t, a_t)&lt;/script&gt; ก็คือ &lt;script type=&quot;math/tex&quot;&gt;g(x)​&lt;/script&gt; อันใหม่&lt;/li&gt;
  &lt;li&gt;&lt;script type=&quot;math/tex&quot;&gt;r_{t+1}&lt;/script&gt; ก็คือ &lt;script type=&quot;math/tex&quot;&gt;f(x)&lt;/script&gt; ของเรานั่นเอง&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;เมื่อเห็นฉะนี้เราก็สามาถรเขียนได้ว่า Importance sampling ratio ระหว่าง &lt;script type=&quot;math/tex&quot;&gt;\pi&lt;/script&gt; กับ &lt;script type=&quot;math/tex&quot;&gt;b&lt;/script&gt; สำหรับ reward &lt;script type=&quot;math/tex&quot;&gt;r_{t+1}&lt;/script&gt; ก็คือ&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{split}
\rho_{t:t} &amp;= \frac{\pi(a_t|s_t) \cancel{p(r_{t+1}|s_t, a_t)}}{b(a_t|s_t) \cancel{p(r_{t+1}|s_t, a_t)}} \\
&amp;= \frac{\pi(a_t|s_t)}{b(a_t|s_t)}
\end{split}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;ใช้อักษร &lt;script type=&quot;math/tex&quot;&gt;\rho&lt;/script&gt; (โรห์) แทน importance sampling ratio&lt;/p&gt;

&lt;p&gt;ข้อสังเกต: จะเห็นว่าถ้า &lt;script type=&quot;math/tex&quot;&gt;b(a_t \vert s_t)&lt;/script&gt; มีค่าน้อยมาก ๆ อาจจะทำให้ค่า &lt;script type=&quot;math/tex&quot;&gt;\rho​&lt;/script&gt; ระเบิดได้ดังนั้น behavioral policy จะต้องไม่ “คม” เกินไป  กล่าวคือจะต้องให้โอกาสเลือก action ต่าง ๆ ไม่น้อยเกินไปนั่นเอง&lt;/p&gt;

&lt;p&gt;และถ้าเราคิดต่อไปสำหรับกรณี reward ตัวที่สองเราก็จะได้ว่า Importance sampling ratio ระหว่าง &lt;script type=&quot;math/tex&quot;&gt;\pi&lt;/script&gt; กับ &lt;script type=&quot;math/tex&quot;&gt;b&lt;/script&gt; สำหรับ &lt;script type=&quot;math/tex&quot;&gt;r_{t+2}&lt;/script&gt; ก็คือ&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{split}
\rho_{t:t+1} &amp;= \frac{\pi(a_t|s_t) \cancel{p(s_{t+1}|s_t, a_t)} \pi(a_{t+1}|s_{t+1}) \cancel{p(r_{t+2}|s_{t+1}, a_{t+1})}}{b(a_t|s_t) \cancel{p(s_{t+1}|s_t, a_t)} b(a_{t+1}|s_{t+1}) \cancel{p(r_{t+2}|s_{t+1}, a_{t+1})}} \\
&amp;= \frac{\pi(a_t|s_t)\pi(a_{t+1}|s_{t+1})}{b(a_t|s_t)b(a_{t+1}|s_{t+1})}
\end{split}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;&lt;script type=&quot;math/tex&quot;&gt;\rho_{t:t+1}&lt;/script&gt; บอกถึงว่าเรา “คูณกันจาก t ถึง t+1”&lt;/p&gt;

&lt;p&gt;จะเห็นว่าแม้ในตอนคูณกันนั้นจะมีส่วนของ state transition probability และ reward probability สุดท้ายแล้วก็ํจะตัดกันเองอยู่ดี เพราะว่าไม่ว่าจะเป็น &lt;script type=&quot;math/tex&quot;&gt;\pi&lt;/script&gt; หรือ &lt;script type=&quot;math/tex&quot;&gt;b​&lt;/script&gt; ก็ล้วนอยู่ภายใต้ environment (MDP) เดียวกัน ทำเราให้เราสนใจเฉพาะความต่างของทั้งสองก็พอ&lt;/p&gt;

&lt;p&gt;สำหรับกรณี reward อื่น ๆ นั้นเราสามารถเดาไปจากตรงนี้ว่า สำหรับ &lt;script type=&quot;math/tex&quot;&gt;r_T&lt;/script&gt; จะมี importance sampling ratio ของตัวเองเท่ากับ&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{split}
\rho_{t:T-1} 
&amp;= \prod_{k=t}^{T-1} \frac{\pi(a_k|s_k)}{b(a_k|s_k)}
\end{split}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;เอาทุกอย่างมารวมกัน เราจะได้ว่าสำหรับแต่ต้นนั้นในกรณีของ on-policy เรามี&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\mathrm{E}_{r_{t+1}, r_{t+2}, \dots \sim \pi} \left[ r_{t+1} + r_{t+2} + \dots \right] = v_\pi&lt;/script&gt;

&lt;p&gt;ในกรณีของ off-policy เราจะต้องคูณ &lt;script type=&quot;math/tex&quot;&gt;\rho&lt;/script&gt; ของแต่ละ reward ให้ถูกต้อง หน้าแต่ละ reward เพื่อทำให้ได้ค่าเหมือนเดิม&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\mathrm{E}_{r_{t+1}, r_{t+2}, \dots \sim b} \left[ \rho_{t:t}r_{t+1} + \rho_{t:t+1}r_{t+2} + \dots \right] = v_\pi&lt;/script&gt;

&lt;p&gt;จะเห็นว่าเราต้องใช้ แต่ละ &lt;script type=&quot;math/tex&quot;&gt;\rho&lt;/script&gt; สำหรับแต่ละ reward วิธีการนี้จึงมีชื่อว่า &lt;strong&gt;Per-decision Importance Sampling&lt;/strong&gt; ก็เพราะว่าเราสร้าง importance sampling สำหรับแต่ละ decision (แต่ละ action แต่ละ reward) เลย&lt;/p&gt;

&lt;p&gt;ในการ Implement จริง ๆ เราจะต้องเขียนได้ว่า &lt;script type=&quot;math/tex&quot;&gt;v(s)&lt;/script&gt; นั้นหามาจากไหน เราจะเขียนได้ว่า&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\begin{equation}
v(s) = \frac{\sum_{t \in \tau(s)} \sum_{k=t}^{T-1} \rho_{t:k} r_{t+1}}{|\tau(s)|}
\end{equation}&lt;/script&gt;

&lt;p&gt;อาจจะดูเข้าใจยากซักนิด แต่หากแยกเป็นส่วน ๆ จะเห็นว่า&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;script type=&quot;math/tex&quot;&gt;\sum_{k=t}^{T-1} \rho_{t:k} r_{t+1}​&lt;/script&gt; ตรงนี้จริง ๆ แล้วก็คือ ผลรวมของ reward ที่ผ่านการคูณด้วย importance sampling ratio แล้ว&lt;/li&gt;
  &lt;li&gt;ส่วนที่เหลือก็คือการหาค่า “เฉลี่ย” จากหลาย ๆ ครั้งนั่นเอง (เพราะว่าค่าคาดหวังก็คือค่าเฉลี่ย)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;การหาค่าเฉลี่ยในที่นี้ใช้เครื่องหมาย &lt;script type=&quot;math/tex&quot;&gt;\tau(s)​&lt;/script&gt; ช่วย โดยเรากำหนดขึ้นมาที่นี้ว่า &lt;script type=&quot;math/tex&quot;&gt;\tau(s)​&lt;/script&gt; เป็น set ของทุก ๆ timestep ที่ state “ผ่าน” state &lt;script type=&quot;math/tex&quot;&gt;s​&lt;/script&gt; พอดิบพอดี ดังนั้นการหาค่าเฉลี่ยของทุก ๆ ครั้งที่เราวิ่งผ่าน &lt;script type=&quot;math/tex&quot;&gt;s​&lt;/script&gt; ก็คือการหา “ค่าเฉลี่ยของผลรวม reward ทุก ๆ ครั้งที่เริ่มจาก &lt;script type=&quot;math/tex&quot;&gt;s​&lt;/script&gt;” นั่นเอง&lt;/p&gt;

&lt;p&gt;เพิ่มเติม: การกำหนด &lt;script type=&quot;math/tex&quot;&gt;\tau(s)&lt;/script&gt; ว่าเป็น set ของทุก ๆ timestep ที่ผ่าน state &lt;script type=&quot;math/tex&quot;&gt;s&lt;/script&gt; เรียกว่า &lt;strong&gt;every-visit Monte Carlo&lt;/strong&gt; อีกวิธีหนึ่งที่เราทำได้ ก็คือ “สนใจเฉพาะ &lt;script type=&quot;math/tex&quot;&gt;s&lt;/script&gt; แรกของแต่ละ episode เท่านั้น” เราก็จะแก้ความหมาย &lt;script type=&quot;math/tex&quot;&gt;\tau(s)&lt;/script&gt; เล็กน้อย แล้วเรียกว่า &lt;strong&gt;first-visit Monte Carlo&lt;/strong&gt; ความต่างของทั้งสองก็คือ every-visit นั้น implement ง่ายกว่า เพราะเราไม่ต้องจำว่าเราผ่าน state นี้ครั้งแรกหรือเปล่า แต่ว่าอาจจะให้ค่าที่แปลก ๆ เพราะหากเราผ่าน state &lt;script type=&quot;math/tex&quot;&gt;s&lt;/script&gt; หลายครั้งในหนึ่ง episode ค่า &lt;script type=&quot;math/tex&quot;&gt;v(s)​&lt;/script&gt; จะเป็นค่าเฉลี่ยจากทุกครั้งที่เราผ่าน ต่างกับกรณี first-visit ที่จะสนใจเฉพาะค่าแรกเท่านั้น&lt;/p&gt;

&lt;h3 id=&quot;importance-sampling-สำหรับผลรวมทั้งเส้น&quot;&gt;Importance Sampling สำหรับผลรวมทั้งเส้น&lt;/h3&gt;

&lt;p&gt;แต่ว่าก็มีอีกวิธีที่เรามอง “ทุก reward เป็นภาพรวม” กล่าวคือเราไม่แยกมองเป็นทีละชิ้น แต่เรามองทั้งหมดเป็น return &lt;script type=&quot;math/tex&quot;&gt;G_t​&lt;/script&gt; เลย&lt;/p&gt;

&lt;p&gt;กล่าวคือ&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;G_t = r_{t+1} + r_{t+2} + r_{t+3} + \dots \quad \sim \pi&lt;/script&gt;

&lt;p&gt;โดยเราจะหาความน่าจะเป็นที่จะ sample ได้ค่า &lt;script type=&quot;math/tex&quot;&gt;r_{t+1}, r_{t+2}, \dots&lt;/script&gt; พร้อมกันทั้งหมดแทน ซึ่งก็สามารถทำได้ในลักษณะเดียวกัน โดยตรงนี้จะแสดงให้เห็นกรณี reward 2 ตัวแรก&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;r_{t+1}, r_{t+2} \sim \pi(a_t|s_t) p(r_{t+1}|s_t, a_t) p(s_{t+1}|s_t, a_t) \pi(a_{t+1}|s_{t+1}) p(r_{t+2}|s_{t+1}, a_{t+1})&lt;/script&gt;

&lt;p&gt;หลังจากนั้นเราสามารถเขียนสำหรับกรณีทั่วไปได้ดังนี้&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;r_{t+1}, r_{t+2}, \dots, r_{T} \sim \prod_{k=t}^{T-1} \pi(a_k|s_k) p(r_{k+1}|s_k, a_k) p(s_{k+1}|s_k, a_k)
\label{eq:pG}&lt;/script&gt;

&lt;p&gt;จากสมการ &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:pG}&lt;/script&gt; เราสามารถหาค่า Importance sampling ratio ระหว่าง &lt;script type=&quot;math/tex&quot;&gt;\pi&lt;/script&gt; กับ &lt;script type=&quot;math/tex&quot;&gt;b&lt;/script&gt; สำหรับ &lt;script type=&quot;math/tex&quot;&gt;G_t&lt;/script&gt; ได้ดังต่อไปนี้&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{split}
\rho_{t:T-1} &amp;= \prod_{k=t}^{T-1} \frac{\pi(a_k|s_k) \cancel{p(r_{k+1}|s_k, a_k)} \cancel{p(s_{k+1}|s_k, a_k)}}{b(a_k|s_k) \cancel{p(r_{k+1}|s_k, a_k)} \cancel{p(s_{k+1}|s_k, a_k)}} \\
&amp;= \prod_{k=t}^{T-1} \frac{\pi(a_k|s_k)}{b(a_k|s_k)}
\end{split}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;จะเห็นว่าหน้าตาคล้ายเดิมอย่างยิ่ง เพียงแต่ ณ ตอนนี้เราสามารถใช้ ค่า &lt;script type=&quot;math/tex&quot;&gt;\rho_{t:T-1}&lt;/script&gt; คูณเข้าไปยัง &lt;script type=&quot;math/tex&quot;&gt;G_t&lt;/script&gt; ทั้งเส้น เพื่อให้ได้ค่าที่ถูกต้อง แทนที่จะต้องใช้ค่า &lt;script type=&quot;math/tex&quot;&gt;\rho&lt;/script&gt; สำหรับแต่ละ reward&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\begin{equation}
\mathrm{E}_{r_{t+1}, r_{t+2}, \dots \sim b} \left[ \rho_{t:T-1} \sum_t^{T-1} r_{t+1} \right] = v_\pi
\end{equation}&lt;/script&gt;

&lt;p&gt;วิธีนี้เรียกว่า &lt;strong&gt;importance sampling&lt;/strong&gt; แบบปกติ (ทั้งเส้น)&lt;/p&gt;

&lt;p&gt;เราสามารถเขียนนิยามของ &lt;script type=&quot;math/tex&quot;&gt;v(s)&lt;/script&gt; ได้ในลักษณะเดียวกัน ก็คือการเฉลี่ยจากหลาย ๆ ครั้งที่เราผ่าน state &lt;script type=&quot;math/tex&quot;&gt;s&lt;/script&gt; นั้น ๆ&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\begin{equation}
v(s) = \frac{\sum_{t \in \tau(s)} \rho_{t:T-1} G_t}{|\tau(s)|}
\label{eq:ord_is}
\end{equation}&lt;/script&gt;

&lt;h3 id=&quot;เปรียบเทียบ-importance-sampling-และ-per-decision-importance-sampling&quot;&gt;เปรียบเทียบ Importance Sampling และ Per-decision Importance Sampling&lt;/h3&gt;

&lt;p&gt;ปัญหาของ Importance sampling ในภาพรวมก็คือการคูณทบ ๆ กัน ของ &lt;script type=&quot;math/tex&quot;&gt;\frac{\pi}{b}​&lt;/script&gt; ซึ่งมันจะทำให้ค่าที่ได้มีการแกว่งมาก ๆ ก็เพราะว่ามันขึ้นอยู่กับการ sampling ต่อเนื่องเป็นระยะยาว และเอาแต่ละพจน์มาคูณกัน ยิ่งส่งผลให้ช่วงของค่ามากขึ้นไปอีก ทำให้ importance sampling มีปัญหากับขนาดของ variance มีการกล่าวในหนังสือของ (Sutton, 2018) ว่า variance ของ importance sampling นั้นอาจจะถึง &lt;strong&gt;อนันต์&lt;/strong&gt; ซึ่งก็เห็นด้วยได้ง่ายเพราะว่าความยาวของ episode นั้นอาจจะยาวเท่าใดก็ได้&lt;/p&gt;

&lt;p&gt;เพราะฉะนั้นสำหรับงานใดที่ต้องการใช้ importance sampling จำต้องพิเคราะห์ถึงการจำกัด variance ให้ดี โดยวิธีที่จำกัด variance ได้มาก มักก็จะส่งผลให้มีผลดีในการใช้งานจริงด้วย&lt;/p&gt;

&lt;p&gt;เป็นที่ทราบกันว่าหากใช้ importance sampling (แบบทั้งเส้น) โดยตรงนั้น การเทรนจะทำได้ยากอย่างยิ่ง และอาจจะไม่ converge เลยด้วยซ้ำ แต่ว่า per-decision importance sampling ซึ่ง แม้ว่าจะมีพจน์ &lt;script type=&quot;math/tex&quot;&gt;\rho_{t:T-1}&lt;/script&gt; เช่นกัน แต่ว่าก็ส่งผลเพียงต่อ reward ท้าย ๆ ซึ่งก็อาจจะถูกพลังของ discount &lt;script type=&quot;math/tex&quot;&gt;\gamma&lt;/script&gt; ลดความสำคัญลงไปเยอะ ก็จะช่วยทำให้ variance ลดลงได้&lt;/p&gt;

&lt;p&gt;อย่างไรก็ดีในการใช้งานจริงนิยมใช้วิธีที่ “ใกล้เคียง” แต่ไม่ใช่ทั้ง importance sampling หรือ per-decision importance sampling ซึ่งเรียกว่า &lt;strong&gt;weighted importance sampling&lt;/strong&gt; ซึ่งวิธีนี้นั้นจริง ๆ แล้ว “ไม่ให้ค่าที่ถูกต้อง” (มี bias) แต่ว่าสามารถควบคุม variance ได้เป็นอย่างดีจึงทำให้การใช้งานจริงนั้นให้ผลที่ดีกว่ามาก&lt;/p&gt;

&lt;h3 id=&quot;weighted-importance-sampling&quot;&gt;Weighted Importance Sampling&lt;/h3&gt;

&lt;p&gt;การที่เราคูณ &lt;script type=&quot;math/tex&quot;&gt;\prod \frac{\pi}{b}&lt;/script&gt; หลาย ๆ ครั้งส่งผลให้ค่า &lt;script type=&quot;math/tex&quot;&gt;\rho&lt;/script&gt; นี้ แกว่งมาก ๆ และก็แกว่งมากขึ้นเรื่อย ๆ ตามจำนวนการคูณ วิธีหนึ่งที่จะช่วย “จำกัด” การแกว่งก็คือการ “หาร” ด้วยอะไรที่เยอะพอ ๆ กัน&lt;/p&gt;

&lt;p&gt;เราทำการแก้ไขเล็กน้อยจากสมการ &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:ord_is}&lt;/script&gt; โดยการแก้ตัวส่วนให้มีค่าแกว่งไปพร้อม ๆ กับตัวเศษ&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;v(s) = \frac{\sum_{t \in \tau(s)} \rho_{t:T-1} G_t}{\sum_{t \in \tau(s)} \rho_{t:T-1}}
\label{eq:weighted_is}&lt;/script&gt;

&lt;p&gt;สิ่งที่เราเห็นในทันทีก็คือ &lt;script type=&quot;math/tex&quot;&gt;v(s)&lt;/script&gt; ใหม่นี้จะแกว่งน้อยกว่ามากส่งผลให้ variance น้อยลงตามไปด้วย วิธีนี้จึงเหมาะสมมากกว่าในการใช้งานจริง&lt;/p&gt;

&lt;p&gt;สิ่งที่เราเห็นต่อมาก็คือ อยู่ดี ๆ เราจะแก้ตามอำเภอใจแบบนี้ไม่ได้สิ คำตอบแบบสั้น ๆ ก็คือ เรายอม “ผิด” เพราะว่าสมการ &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:weighted_is}&lt;/script&gt; นั้น bias ไม่ได้ให้ค่าที่ถูกต้องโดยเฉลี่ยเหมือนกับ importance sampling ทั่วไป แต่เราก็ยอมจ่ายเพราะว่ามันช่วยให้เราทำงานกับมันได้ง่ายมากขึ้น&lt;/p&gt;

&lt;p&gt;คำถามต่อมาก็คือ แล้วมัน bias ไปขนาดไหนล่ะ? เพราะว่าถ้ามัน bias แบบไม่เห็นเค้าเดิมเลยมันก็ไม่น่าจะดีอยู่แล้ว จริงอย่างว่า เพราะว่า สมการ &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:weighted_is}​&lt;/script&gt; นั้นมี bias ก็จริง แต่ว่าขนาดของ bias นั้น “น้อยลง” เรื่อย ๆ หากเราเฉลี่ยด้วยจำนวนที่มากขึ้น และมัน “เข้าใกล้” ค่าจริงเมื่อเราเฉลี่ยด้วยจำนวนอนันต์ แต่แน่นอนว่าเราไม่ได้เฉลี่ยด้วยจำนวนอนันต์จึงต้องยอมรับว่า มันก็ยัง bias อยู่ดี&lt;/p&gt;

&lt;p&gt;การแสดงว่ามันเข้าใกล้ค่าจริง เมื่อเฉลี่ยด้วยจำนวนอนันต์สามารถทำได้ดังนี้&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;เราอาศัยความจริงที่ว่า &lt;script type=&quot;math/tex&quot;&gt;\mathrm{E}[\rho] = 1​&lt;/script&gt;&lt;/li&gt;
  &lt;li&gt;และเราจะแสดงว่า weighted importance sampling นั้นเข้าใกล้ importance sampling เมื่อ &lt;script type=&quot;math/tex&quot;&gt;\tau(s)&lt;/script&gt; มีขนาดอนันต์&lt;/li&gt;
&lt;/ul&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\begin{equation}
\frac{\sum_{t \in \tau(s)} \rho_{t:T-1}}{\left| \tau(s) \right|} = \mathrm{E}_b \left[ \rho_{t:T-1} \right] = 1
\label{eq:expect_rho_tau}
\end{equation}&lt;/script&gt;

&lt;p&gt;สมการ &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:expect_rho_tau}&lt;/script&gt; จะเป็นจริงก็ด้วย &lt;a href=&quot;http://www.incompleteideas.net/book/ebook/node46.html&quot;&gt;Law of large numbers&lt;/a&gt; เท่านั้น ดังนั้นหาก &lt;script type=&quot;math/tex&quot;&gt;\left \vert  \tau(s) \right \vert&lt;/script&gt; ไม่ได้เยอะเข้าใกล้ &lt;script type=&quot;math/tex&quot;&gt;\infty&lt;/script&gt; แล้วก็พูดอย่างนั้นไม่ได้&lt;/p&gt;

&lt;p&gt;หลังจากนั้นเราก็ทำการย้ายข้างเล็กน้อยดังนี้&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\begin{equation} 
\sum_{t \in \tau(s)} \rho_{t:T-1} = \left| \tau(s) \right| \mathrm{E}_b \left[ \rho_{t:T-1} \right] = \left| \tau(s) \right|
\end{equation}&lt;/script&gt;

&lt;p&gt;นำค่าที่ได้ไปแทนในสมการ &lt;script type=&quot;math/tex&quot;&gt;\eqref{eq:weighted_is}&lt;/script&gt; จะได้ว่า&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{split}
v(s) &amp;= \frac{\sum_{t \in \tau(s)} \rho_{t:T-1} G_t}{\sum_{t \in \tau(s)} \rho_{t:T-1}} \\
&amp;= \frac{\sum_{t \in \tau(s)} \rho_{t:T-1} G_t}{\left|\tau(s)\right|} \\ 
\end{split}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;เราจะเห็นว่าจริง ๆ แล้ว weighted importance sampling กับ importance sampling ธรรมดานั้นมีค่าเท่ากันเมื่อ &lt;script type=&quot;math/tex&quot;&gt;\vert \tau(s) \vert&lt;/script&gt; เป็นอนันต์ (ใหญ่พอ)&lt;/p&gt;

&lt;p&gt;หมายเหตุ: การจะทำแบบเดียวกันนี้กับ per-decision importance sampling นั้นไม่ตรงไปตรงมาเท่าใดนักก็เพราะว่า &lt;script type=&quot;math/tex&quot;&gt;\rho​&lt;/script&gt; ของแต่ละ reward ไม่เหมือนกัน ทำให้พูดได้ยากว่าอะไรคือ weight ที่เหมาะสมกันแน่ อย่างไรก็ดีมีงานที่เสนอการทำ weighted per-decision importance sampling ชื่อว่า &lt;a href=&quot;https://scholarworks.umass.edu/cgi/viewcontent.cgi?article=1079&amp;amp;context=cs_faculty_pubs&quot;&gt;Eligibility Traces for Off-Policy Policy Evaluation (2000)&lt;/a&gt;&lt;/p&gt;

&lt;h4 id=&quot;แสดงว่า-mathrmerho--1&quot;&gt;แสดงว่า &lt;script type=&quot;math/tex&quot;&gt;\mathrm{E}[\rho] = 1&lt;/script&gt;&lt;/h4&gt;

&lt;p&gt;เพื่อให้เห็นภาพจะแสดงให้ดูในกรณีของ &lt;script type=&quot;math/tex&quot;&gt;r_{t+1}, r_{t+2}​&lt;/script&gt; อย่างละเอียดเพื่อให้เห็นภาพชัดเจน&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;\rho_{t:t+1} = \frac{\pi(a_t|s_t)\pi(a_{t+1}|s_{t+1})}{b(a_t|s_t)b(a_{t+1}|s_{t+1})}&lt;/script&gt;

&lt;p&gt;ลองหาค่าคาดหวังของ &lt;script type=&quot;math/tex&quot;&gt;\rho&lt;/script&gt; ภายใต้ behavioral policy &lt;script type=&quot;math/tex&quot;&gt;b&lt;/script&gt;&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;% &lt;![CDATA[
\begin{equation}
\begin{split}
\mathrm{E}_{a_t, a_{t+1} \sim b} \left[ \frac{\pi(a_t|s_t)\pi(a_{t+1}|s_{t+1})}{b(a_t|s_t)b(a_{t+1}|s_{t+1})} \right]
&amp;= \sum_{a_t} b(a_t|s_t) \sum_{a_{t+1}} b(a_{t+1}|s_{t+1}) \frac{\pi(a_t|s_t)\pi(a_{t+1}|s_{t+1})}{b(a_t|s_t)b(a_{t+1}|s_{t+1})} \\
&amp;= \sum_{a_t} \cancel{b(a_t|s_t)} \frac{\pi(a_t|s_t)}{\cancel{b(a_t|s_t)}} 
\sum_{a_{t+1}} \cancel{b(a_{t+1}|s_{t+1})} \frac{\pi(a_{t+1}|s_{t+1})}{\cancel{b(a_{t+1}|s_{t+1})}} \\
&amp;= \sum_{a_t} \pi(a_t|s_t) \sum_{a_{t+1}} \pi(a_{t+1}|s_{t+1}) \\
&amp;= \sum_{a_t} \pi(a_t|s_t) 1 \\
&amp;=  1
\end{split}
\end{equation} %]]&gt;&lt;/script&gt;

&lt;p&gt;จะเห็นว่าจริง ๆ แล้วเนื่องจากระหว่าง &lt;script type=&quot;math/tex&quot;&gt;a_t&lt;/script&gt; กับ &lt;script type=&quot;math/tex&quot;&gt;a_{t+1}&lt;/script&gt; นั้นไม่เกี่ยวข้องกัน (เมื่อกำหนด &lt;script type=&quot;math/tex&quot;&gt;s&lt;/script&gt; ให้) ดังนั้นจึงราวกับว่าแต่ละ term ที่คูณกันใน &lt;script type=&quot;math/tex&quot;&gt;\rho&lt;/script&gt; สามารถแยกกันคิดได้ ซึ่งก็ส่งผลให้ค่าคาดหวังทั้งหมดกลายเป็น 1 เพราะว่าแต่ละส่วนเป็น 1 นั่นเอง&lt;/p&gt;

&lt;h3 id=&quot;การใช้งานกับ-n-step-td&quot;&gt;การใช้งานกับ n-step TD&lt;/h3&gt;

&lt;p&gt;โดยปกติ TD หรือ Temporal Difference จะใช้ตัวอย่าง reward เพียง 1 ตัวอย่างเพื่ออัพเดทค่าประมาณ &lt;script type=&quot;math/tex&quot;&gt;v&lt;/script&gt; หรือ &lt;script type=&quot;math/tex&quot;&gt;q&lt;/script&gt; เป็นที่ทราบกันดีว่า TD นั้นอยู่ฝั่งตรงข้ามกับ Monte Carlo ในมุมของ variance และ bias กล่าวคือ&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;TD มี bias มาก มี variance น้อย&lt;/li&gt;
  &lt;li&gt;Monte Carlo ไม่มี bias แต่มี variance มาก&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;n-step TD คือความพยายามหา “จุดกึ่งกลาง” ระหว่าง 2 วิธีการนี้ แทนที่จะใช้ reward เพียงอันเดียวแบบ TD ดังนี้&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;G_{t:t+1} = r_{t+1} + \gamma v(s_{t+1})&lt;/script&gt;

&lt;p&gt;เราจะใช้ reward หลาย ๆ ตัว ยกตัวอย่างเช่น 2 ตัว ดังต่อไปนี้&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;G_{t:t+2} = r_{t+1} + \gamma r_{t+2} + \gamma^2 v(s_{t+2})&lt;/script&gt;

&lt;p&gt;เราก็สามารถเดาได้ว่า &lt;script type=&quot;math/tex&quot;&gt;G_{t:t+n}&lt;/script&gt; จะมีหน้าตาเป็นอย่างไร&lt;/p&gt;

&lt;p&gt;n-step TD คือการใช้ &lt;script type=&quot;math/tex&quot;&gt;G_{t:t+n}&lt;/script&gt; มาแทนที่ของ &lt;script type=&quot;math/tex&quot;&gt;G_{t:t+1}&lt;/script&gt; เราจะได้ว่าหน้าตาของ &lt;strong&gt;n-step SARSA&lt;/strong&gt; เป็นดังนี้&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;q(s_t,a_t) \leftarrow q(s_t, a_t) + \alpha \left[ G_{t:t+n} - q(s_t, a_t) \right]&lt;/script&gt;

&lt;p&gt;จะเห็นว่า &lt;script type=&quot;math/tex&quot;&gt;G_{t:t+n}&lt;/script&gt; ต้องการ &lt;script type=&quot;math/tex&quot;&gt;v&lt;/script&gt; แต่ในกรณีที่เรามีเฉพาะค่า &lt;script type=&quot;math/tex&quot;&gt;q&lt;/script&gt; เราจะสามารถหาค่า &lt;script type=&quot;math/tex&quot;&gt;G_{t:t+n}&lt;/script&gt; ได้ดังนี้&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;G_{t:t+n} = \left( \sum_{i=0}^{n-1} \gamma^i r_{t+i+1} \right) + \gamma^n \mathrm{E}_{a \sim \pi} \left[ q(s_{t+n}, a) \right]&lt;/script&gt;

&lt;p&gt;หากเราใช้การ sampling สำหรับประมาณ &lt;script type=&quot;math/tex&quot;&gt;v&lt;/script&gt; ดังด้านบน เราจะเรียกว่า SARSA เฉย ๆ แต่ว่าถ้าเราใช้การหาค่าเฉลี่ยแบบเป๊ะ ๆ ดังต่อไปนี้&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;G_{t:t+n} = \left( \sum_{i=0}^{n-1} \gamma^i r_{t+i+1} \right) + \gamma^n \sum_a \pi(a|s_{t+n}) q(s_{t+n}, a)&lt;/script&gt;

&lt;p&gt;เราเรียกวิธีการนี้ว่า &lt;strong&gt;n-step expected SARSA&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;ซึ่งเวลาที่เรามาใช้กับ off-policy importance sampling สิ่งที่เราต้องสนใจก็คือ “สำหรับแต่ละ term มีการ sampling action หรือเปล่า?” เพราะว่าเราต้องคูณ &lt;script type=&quot;math/tex&quot;&gt;\rho&lt;/script&gt; ทุกที่ที่มีการ sampling action&lt;/p&gt;

&lt;p&gt;จะเห็นว่าในกรณีของ n-step SARSA เรามีการสุ่ม n-1 ครั้งสำหรับ n reward แรก ที่เป็น n-1 ก็เพราะว่า SARSA เป็นฟังก์ชัน &lt;script type=&quot;math/tex&quot;&gt;q(s,a)&lt;/script&gt; ดังนั้น action แรกไม่ได้เกิดจากการสุ่ม และรวมกับอีก 1 ครั้งตอนสุ่มหาค่า &lt;script type=&quot;math/tex&quot;&gt;v&lt;/script&gt;&lt;/p&gt;

&lt;p&gt;จึงได้ว่าสำหรับ n-step SARSA เราจะเขียนแบบ off-policy ได้ดังนี้&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;G_{t:t+n} = \left( \sum_{i=0}^{n-1} \rho_{t:t+i} \gamma^i r_{t+i+1} \right) + \rho_{t:t+n} \gamma^n \mathrm{E}_{a \sim \pi} \left[ q(s_{t+n}, a) \right]&lt;/script&gt;

&lt;p&gt;สำหรับ n-step expected SARSA เรามีการ n-1 ครั้งสำหรับ n reward แรก เหมือนกัน แต่ว่าเราไม่ได้สุ่มอีกเลยตอนหาค่า v เพราะเราหาค่าแบบเป๊ะ ๆ จึงได้ว่าสำหรับ n-step expected SARSA เราสามารถเขียน off-policy ได้ดังนี้&lt;/p&gt;

&lt;script type=&quot;math/tex; mode=display&quot;&gt;G_{t:t+n} = \left( \sum_{i=0}^{n-1} \rho_{t:t+i} \gamma^i r_{t+i+1} \right) + \rho_{t:t+n-1} \gamma^n \sum_a \pi(a|s_{t+n}) q(s_{t+n}, a)&lt;/script&gt;

&lt;p&gt;หมายเหตุ: เราสามารถใช้ได้ทั้ง importance sampling หรือ per-decision importance sampling หรือ weighted importance sampling เพียงแค่แก้ค่า &lt;script type=&quot;math/tex&quot;&gt;G_{t:t+n}&lt;/script&gt; ให้เหมาะสม&lt;/p&gt;

&lt;h3 id=&quot;การใช้งานกับ-experience-replay&quot;&gt;การใช้งานกับ Experience Replay&lt;/h3&gt;

&lt;p&gt;สำหรับอัลกอริทึมที่ใช้ข้อมูลแบบ off-policy เรามักจะใช้งาน experience replay เนื่องจากเราสามารถใช้ขอมูลเก่า ๆ ได้ (ต่างจาก on-policy ที่ต้องการประสบการณ์สดใหม่เท่านั้น จึงไม่นิยมใช้ experience replay)&lt;/p&gt;

&lt;p&gt;หมายเหตุ: กรณีของ DQN และ Q-learning โดยทั่วไปไม่ต้องทำการคูณด้วย importance sampling ratio เนื่องจากสมการของ Q-learning ไม่ได้สนใจว่าประสบการณ์นั้นมาจาก policy ใด จึงเรียกว่า Q-learning เป็น off-policy โดยกำเนิด แต่นี่ไม่เป็นจริงสำหรับการใช้ n-step Q-learning (และ n-step algorithm ในภาพรวม)&lt;/p&gt;

&lt;p&gt;เนื่องจากการใช้งาน importance sampling เราจำเป็นต้องรู้ว่า policy ที่ใช้เก็บข้อมูลนั้นมีหน้าตาเป็นอย่างไร กล่าวคือ &lt;script type=&quot;math/tex&quot;&gt;b(a \vert s)&lt;/script&gt; มีค่าเท่าไหร่ เพราะว่าต้องเอาไปเป็นตัวหาร ดังนั้น นอกจากจะต้องเก็บข้อมูลอย่าง state, action, reward ใน experience replay แล้ว ก็ยังจะต้องเก็บด้วยว่า ณ ตอนที่เก็บข้อมูลนี้นั้น &lt;script type=&quot;math/tex&quot;&gt;b(a \vert s)&lt;/script&gt; มีค่าเท่าไหร่&lt;/p&gt;

&lt;h1 id=&quot;อ้างอิง&quot;&gt;อ้างอิง&lt;/h1&gt;

&lt;p&gt;Sutton, R. S., &amp;amp; Barto, A. G. (2018). Reinforcement learning: An introduction. MIT press. https://doi.org/10.1016/S1364-6613(99)01331-5&lt;/p&gt;

&lt;p&gt;Hernandez-Garcia, J. F., &amp;amp; Sutton, R. S. (2019). Understanding Multi-Step Deep Reinforcement Learning: A Systematic Study of the DQN Target. Retrieved from http://arxiv.org/abs/1901.07510&lt;/p&gt;

&lt;p&gt;Amherst, S., Precup, D., Sutton, R. S., &amp;amp; Singh, S. (2000). Eligibility Traces for Off-Policy Policy Evaluation (Vol. 80).&lt;/p&gt;</content><author><name>Konpat Preechakul</name></author><category term="rl" /><category term="thai" /><summary type="html">ขั้นตอนในการเรียนรู้ policy ที่ดีใน reinforcement learning นั้น มักจะประกอบไปด้วยสองส่วน หนึ่ง คือส่วนที่เรียกว่า prediction ก็คือส่วนที่ตอบว่า “ถ้าเราเดินไปตามเส้นทางนี้ แล้วจะดีขนาดไหน” นั่นก็คือ “คาดการณ์” (prediction) ค่าของ และหรือ</summary></entry><entry><title type="html">Academic Machine Learning Development Process</title><link href="https://blog.konpat.me/academic/2019/01/23/academic-machine-learning-development-process.html" rel="alternate" type="text/html" title="Academic Machine Learning Development Process" /><published>2019-01-23T00:00:00+07:00</published><updated>2019-01-23T00:00:00+07:00</updated><id>https://blog.konpat.me/academic/2019/01/23/academic-machine-learning-development-process</id><content type="html" xml:base="https://blog.konpat.me/academic/2019/01/23/academic-machine-learning-development-process.html">&lt;p&gt;&lt;strong&gt;Update (3 May 2019)&lt;/strong&gt;: This is outdated. VSCode team just released a set of extensions which works better in this scenario. Please visit &lt;a href=&quot;https://code.visualstudio.com/blogs/2019/05/02/remote-development&quot;&gt;https://code.visualstudio.com/blogs/2019/05/02/remote-development&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Machine learning projects nowadays cannot easily fit into a laptop. While we optimize laptop for maximum portability, it does not usually come with a powerful GPU. The conventional wisdom is that we buy our own machine learning rig with powerful enough GPU(s). This now splits our development machine, where we actually writing codes, and the running machine, where we have all the libraries and resources. Of course, In this scenario, we don’t include the GPU farm, if you have any, in that case other layer of considerations must be in place.&lt;/p&gt;

&lt;p&gt;Splitting developing machine and running machine give rise to a lot of headaches because the latency of the task is generally very low, iterations are fast. How could we manage to do this? Worse yet, usually during coding we want to have access to all development tools including but not limited to code suggestion and auto-completion. If all the libraries reside in the running machine, how could we have a precise code suggestion then?&lt;/p&gt;

&lt;p&gt;I think &lt;strong&gt;&lt;a href=&quot;https://github.com/jupyterlab/jupyterlab&quot;&gt;Jupyterlab&lt;/a&gt;&lt;/strong&gt; (and all other IDEs with client side UI) try to solve the right problem, it is really a problem developers haven’t seen conventionally, it is just beginning to emerge and our tools are not capable of it yet. Jupyterlab is quite limited by itself. The project began as a language agnostic platform, it does not provide any language specific code suggestion and completion. This task should be done via extensions according to the project philosophy. The problem is rather the project is still very young and there is no such extension. This renders the tools only good enough for small code bases where the interactivity which is the main-selling point of this tool outshines its flaws.&lt;/p&gt;

&lt;p&gt;We now move on to see other candidates where the core resides on the running machine but has a client-side UI. The solution I have found is quite unexpected, it is &lt;a href=&quot;https://code.visualstudio.com/&quot;&gt;&lt;strong&gt;Visual Studio Code&lt;/strong&gt;&lt;/a&gt;. I don’t think Code is designed to be a server side IDE at all (only recently it seems to have enough requests to do so), but since the introduction of its feature &lt;a href=&quot;https://code.visualstudio.com/blogs/2017/11/15/live-share&quot;&gt;&lt;strong&gt;Live share&lt;/strong&gt;&lt;/a&gt;, it now has the capability to do so.&lt;/p&gt;

&lt;p&gt;Live share solves our problem in a sense that we can remote to our running machine and edit the code there while maintaining laptop portability. If all operations are done in the server side e.g. file operations, debugging, versioning, leaving only the visuals and controls to be transmitted through the wire, the cost of being remote should be rather small since these operations are not latency sensitive. If the dynamics of GUI is known in the client side, there should be no delay between typing and presenting the characters typed.&lt;/p&gt;

&lt;p&gt;Live share is still beta though and only recently it has met the usable quality. It still has a long way to go i.e. versioning is not fully supported from the client but we still can use a separate terminal to do that, not that hard.&lt;/p&gt;

&lt;p&gt;To run live share we need to run Code, and to run Code we need a desktop environment. The fact that Code does not support headless mode is still a caveat to use this solution, but for me this is rather slim since I could just install a &lt;strong&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Virtual_Network_Computing&quot;&gt;VNC&lt;/a&gt;&lt;/strong&gt; server of some kind (I personally use &lt;strong&gt;&lt;a href=&quot;https://code.visualstudio.com/blogs/2017/11/15/live-share&quot;&gt;TurboVNC&lt;/a&gt;&lt;/strong&gt;) and run the Code from there.&lt;/p&gt;

&lt;p&gt;Visual Studio Code now seems to focus on machine learning community as well, you can see with its powerful &lt;strong&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=ms-python.python&quot;&gt;Python&lt;/a&gt;&lt;/strong&gt; extension, and also its &lt;strong&gt;&lt;a href=&quot;https://marketplace.visualstudio.com/items?itemName=VisualStudioExptTeam.vscodeintellicode&quot;&gt;Intellicode&lt;/a&gt;&lt;/strong&gt; extension which supports many deep learning frameworks.&lt;/p&gt;</content><author><name>Konpat Preechakul</name></author><category term="academic" /><category term="ml" /><category term="vscode" /><summary type="html">Update (3 May 2019): This is outdated. VSCode team just released a set of extensions which works better in this scenario. Please visit https://code.visualstudio.com/blogs/2019/05/02/remote-development.</summary></entry><entry><title type="html">Moving to Jekyll</title><link href="https://blog.konpat.me/me/2019/01/23/moving-to-jekyll.html" rel="alternate" type="text/html" title="Moving to Jekyll" /><published>2019-01-23T00:00:00+07:00</published><updated>2019-01-23T00:00:00+07:00</updated><id>https://blog.konpat.me/me/2019/01/23/moving-to-jekyll</id><content type="html" xml:base="https://blog.konpat.me/me/2019/01/23/moving-to-jekyll.html">&lt;p&gt;It has been more than a year without an update to the blog. It is because I quitted being a developer, and becoming a machine learning researcher. The blog, which has initially been conceived for jotting down my development struggles, seems unfit for my new direction.&lt;/p&gt;

&lt;p&gt;Now I aim to revive the blog somehow with a new goal under new requirements. The contents before were about coding snippets, but now I have to look from an academic perspective. My blog may need to support more for equations. I take this opportunity as a fresh start to try out &lt;strong&gt;Jekyll&lt;/strong&gt;, a static-file blog platform.&lt;/p&gt;

&lt;p&gt;Currently, I have migrated contents from the old blog to here.&lt;/p&gt;</content><author><name>Konpat Preechakul</name></author><summary type="html">It has been more than a year without an update to the blog. It is because I quitted being a developer, and becoming a machine learning researcher. The blog, which has initially been conceived for jotting down my development struggles, seems unfit for my new direction.</summary></entry><entry><title type="html">Install Canon MP280 Driver on Ubuntu 18.04</title><link href="https://blog.konpat.me/dev/2018/07/10/install-canon-mp280-driver-on-ubuntu-18-04.html" rel="alternate" type="text/html" title="Install Canon MP280 Driver on Ubuntu 18.04" /><published>2018-07-10T00:00:00+07:00</published><updated>2018-07-10T00:00:00+07:00</updated><id>https://blog.konpat.me/dev/2018/07/10/install-canon-mp280-driver-on-ubuntu-18-04</id><content type="html" xml:base="https://blog.konpat.me/dev/2018/07/10/install-canon-mp280-driver-on-ubuntu-18-04.html">&lt;p&gt;You need &lt;strong&gt;libtiff4&lt;/strong&gt; which cannot be installed via apt from &lt;a href=&quot;https://mun-steiner.de/wordpress/index.php/linux/scannen-und-drucken/canon-software-pixma-mg5250/libtiff4-erforderlich/&quot;&gt;here &lt;/a&gt;(direct link: &lt;a href=&quot;http://old-releases.ubuntu.com/ubuntu/pool/universe/t/tiff3/libtiff4_3.9.7-2ubuntu1_amd64.deb&quot;&gt;http://old-releases.ubuntu.com/ubuntu/pool/universe/t/tiff3/libtiff4_3.9.7-2ubuntu1_amd64.deb&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Install the libtiff4 package:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dpkg -i libtiff4_3.9.7-2ubuntu1_amd64.deb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You also need &lt;strong&gt;libpng12–0&lt;/strong&gt; which will not be found in the apt-get from &lt;a href=&quot;https://packages.ubuntu.com/xenial/amd64/libpng12-0/download&quot;&gt;here&lt;/a&gt;(direct link: &lt;a href=&quot;http://mirrors.kernel.org/ubuntu/pool/main/libp/libpng/libpng12-0_1.2.54-1ubuntu1_amd64.deb&quot;&gt;http://mirrors.kernel.org/ubuntu/pool/main/libp/libpng/libpng12-0_1.2.54-1ubuntu1_amd64.deb&lt;/a&gt;)&lt;/p&gt;

&lt;p&gt;Install the libpng12–0 package:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dpkg -i libpng12-0_1.2.54-1ubuntu1_amd64.deb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Now, install the dependencies of the driver:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;apt install libatk1.0-0 libgtk2.0-0 libpango1.0-0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;You can download the driver from &lt;a href=&quot;http://support-in.canon-asia.com/contents/IN/EN/0100301402.html&quot;&gt;http://support-in.canon-asia.com/contents/IN/EN/0100301402.html&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;After extracting the archive, you will see:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;packages
resources
install.sh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Just go to the packages directly, you will see:&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;cnijfilter-common_3.40-1_amd64.deb
cnijfilter-common_3.40-1_i386.deb
cnijfilter-mp280series_3.40-1_amd64.deb
cnijfilter-mp280series_3.40-1_i386.deb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;I will assume that you use &lt;strong&gt;amd64&lt;/strong&gt; architecture. Go ahead install both of the &lt;strong&gt;common&lt;/strong&gt; and the &lt;strong&gt;mp280series&lt;/strong&gt; packages.&lt;/p&gt;

&lt;div class=&quot;highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;dpkg -i cnijfilter-common_3.40-1_amd64.deb
dpkg -i cnijfilter-mp280series_3.40-1_amd64.deb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;That should be all!&lt;/p&gt;</content><author><name>Konpat Preechakul</name></author><category term="ubuntu" /><summary type="html">You need libtiff4 which cannot be installed via apt from here (direct link: http://old-releases.ubuntu.com/ubuntu/pool/universe/t/tiff3/libtiff4_3.9.7-2ubuntu1_amd64.deb)</summary></entry></feed>