<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/scripts/pretty-feed-v3.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:h="http://www.w3.org/TR/html4/"><channel><title>Lingyun&apos;s website</title><description>Looking back on this life, I have no regrets towards the world.</description><link>https://avidjoycexu.github.io</link><item><title>【Display Troubleshooting】</title><link>https://avidjoycexu.github.io/blog/display</link><guid isPermaLink="true">https://avidjoycexu.github.io/blog/display</guid><description>Tailscale for connecting remote servers and RDP for  forwarding rendered views</description><pubDate>Tue, 23 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;https://askubuntu.com/questions/432255/what-is-the-display-environment-variable&lt;/p&gt;</content:encoded><h:img src="/_astro/cover.BJ0GF7iZ.png"/><enclosure url="/_astro/cover.BJ0GF7iZ.png"/></item><item><title>【Computer Network Troubleshooting II: Tailscale】</title><link>https://avidjoycexu.github.io/blog/network2</link><guid isPermaLink="true">https://avidjoycexu.github.io/blog/network2</guid><description>Tailscale for connecting remote servers and RDP for  forwarding rendered views</description><pubDate>Tue, 23 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;ul&gt;
&lt;li&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;https://unix.stackexchange.com/questions/523152/xrdp-disconnects-immediately-after-connection-from-windows10-centos-to-centos7#&lt;/p&gt;
&lt;p&gt;https://www.cnblogs.com/dwj192/p/15685314.html&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;~/.xsession
/etc/xrdp/startwm.sh
/etc/xrdp/xrdp.ini

sudo systemctl restart xrdp
journalctl -u xrdp -e
journalctl -u xrdp-sesman -e
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;报错&lt;/h1&gt;
&lt;h2&gt;&lt;code&gt;xrdp&lt;/code&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;9月 25 22:00:37 ubuntu xrdp[507325]: **[ERROR] xrdp_sec_recv: xrdp_mcs_recv failed**

9月 25 22:00:37 ubuntu xrdp[507325]: **[ERROR] xrdp_rdp_recv: xrdp_sec_recv failed**

9月 25 22:00:37 ubuntu xrdp[507325]: **[ERROR] libxrdp_process_data: xrdp_rdp_recv failed**

9月 25 22:00:37 ubuntu xrdp[507325]: **[ERROR] xrdp_process_data_in: xrdp_process_loop failed**

9月 25 22:00:37 ubuntu xrdp[507325]: **[ERROR] SSL_shutdown: Failure in SSL library (protocol error?)**

9月 25 22:00:37 ubuntu xrdp[507325]: **[ERROR] SSL: error:0A000126:SSL routines::unexpected eof while reading**
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;&lt;code&gt;xrdp-sesman&lt;/code&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-shell&quot;&gt;9月 25 15:55:19 ubuntu xrdp-sesman[491872]: **[ERROR] sesman_data_in: scp_process_msg failed**

9月 25 15:55:19 ubuntu xrdp-sesman[491872]: **[ERROR] sesman_main_loop: trans_check_wait_objs failed, removing trans**
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;display&lt;/h1&gt;
&lt;pre&gt;&lt;code&gt; 1063  **ps** -ef | grep Xorg
&lt;/code&gt;&lt;/pre&gt;</content:encoded><h:img src="/_astro/cover.BJ0GF7iZ.png"/><enclosure url="/_astro/cover.BJ0GF7iZ.png"/></item><item><title>【Network Troubleshooting I: VPN &amp; Internet Access】</title><link>https://avidjoycexu.github.io/blog/network1</link><guid isPermaLink="true">https://avidjoycexu.github.io/blog/network1</guid><description>VPN for internet access</description><pubDate>Tue, 23 Sep 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h1&gt;Debugging VPN and Network Connectivity on Campus WiFi&lt;/h1&gt;
&lt;h2&gt;Intro&lt;/h2&gt;
&lt;p&gt;It is common to encounter stubborn network issues when setting up a new computer or switching to a new Internet environment. For me, the case is &lt;strong&gt;returning from CMU to PKU&lt;/strong&gt;: my VPN that previously worked flawlessly suddenly refused to connect when I joined &lt;strong&gt;PKU Secure&lt;/strong&gt;, the campus WiFi.&lt;/p&gt;
&lt;p&gt;This blog documents my debugging journey, where the culprit turned out to be a gateway problem, and along the way introduces a set of standard tools for &lt;strong&gt;network debugging on macOS and Linux systems&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Mistakes are bound to happen, so if you spot anything inaccurate, please feel free to reach out via email or comments.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Problem: VPN Fails on Campus WIFI&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;My VPN connects perfectly over a &lt;strong&gt;mobile hotspot&lt;/strong&gt;, but fails on &lt;strong&gt;PKU Secure&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;The key difference:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Hotspot uses public IPv4 addresses.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;PKU Secure assigns addresses in a &lt;strong&gt;special subnet (10.x.x.x)&lt;/strong&gt; with stricter campus-side firewall rules.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Analysis&lt;/strong&gt;&lt;br&gt;
Two potential causes stand out:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Local restrictions&lt;/strong&gt; — my computer’s firewall could be blocking routes to these private subnets.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Campus network policies&lt;/strong&gt; — PKU Secure itself may prohibit certain types of forwarding or tunneling.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;To untangle these, I turned to a set of well-known command-line tools.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;Tools and Commands&lt;/h2&gt;
&lt;h3&gt;1. Routing and Gateway Inspection — &lt;code&gt;netstat&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;netstat -rn
netstat -rn | grep -i default
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Shows the routing table.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Look for the &lt;strong&gt;default gateway&lt;/strong&gt;: if you don’t see one pointing to the campus network, your packets won’t make it past the first hop.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;2. Firewall Rules — &lt;code&gt;pfctl&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo pfctl -sr    # Show current firewall rules
sudo pfctl -d     # Temporarily disable packet filter
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;macOS uses &lt;code&gt;pf&lt;/code&gt; as its built-in firewall.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Checking rules helps confirm whether connections to 10.x subnets are being silently dropped.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;3. DNS Resolution — &lt;code&gt;dig&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;dig +short jt6t2204.epicgames.ink
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Resolves domain names to IPs.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;This step ensures the problem isn’t with &lt;strong&gt;name resolution&lt;/strong&gt;, but rather with &lt;strong&gt;routing&lt;/strong&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;4. Path Testing — &lt;code&gt;traceroute&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;traceroute -n &amp;#x3C;target-server&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Shows the hops between your computer and the target server.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;In my case, the traceroute &lt;strong&gt;couldn’t make a second hop&lt;/strong&gt; because I wasn’t connected to the campus gateway at all.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Note that some intermediate hops, especially on &lt;strong&gt;.edu networks&lt;/strong&gt;, may deliberately block ICMP or UDP trace packets. Seeing &lt;code&gt;* * *&lt;/code&gt; for a hop therefore &lt;strong&gt;does not necessarily mean&lt;/strong&gt; the forward path is broken; it may only mean that that router declined to respond to the trace probes.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;How &lt;code&gt;traceroute&lt;/code&gt; ends: it stops when the destination returns an ICMP &lt;strong&gt;Port Unreachable&lt;/strong&gt; (i.e., the probe reached the host) or when the probe TTL reaches the configured maximum number of hops (the default is usually 30). It does &lt;strong&gt;not&lt;/strong&gt; run forever — if intermediate hops never respond you will see repeated &lt;code&gt;* * *&lt;/code&gt; lines up to the max-hops limit, and then &lt;code&gt;traceroute&lt;/code&gt; exits.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;5. Network Service State — &lt;code&gt;networksetup&lt;/code&gt; &amp;#x26; &lt;code&gt;scutil&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;networksetup -listallnetworkservices
scutil --nwi
sudo scutil --nc list
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;networksetup&lt;/code&gt;: Lists all network interfaces (WiFi, Ethernet, VPN).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;scutil&lt;/code&gt;: Reveals &lt;strong&gt;per-service connectivity&lt;/strong&gt; and VPN states.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;6. System Profiles and Extensions&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo profiles -L
systemextensionsctl list
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;Useful for checking whether enterprise profiles or third-party system extensions are enforcing policies on your Mac.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;7. Interface Inspection — &lt;code&gt;ifconfig&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;ifconfig -a | grep utun
ifconfig utun0
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;VPN tunnels usually appear as &lt;strong&gt;&lt;code&gt;utun&lt;/code&gt; interfaces&lt;/strong&gt; on macOS.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Checking them confirms whether the VPN connection was established at all.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;8. Connectivity Testing — &lt;code&gt;curl&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;curl --interface en0 -4 www.baidu.com
curl -4 www.baidu.com
curl -6 www.baidu.com
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Forces traffic over specific interfaces (&lt;code&gt;en0&lt;/code&gt; for WiFi).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Helps compare IPv4 vs IPv6 connectivity.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;9. Open Sockets — &lt;code&gt;lsof&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;sudo lsof | grep -i utun
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Lists processes bound to VPN interfaces.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Useful for verifying whether your VPN client is holding a proper tunnel.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;Takeaway&lt;/h2&gt;
&lt;p&gt;The real culprit was simple yet fundamental: &lt;strong&gt;my machine wasn’t connected to the gateway of PKU Secure at all&lt;/strong&gt;, so packets couldn’t escape beyond the first hop.&lt;/p&gt;
&lt;p&gt;In practice, network debugging often requires peeling away multiple layers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Routing tables&lt;/strong&gt; tell you where packets &lt;em&gt;should&lt;/em&gt; go.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Traceroute&lt;/strong&gt; shows whether they &lt;em&gt;actually&lt;/em&gt; go there.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Firewalls and profiles&lt;/strong&gt; reveal hidden restrictions.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And when in doubt, test with &lt;strong&gt;both IPv4 and IPv6&lt;/strong&gt;, as campus networks sometimes block or misconfigure one of them.&lt;/p&gt;</content:encoded><h:img src="/_astro/cover.BJ0GF7iZ.png"/><enclosure url="/_astro/cover.BJ0GF7iZ.png"/></item><item><title>【Generative Model】Look-into Video-Prediction-Policy codebase</title><link>https://avidjoycexu.github.io/blog/vpo</link><guid isPermaLink="true">https://avidjoycexu.github.io/blog/vpo</guid><description>Understand VPO implementation on github</description><pubDate>Fri, 09 May 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Credits&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;link: &lt;a href=&quot;https://github.com/roboterax/video-prediction-policy&quot;&gt;VPO repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;@article{hu2024video,
  title={Video Prediction Policy: A Generalist Robot Policy with Predictive Visual Representations},
  author={Hu, Yucheng and Guo, Yanjiang and Wang, Pengchao and Chen, Xiaoyu and Wang, Yen-Jen and Zhang, Jianke and Sreenath, Koushil and Lu, Chaochao and Chen, Jianyu},
  journal={arXiv preprint arXiv:2412.14803},
  year={2024}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Training&lt;/h2&gt;
&lt;h3&gt;text conditioning in SVP with CLIP&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;CLIP:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;tokenize&lt;/li&gt;
&lt;li&gt;call the encoder&lt;/li&gt;
&lt;li&gt;add positional encodings&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;concat with the image embeddings&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;details in &lt;code&gt;def encode_text(...)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;Feature Extractions in SVP&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;The UNet processes video frames through multiple layers&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Overall&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;in &lt;code&gt;policy_models.VPP_policy&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class VPP_Policy(...):
	def __init__(...):
		# img encoder
		self.TVP_encoder = Diffusion_feature_extractor(pipeline=pipeline,
			tokenizer=tokenizer,	
			text_encoder=text_encoder,
			position_encoding = self.use_position_encoding)
		# goal encoder
		self.language_goal = LangClip(model_name=&apos;ViT-B/32&apos;).to(self.device)
		...

	def extract_predictive_featue(self, dataset_batch):
		...
		latent_goal = self.language_goal(dataset_batch[&quot;lang&quot;])

		with torch.no_grad():
			input_rgb = torch.cat([rgb_static, rgb_gripper], dim=0)
			language = language + language
			perceptual_features = self.TVP_encoder(input_rgb, language, self.timestep, self.extract_layer_idx, all_layer=self.use_all_layer, step_time=1, max_length=self.max_length)

			perceptual_features = self.Video_Former(perceptual_features)
	
			...
			return predictive_feature, latent_goal

	def training_step(self, dataset_batch):
		predictive_feature, latent_goal = self.extract_predictive_feature(dataset_batch)

		act_loss, _, _ = self.diffusion_loss(
			predictive_feature. 
			latent_goal,
			dataset_batch[&quot;actions&quot;],
		)
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;details in SVP&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;features are &lt;strong&gt;extracted at specific layers&lt;/strong&gt; (controlled by &lt;code&gt;extract_layer_idx&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class VPP_Policy(pl.LightningModule):
    def __init__(
        self,
        latent_dim: int = 512,
        use_Former: str = &apos;3d&apos;,
        extract_layer_idx: int = 1,  # Controls which layer to extract features from
        use_all_layer: bool = False,  # Option to use all layers
        action_dim: int = 7,
        action_seq_len: int = 10,
    ):
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;in &lt;code&gt;policy_models.module.diffusion_extract&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class Diffusion_feature_extractor(nn.Module):
	def forward(
		self,...
		extract_layer_idx,...
	)
		...
		for i, t in enumerate(timesteps):
			...
			feature_pred = self.step_unet(
				...
				use_layer_idx=extract_layer_idx
			)[0]
			...
		return feature_pred
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;cross-attention and self-attention on features in VideoFormer&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;These features capture both spatial and temporal information&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;if use 3d, &lt;code&gt;self.Video_Former = Video_Former_3D(...)&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class Video_Former_3D(nn.Module):
    def __init__(
        self,
        dim: int,
        depth: int,
        condition_dim: int = 1280,
        dim_head: int = 64,
        heads: int = 8,
        num_latents: int = 64,
        num_frame: int = 16,
        num_time_embeds: int = 4,
        use_temporal: bool = False,
    ):
        # ...
        self.layers = nn.ModuleList([])
        if self.use_temporal:
            for _ in range(depth):
                self.layers.append(
                    nn.ModuleList([
                        PerceiverAttentionLayer(dim=dim, dim_head=dim_head, heads=heads),
                        Attention(dim, num_heads=heads, qkv_bias=True, use_cross_attn=False,
                                y_dim=512, attn_mask=attn_mask),
                        feed_forward_layer(dim=dim, mult=ff_mult, activation=activation),
                    ])
                )

	def forward(x_f, mask): # x_f: input visual embedding
		# 1. Mask the position embeddings for the padded frames
		...
		# 2. Apply the position embeddings
		...
		x_f = x_f + time_pos_emb

		# 3. Apply attention and feed-forward layer
		for attn, temp_attn, ffw in self.layers:
			x = x + attn(x_f, x)
			x = rearrange(x, &apos;(b T) q d -&gt; (b q) T d&apos;, b = batch_size)
			x = x + Temp_attn(x)
			x = rearrange(x, &apos;(b q) T d -&gt; (b T) q d&apos;, b = batch_size)
			x = x + ffw(x)

		x = x.reshape(batch_size, -1 ,x.shape[1],x.shape[2])
		x = rearrange(x, &apos;b T q d -&gt; b (T q) d&apos;)
		norm = self.norm(x)

		return norm
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class PerceiverAttentionLayer(nn.Module):
	def forward(self, features, latents):
		# Layer normalization
		x = self.norm_media(features)
		latents = self.norm_latents(latents)

		# Cross-attention
		q = self.to_q(latents)
		kv_input = toch.cat((x, latents), dim=-2)
		k = self.to_k(kv_input)
		v = self.to_v(kv_input)

		# attention scores
		sim = eimsum(&apos;b h q d, b h f d -&gt; b h q f&apos;, q, k)
		alphas = sim.softmax(dim=-1)

		out = einsum(&apos;b h q f, b h f v -&gt; b h q v&apos;, alphas, v)
		out = rearrange(out, &apos;b h q v -&gt; b q (h v)&apos;)

		return self.to_out(out)
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class Attention(...):
	def forward(self, x):
		# Perform self-attention
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;diffusion loss in DiT&lt;/h3&gt;
&lt;h4&gt;diffusion loss&lt;/h4&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class VPP_Policy(...):
	def diffusion_loss(
		self, 
		perceptual_emb,
		latent_goal,
		actions
	):
		sigmas = self.male_sample_density()(shape=(len(actions),))
		noise = torch.rand_like(actions)
		loss = self.model.loss(perceptual_emb, actions, latent_goal, noise, sigmas)
		return loss, sigmas, noise
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;self.model = GCDenoiser()&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h4&gt;score matching loss&lt;/h4&gt;
&lt;blockquote&gt;
&lt;p&gt;The loss effectively implements score matching, where the model learns to predict the score (gradient of log probability) of the data distribution.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class GCDenoiser(nn.Module):
	def loss(self, state, action, goal, noise, sigma, **kwargs):
		c_skip, c_out, c_in = [append_dims(x, action.ndim) for x in self.get_scalings(sigma)]
		noised_input = action + noise * append_dims(sigma, action.ndim)
		model_output = self.inner_model(state, noised_input * c_in, goal, sigma, **kwargs)
		target = (action - c_skip * noised_input) / c_out # NOTE: target score
		return (model_output - target).pow(2).flatten(1).mean(), model_output
&lt;/code&gt;&lt;/pre&gt;
&lt;h4&gt;&lt;code&gt;inner_model&lt;/code&gt; architecture&lt;/h4&gt;
&lt;p&gt;Inputs:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;States (visual observations)&lt;/li&gt;
&lt;li&gt;Goals (language instructions)&lt;/li&gt;
&lt;li&gt;Actions (current actions)&lt;/li&gt;
&lt;li&gt;Sigma (noise level)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Process:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Encode context:
States + Goals → Encoder → Context&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Decode actions:
Actions + Context + Sigma → Decoder → Predicted Actions&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class GCDenoiser(nn.Module):
	def _init__(...):
		self.inner_model = DiffusionTransformer(
			action_dim = action_dim,
			obs_dim = obs_dim,
			goal_dim = goal_dim,
			proprio_dim= proprio_dim,
			goal_conditioned = True,
			...
		)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;in &lt;code&gt;policy_models.module.diffusion_decoder&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class DiffusionTransformer(nn.Module):
	def __init__(...):
		self.encoder = TransformerEncoder(...)
		self.decoder = TransformerFiLMDecoder(...)
		self.proprio_emb = nn.Sequential(
			nn.Linear(...)
			nn.Mish(),
			nn.Linear(...)
		)
		self.sigma_emb = ...
		self.action_emb = nn.Linear(...)
	def forward(self, states, actions, goals, signa, uncond: Optional[bool]):
		# actions: actually noises (or noised_input for training)
		context = self.forward_enc_only(states, actions, goals, sigma, uncond)
		pred_actoins = self.forward_dec_only(context, actions, sigma)
		return pred_actions
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Inference&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;class VPP_Policy: 
	def eval_forward(self, obs, goals)
	act_seq = self.denoise_actions(
		torch.zeros_like(latent_goal).to(latent_goal.device),
		perceptual_emb,
		latent_goal,
		inference=True,
	)
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;denoise_actions&lt;/code&gt; depend on the specific samplers&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;TODO: look into the different samplers&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</content:encoded><h:img src="/_astro/cover.BTAAy7gE.png"/><enclosure url="/_astro/cover.BTAAy7gE.png"/></item><item><title>【Learning VLA】Understand π0 codebase framework【I】</title><link>https://avidjoycexu.github.io/blog/pi-0</link><guid isPermaLink="true">https://avidjoycexu.github.io/blog/pi-0</guid><description>Understand π0 implementation on github</description><pubDate>Mon, 05 May 2025 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Model architecture overview&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Vision-Language Backbone&lt;/strong&gt;: Based on PaliGemma, a pre-trained VLM that processes visual inputs and language instructions. This backbone leverages 400M images from SigLIP pre-training and 2.6B tokens from the Gemma language model.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Action Expert&lt;/strong&gt;: A specialized module that translates the visual and language representations into robot actions. This component is trained on approximately 300M parameters and uses flow matching to generate continuous action distributions appropriate for robotic control.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;VLM initialization&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;llm = nnx_bridge.ToNNX(
    _gemma.Module(
        configs=[paligemma_config, action_expert_config],
        embed_dtype=config.dtype,
    )
)
img = nnx_bridge.ToNNX(
    _siglip.Module(
        num_classes=paligemma_config.width,
        variant=&quot;So400m/14&quot;,
        pool_type=&quot;none&quot;,
        scan=True,
        dtype_mm=config.dtype,
    )
)
self.PaliGemma = nnx.Dict(llm=llm, img=img)
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Token calculation&lt;/h3&gt;
&lt;h3&gt;prefix embedding&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;visual &amp;#x26; language inputs&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def embed_prefix(self, obs: _model.Observation):
    # Embed images
    for name in obs.images:
        image_tokens, _ = self.PaliGemma.img(obs.images[name], train=False)
        tokens.append(image_tokens)
        # ... handle masks and attention
    
    # Add language inputs
    if obs.tokenized_prompt is not None:
        tokenized_inputs = self.PaliGemma.llm(obs.tokenized_prompt, method=&quot;embed&quot;)
        tokens.append(tokenized_inputs)
        # ... handle masks and attention
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;suffix embedding&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;action &amp;#x26; state information&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;projection network initialization&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;self.state_proj = nnx.Linear(config.action_dim, action_expert_config.width, rngs=rngs)

self.action_in_proj = nnx.Linear(config.action_dim, action_expert_config.width, rngs=rngs)

self.action_time_mlp_in = nnx.Linear(2 * action_expert_config.width, action_expert_config.width, rngs=rngs)

self.action_time_mlp_out = nnx.Linear(action_expert_config.width, action_expert_config.width, rngs=rngs)

self.action_out_proj = nnx.Linear(action_expert_config.width, config.action_dim, rngs=rngs)
&lt;/code&gt;&lt;/pre&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;calculate embedding&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;@at.typecheck
def embed_suffix(
    self, obs: _model.Observation, noisy_actions: _model.Actions, timestep: at.Float[at.Array, &quot; b&quot;]
) -&gt; tuple[at.Float[at.Array, &quot;b s emb&quot;], at.Bool[at.Array, &quot;b s&quot;], at.Bool[at.Array, &quot; s&quot;]]:
    input_mask = []
    ar_mask = []
    tokens = []
    
    # 1. Project state to token space
    state_token = self.state_proj(obs.state)[:, None, :]
    tokens.append(state_token)
    input_mask.append(jnp.ones((obs.state.shape[0], 1), dtype=jnp.bool_))
    ar_mask += [True]  # State token can&apos;t attend to previous tokens

    # 2. Project actions to token space
    action_tokens = self.action_in_proj(noisy_actions)
    
    # 3. Create time embeddings using sine-cosine positional encoding
    time_emb = posemb_sincos(timestep, self.action_in_proj.out_features, min_period=4e-3, max_period=4.0)
    time_tokens = einops.repeat(time_emb, &quot;b emb -&gt; b s emb&quot;, s=self.action_horizon)
    
    # 4. Mix action and time information
    action_time_tokens = jnp.concatenate([action_tokens, time_tokens], axis=-1)
    action_time_tokens = self.action_time_mlp_in(action_time_tokens)
    action_time_tokens = nnx.swish(action_time_tokens)
    action_time_tokens = self.action_time_mlp_out(action_time_tokens)
    
    tokens.append(action_time_tokens)
    input_mask.append(jnp.ones(action_time_tokens.shape[:2], dtype=jnp.bool_))
    ar_mask += [True] + ([False] * (self.action_horizon - 1))
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Flow Matching&lt;/h2&gt;
&lt;h3&gt;Inference&lt;/h3&gt;
&lt;h4&gt;sample actions&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;flow matching&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;given t=1, apply velocity to noise, until t=0&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;code reading&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;def step(carry)&lt;/code&gt;: given the current ($x_t$, time), determine the next ($x_t$, time)&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;use KV caching to process the prefix only once&lt;/p&gt;
&lt;/blockquote&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;@override
def sample_actions(
	self, 
	rng, 
	observation,
	*,
	num_steps
) -&gt; _model.Actions:
    observation = _model.preprocess_observation(None, observation, train=False)
    # note that we use the convention more common in diffusion literature, where t=1 is noise and t=0 is the target
    # distribution. yes, this is the opposite of the pi0 paper, and I&apos;m sorry.
    dt = -1.0 / num_steps
    batch_size = observation.state.shape[0]
    noise = jax.random.normal(rng, (batch_size, self.action_horizon, self.action_dim))

    # first fill KV cache with a forward pass of the prefix
    prefix_tokens, prefix_mask, prefix_ar_mask = self.embed_prefix(observation)
    prefix_attn_mask = make_attn_mask(prefix_mask, prefix_ar_mask)
    positions = jnp.cumsum(prefix_mask, axis=1) - 1
    _, kv_cache = self.PaliGemma.llm([prefix_tokens, None], mask=prefix_attn_mask, positions=positions)

    def step(carry):
        x_t, time = carry
        suffix_tokens, suffix_mask, suffix_ar_mask = self.embed_suffix(
            observation, x_t, jnp.broadcast_to(time, batch_size)
        )
        # `suffix_attn_mask` is shape (b, suffix_len, suffix_len) indicating how the suffix tokens can attend to each other
        suffix_attn_mask = make_attn_mask(suffix_mask, suffix_ar_mask)
        # `prefix_attn_mask` is shape (b, suffix_len, prefix_len) indicating how the suffix tokens can attend to the prefix tokens
        prefix_attn_mask = einops.repeat(prefix_mask, &quot;b p -&gt; b s p&quot;, s=suffix_tokens.shape[1])
        # `combined_mask` is shape (b, suffix_len, prefix_len + suffix_len) indicating how the suffix tokens (which generate the queries) can attend to the full prefix + suffix sequence (which generates the keys and values)
        full_attn_mask = jnp.concatenate([prefix_attn_mask, suffix_attn_mask], axis=-1)
        assert full_attn_mask.shape == (
            batch_size,
            suffix_tokens.shape[1],
            prefix_tokens.shape[1] + suffix_tokens.shape[1],
        )
        # `positions` is shape (b, suffix_len) indicating the positions of the suffix tokens
        positions = jnp.sum(prefix_mask, axis=-1)[:, None] + jnp.cumsum(suffix_mask, axis=-1) - 1

        (prefix_out, suffix_out), _ = self.PaliGemma.llm(
            [None, suffix_tokens], mask=full_attn_mask, positions=positions, kv_cache=kv_cache
        )
        assert prefix_out is None
        v_t = self.action_out_proj(suffix_out[:, -self.action_horizon :])

        return x_t + dt * v_t, time + dt

    def cond(carry):
        x_t, time = carry
        # robust to floating-point error
        return time &gt;= -dt / 2

    x_0, _ = jax.lax.while_loop(cond, step, (noise, 1.0))
    return x_0
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;Training&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;flow matching loss&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;generate random noise&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;sample time points from &lt;strong&gt;beta distribution&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;interpolate between noise and gt actions -&gt; $x_t$&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;$x_t$: action of the current timestep;
the model takes $x_t$ as input&lt;/p&gt;
&lt;/blockquote&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;
&lt;p&gt;calculate gt velocity&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;get model predictions&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;project model output to velocity space&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;compute MSE loss between predicted and gt velocity&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;def compute_loss(self, rng, observation, actions, *, train=False):
    # Generate noise and time samples
    noise = jax.random.normal(noise_rng, actions.shape)
    time = jax.random.beta(time_rng, 1.5, 1, batch_shape) * 0.999 + 0.001
    
    # Interpolate between noise and actions
    time_expanded = time[..., None, None]
    x_t = time_expanded * noise + (1 - time_expanded) * actions
    u_t = noise - actions
    
    # Process through model
    prefix_tokens, prefix_mask, prefix_ar_mask = self.embed_prefix(observation)
    suffix_tokens, suffix_mask, suffix_ar_mask = self.embed_suffix(observation, x_t, time)
    
    # Compute attention and get model output
    attn_mask = make_attn_mask(input_mask, ar_mask)
    positions = jnp.cumsum(input_mask, axis=1) - 1
    (prefix_out, suffix_out), _ = self.PaliGemma.llm(
        [prefix_tokens, suffix_tokens], mask=attn_mask, positions=positions
    )
    v_t = self.action_out_proj(suffix_out[:, -self.action_horizon:])
    
    # Compute MSE loss between predicted and target velocity
    return jnp.mean(jnp.square(v_t - u_t), axis=-1)
&lt;/code&gt;&lt;/pre&gt;</content:encoded><h:img src="/_astro/cover.HMmDGB7w.png"/><enclosure url="/_astro/cover.HMmDGB7w.png"/></item></channel></rss>