Seaborn无Matplotlib添加多行绘图及Metropolis-Hastings代码无输出问题
Hey there! Let's break down why your code isn't producing plots and how to fix it, plus implement multi-line plotting using just Seaborn (no direct Matplotlib plt calls beyond the minimal display trigger, which Seaborn wraps anyway).
First: Finish the Metropolis-Hastings Function
Your metropolis_hastings function is incomplete—you need to actually implement the sampling logic to generate the data we'll plot. Here's the full, working version:
import numpy as np import scipy.stats as st import seaborn as sns import pandas as pd # For easier data handling with Seaborn mus = np.array([5, 5]) sigmas = np.array([[1, .9], [.9, 1]]) def circle(x, y): return (x-1)**2 + (y-2)**2 - 3**2 def pgauss(x, y): return st.multivariate_normal.pdf([x, y], mean=mus, cov=sigmas) def metropolis_hastings(p, iter=1000): # Initialize starting point x, y = 0.0, 0.0 samples = np.zeros((iter, 2)) for i in range(iter): # Propose new point using normal distribution x_prop, y_prop = np.array([x, y]) + np.random.normal(size=2) # Calculate acceptance probability current_prob = p(x, y) prop_prob = p(x_prop, y_prop) accept_prob = min(1, prop_prob / current_prob) # Accept or reject the proposal if np.random.rand() < accept_prob: x, y = x_prop, y_prop samples[i] = [x, y] return samples # Generate 5000 samples (more samples = better plot) samples = metropolis_hastings(pgauss, iter=5000)
Second: Add Seaborn Plots (With Multi-Line Support)
The reason you saw no output is you never called any plotting functions. Below are two ways to visualize your samples with multi-line elements, using only Seaborn's APIs:
Option 1: Joint Plot with Trajectory Lines
This creates a scatter plot of your samples, plus adds trajectory lines for the first 1000 steps and mean reference lines:
# Create a joint plot of the samples joint_plot = sns.jointplot(x=samples[:, 0], y=samples[:, 1], kind="scatter", alpha=0.3) # Add x-trajectory line (first 1000 steps) sns.lineplot(x=np.arange(1000), y=samples[:1000, 0], color="crimson", linewidth=0.8, ax=joint_plot.ax_joint) # Add y-trajectory line (first 1000 steps) sns.lineplot(x=np.arange(1000), y=samples[:1000, 1], color="navy", linewidth=0.8, ax=joint_plot.ax_joint) # Add mean reference lines sns.lineplot(x=[0, 1000], y=[mus[0], mus[0]], color="limegreen", linestyle="--", ax=joint_plot.ax_joint) sns.lineplot(x=[mus[1], mus[1]], y=[0, 1000], color="limegreen", linestyle="--", ax=joint_plot.ax_joint) # Trigger plot display (auto-shows in Jupyter, needed for some local environments) sns.plt.show()
Option 2: Standalone Multi-Line Trajectory Plot
If you want a dedicated plot showing how x and y values change over sampling steps:
# Convert samples to a DataFrame for Seaborn compatibility sample_df = pd.DataFrame(samples[:1000], columns=["X Value", "Y Value"]) sample_df["Sampling Step"] = np.arange(1000) # Melt the DataFrame to plot both x and y in one line plot melted_df = sample_df.melt(id_vars="Sampling Step", var_name="Dimension", value_name="Sample Value") # Create the multi-line plot with Seaborn line_plot = sns.relplot( data=melted_df, x="Sampling Step", y="Sample Value", hue="Dimension", kind="line", linewidth=0.8 ) line_plot.set_axis_labels("Sampling Step", "Sample Value") line_plot.fig.suptitle("Metropolis-Hastings Sampling Trajectory", y=1.02) # Display the plot sns.plt.show()
Key Notes
- No plot output fix: You were missing both a completed sampling function and any calls to Seaborn's plotting methods. Once you generate the samples and call a Seaborn plot function, you'll see output.
- Seaborn-only multi-lines: We use Seaborn's
lineplotandrelplotto add multiple lines—no direct Matplotlibplt.plot()calls needed. The only Matplotlib-related call issns.plt.show(), which is a Seaborn-wrapped shortcut to trigger display.
内容的提问来源于stack exchange,提问作者Bob

