You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PCA交互式可视化代码报错:无法访问未赋值的自由变量'fig'

问题解决:调用plot_widget()触发NameError:无法访问自由变量'fig'

问题背景

运行PCA探索性数据分析Notebook时,调用plot_widget()函数触发NameError,报错显示无法访问封闭作用域中未关联值的自由变量fig,错误位于pca_utils.py的update函数第285行,尝试多种方法修复均未解决。

完整报错栈

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
File /Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/site-packages/ipywidgets/widgets/interaction.py:243, in interactive.update(self, *args)
    241     value = widget.get_interact_value()
    242     self.kwargs[widget._kwarg] = value
--> 243 self.result = self.f(**self.kwargs)
    244 show_inline_matplotlib_plots()
    245 if self.auto_display and self.result is not None:

File ~/Documents/GitHub/Machine_Learning/Machine_Learning_in_School/Lab8_PCA_ungraded/pca_utils.py:285, in plot_widget.<locals>.update(angle)
    283 def update(angle):
    284     ang = angle
--> 285     with fig.batch_update():
    286         p0r = rotation_matrix(ang)@p0
    287         p1r = rotation_matrix(ang)@p1

NameError: cannot access free variable 'fig' where it is not associated with a value in enclosing scope

Notebook相关代码

PCA - 探索性数据分析示例

本Notebook目标:

  • 复现Andrew的PCA示例
  • 可视化PCA在二维小数据集上的工作原理,了解并非所有投影都"理想"
  • 可视化三维数据如何被包含在二维子空间中
  • 使用PCA发现高维数据中的隐藏模式

导入库

import pandas as pd
import numpy as np
from sklearn.decomposition import PCA
from pca_utils import plot_widget
from bokeh.io import show, output_notebook
from bokeh.plotting import figure
import matplotlib.pyplot as plt
import plotly.offline as py

[后续Notebook代码及中文说明保留原样]

参考的变量作用域示例(未解决问题)

曾参考Copilot提供的变量作用域示例,但问题仍未解决:

import matplotlib.pyplot as plt

def create_plot():
    # 在正确作用域内定义图形对象
    fig, ax = plt.subplots()

    # 绘制数据
    ax.plot([1, 2, 3], [1, 4, 9])

    # 设置标签和标题
    ax.set_xlabel('X-axis')
    ax.set_ylabel('Y-axis')
    ax.set_title('Sample Plot')

    # 显示图形
    plt.show()

    return fig

# 调用函数创建并显示图形
fig = create_plot()

解决方案

问题根源

报错核心是plot_widget内部定义的update函数尝试访问外部作用域的fig变量,但该变量未被正确捕获到闭包中,或者fig在plot_widget函数内的定义位置错误,导致update无法访问。

修复步骤

修改pca_utils.py中的plot_widget函数,确保fig变量在update函数的封闭作用域中被正确定义,并且通过闭包可以访问:

  1. 打开pca_utils.py,找到plot_widget函数
  2. 确保fig对象在update函数定义之前创建,并且处于同一个作用域内
  3. 若使用Bokeh的figure,需确保fig被正确初始化并传递给闭包

示例修复后的plot_widget函数结构:

from bokeh.models import ColumnDataSource
from ipywidgets import interact

def plot_widget(data):
    # 1. 先创建fig对象,确保在update函数之前定义
    fig = figure(title="PCA 旋转可视化", x_axis_label='X', y_axis_label='Y')
    
    # 初始化数据源
    source = ColumnDataSource(data=dict(x=[], y=[]))
    fig.circle('x', 'y', source=source)
    
    # 2. 定义update函数,此时fig处于封闭作用域,可正常访问
    def update(angle):
        ang = angle
        with fig.batch_update():
            # 执行旋转逻辑
            p0r = rotation_matrix(ang)@p0
            p1r = rotation_matrix(ang)@p1
            # 更新数据源
            source.data = dict(x=p0r[:,0], y=p0r[:,1])
    
    # 3. 返回交互组件
    return interact(update, angle=(0, 360, 1))

关键说明

  • 必须保证fig在update函数定义之前被创建,这样闭包才能捕获到该变量
  • 从报错中的fig.batch_update()判断,fig是Bokeh的figure实例,需避免和Matplotlib的图形对象混淆
  • 检查plot_widget函数内是否有其他逻辑导致fig被重新赋值或作用域被改变

内容的提问来源于stack exchange,提问作者HongViet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.15 17:21:18