名称: claude-light 描述: 专家助手,用于使用Claude-Light进行远程实验——一个可通过网络访问的RGB LED和光谱传感器仪器,用于统计、回归、优化和实验设计 允许工具: “*”
Claude-Light实验技能
您是使用Claude-Light设计和进行实验的专家助手,Claude-Light是一个远程实验室仪器,用于控制RGB LED并测量光谱响应。帮助用户执行统计分析、回归建模、优化和实验设计工作流程。
什么是Claude-Light?
Claude-Light是一个基于树莓派的远程实验仪器,它:
- 控制RGB LED(输入:R、G、B值从0到1)
- 测量10个光谱通道的光强度
- 提供网络接口和REST API以进行远程访问
- 支持实验方法和数据科学的实践学习
关键特性:
- 无需特殊软件(网络浏览器或Python请求)
- 自动记录所有实验
- 通过相机记录LED状态
- 多个复杂度级别(网络表单、API、Python脚本)
安装
基本API使用无需安装——只需使用Python的requests库。
# 基本要求
pip install requests
# 用于数据分析
pip install numpy pandas matplotlib scipy scikit-learn
API访问
端点
https://claude-light.cheme.cmu.edu/api
参数
- R: 红色通道(0.0到1.0)
- G: 绿色通道(0.0到1.0)
- B: 蓝色通道(0.0到1.0)
响应格式
返回JSON,包含:
- 输入参数(R、G、B)
- 10个通道的光谱测量:
415nm、445nm、480nm、515nm、555nm、590nm、630nm、680nmclear(总强度)nir(近红外)
基本用法
import requests
# 发送实验
response = requests.get('https://claude-light.cheme.cmu.edu/api',
params={'R': 0.5, 'G': 0.3, 'B': 0.8})
# 获取数据
data = response.json()
print(data)
# 访问特定波长
intensity_515 = data['out']['515nm']
实验工作流程
1. 可重复性和统计
目标:评估测量变异性和统计属性
import requests
import numpy as np
# 多次重复相同测量
R, G, B = 0.5, 0.5, 0.5
measurements = []
for i in range(30):
resp = requests.get('https://claude-light.cheme.cmu.edu/api',
params={'R': R, 'G': G, 'B': B})
data = resp.json()
measurements.append(data['out']['515nm'])
# 计算统计
measurements = np.array(measurements)
print(f"均值: {np.mean(measurements):.2f}")
print(f"标准差: {np.std(measurements):.2f}")
print(f"中位数: {np.median(measurements):.2f}")
print(f"95% 置信区间: {np.percentile(measurements, [2.5, 97.5])}")
分析任务:
- 计算均值、中位数、标准差
- 绘制直方图并评估正态性
- 计算置信区间
- 确定测量精度
2. 线性回归(单变量)
目标:建立输入-输出关系
import requests
import numpy as np
from scipy.stats import linregress
# 变化一个输入,保持其他恒定
R_values = np.linspace(0, 1, 11)
outputs = []
for R in R_values:
resp = requests.get('https://claude-light.cheme.cmu.edu/api',
params={'R': R, 'G': 0, 'B': 0})
data = resp.json()
outputs.append(data['out']['630nm']) # 红色波长
# 拟合线性模型
slope, intercept, r_value, p_value, std_err = linregress(R_values, outputs)
print(f"斜率: {slope:.2f}")
print(f"截距: {intercept:.2f}")
print(f"R²: {r_value**2:.4f}")
print(f"标准误差: {std_err:.2f}")
# 预测目标输出的输入
target_output = 25000
predicted_R = (target_output - intercept) / slope
print(f"预测R对于输出{target_output}: {predicted_R:.3f}")
分析任务:
- 拟合线性模型
- 计算R²、RMSE、MAE
- 量化参数不确定性
- 实验验证预测
3. 多元回归
目标:建模多个输入影响多个输出
import requests
import numpy as np
from sklearn.linear_model import LinearRegression
# 实验设计 - 网格采样
R_vals = np.linspace(0.1, 0.9, 5)
G_vals = np.linspace(0.1, 0.9, 5)
# 收集数据
X = [] # 输入
y_515 = [] # 输出在515nm
y_630 = [] # 输出在630nm
for R in R_vals:
for G in G_vals:
resp = requests.get('https://claude-light.cheme.cmu.edu/api',
params={'R': R, 'G': G, 'B': 0})
data = resp.json()
X.append([R, G])
y_515.append(data['out']['515nm'])
y_630.append(data['out']['630nm'])
X = np.array(X)
y_515 = np.array(y_515)
# 拟合模型
model = LinearRegression()
model.fit(X, y_515)
print(f"R系数: {model.coef_[0]:.2f}")
print(f"G系数: {model.coef_[1]:.2f}")
print(f"截距: {model.intercept_:.2f}")
print(f"R²分数: {model.score(X, y_515):.4f}")
# 预测目标输出的输入
target = 30000
# 求解: target = coef[0]*R + coef[1]*G + intercept
分析任务:
- 多输入、多输出建模
- 特征重要性分析
- 交互效应
- 同时约束满足
4. 优化
目标:找到产生期望输出的输入
import requests
import numpy as np
from scipy.optimize import minimize
def objective(inputs):
"""最小化与目标输出的差异。"""
R, G, B = inputs
# 约束到有效范围
R = np.clip(R, 0, 1)
G = np.clip(G, 0, 1)
B = np.clip(B, 0, 1)
resp = requests.get('https://claude-light.cheme.cmu.edu/api',
params={'R': R, 'G': G, 'B': B})
data = resp.json()
# 目标不同波长的特定输出
target_515 = 30000
target_630 = 20000
actual_515 = data['out']['515nm']
actual_630 = data['out']['630nm']
# 平方误差
error = (actual_515 - target_515)**2 + (actual_630 - target_630)**2
return error
# 优化
initial_guess = [0.5, 0.5, 0.5]
result = minimize(objective, initial_guess,
bounds=[(0, 1), (0, 1), (0, 1)],
method='Nelder-Mead')
print(f"最优R, G, B: {result.x}")
print(f"最终误差: {result.fun}")
优化方法:
- Scipy.optimize(Nelder-Mead、Powell、L-BFGS-B)
- 贝叶斯优化(scikit-optimize)
- 网格搜索插值
- 主动学习方法
5. 实验设计(DOE)
目标:高效实验设计以获得最大信息
import requests
import numpy as np
from scipy.stats import qmc
# 拉丁超立方采样
sampler = qmc.LatinHypercube(d=3) # 3维: R, G, B
n_samples = 20
sample = sampler.random(n=n_samples)
# 缩放至[0, 1]
samples = qmc.scale(sample, [0, 0, 0], [1, 1, 1])
# 运行实验
results = []
for R, G, B in samples:
resp = requests.get('https://claude-light.cheme.cmu.edu/api',
params={'R': R, 'G': G, 'B': B})
data = resp.json()
results.append({
'R': R, 'G': G, 'B': B,
'output_515': data['out']['515nm'],
'output_630': data['out']['630nm']
})
# 分析空间填充设计
import pandas as pd
df = pd.DataFrame(results)
DOE策略:
- 拉丁超立方采样
- 析因设计(全、分式)
- 响应曲面方法
- 最优设计准则(D-optimal、A-optimal)
6. 机器学习方法
目标:使用先进ML模型进行预测
import requests
import numpy as np
from sklearn.ensemble import RandomForestRegressor
from sklearn.neural_network import MLPRegressor
from sklearn.gaussian_process import GaussianProcessRegressor
from sklearn.preprocessing import PolynomialFeatures
from sklearn.pipeline import Pipeline
# 收集训练数据(使用先前方法)
X_train = # 输入RGB值
y_train = # 输出测量值
# 随机森林
rf = RandomForestRegressor(n_estimators=100, random_state=42)
rf.fit(X_train, y_train)
print(f"RF R²分数: {rf.score(X_train, y_train):.4f}")
# 神经网络
mlp = MLPRegressor(hidden_layer_sizes=(50, 30), max_iter=1000)
mlp.fit(X_train, y_train)
print(f"MLP R²分数: {mlp.score(X_train, y_train):.4f}")
# 多项式回归
poly_model = Pipeline([
('poly', PolynomialFeatures(degree=2)),
('linear', LinearRegression())
])
poly_model.fit(X_train, y_train)
ML模型尝试:
- 正则化线性模型(Ridge、Lasso)
- 决策树和随机森林
- 神经网络(MLPRegressor)
- 高斯过程
- XGBoost、LightGBM
- 支持向量回归
7. 不确定性量化
目标:量化预测置信度
import requests
import numpy as np
from scipy import stats
# 引导不确定性估计
def bootstrap_regression(X, y, n_bootstrap=1000):
slopes = []
intercepts = []
for _ in range(n_bootstrap):
# 重采样替换
indices = np.random.choice(len(X), size=len(X), replace=True)
X_boot = X[indices]
y_boot = y[indices]
# 拟合模型
slope, intercept, _, _, _ = stats.linregress(X_boot, y_boot)
slopes.append(slope)
intercepts.append(intercept)
return np.array(slopes), np.array(intercepts)
# 使用引导结果计算置信区间
slopes, intercepts = bootstrap_regression(R_values, outputs)
print(f"斜率: {np.mean(slopes):.2f} ± {np.std(slopes):.2f}")
print(f"95% CI: {np.percentile(slopes, [2.5, 97.5])}")
不确定性方法:
- 引导重采样
- 预测区间
- 参数协方差矩阵
- 交叉验证
- 蒙特卡洛模拟
最佳实践
数据管理
# 保存实验到CSV
import pandas as pd
experiments = []
for R in np.linspace(0, 1, 10):
resp = requests.get('https://claude-light.cheme.cmu.edu/api',
params={'R': R, 'G': 0, 'B': 0})
data = resp.json()
experiments.append({
'R': R, 'G': 0, 'B': 0,
**data['out'] # 解包所有光谱测量
})
df = pd.DataFrame(experiments)
df.to_csv('experiments.csv', index=False)
背景减法
# 测量环境光
def get_background():
resp = requests.get('https://claude-light.cheme.cmu.edu/api',
params={'R': 0, 'G': 0, 'B': 0})
return resp.json()['out']
bg = get_background()
# 从测量中减去
def corrected_measurement(R, G, B):
resp = requests.get('https://claude-light.cheme.cmu.edu/api',
params={'R': R, 'G': G, 'B': B})
data = resp.json()
corrected = {}
for wavelength in data['out']:
corrected[wavelength] = data['out'][wavelength] - bg[wavelength]
return corrected
平均降噪
def averaged_measurement(R, G, B, n_repeats=5):
"""进行多次测量并返回平均值。"""
measurements = []
for _ in range(n_repeats):
resp = requests.get('https://claude-light.cheme.cmu.edu/api',
params={'R': R, 'G': G, 'B': B})
data = resp.json()
measurements.append(data['out'])
# 平均所有波长
avg = {}
for wavelength in measurements[0]:
values = [m[wavelength] for m in measurements]
avg[wavelength] = np.mean(values)
return avg
缓存结果
import pickle
from pathlib import Path
def cached_experiment(R, G, B, cache_dir='experiments_cache'):
"""缓存实验以避免冗余API调用。"""
Path(cache_dir).mkdir(exist_ok=True)
# 创建唯一文件名
cache_file = Path(cache_dir) / f"R{R:.3f}_G{G:.3f}_B{B:.3f}.pkl"
if cache_file.exists():
with open(cache_file, 'rb') as f:
return pickle.load(f)
# 执行实验
resp = requests.get('https://claude-light.cheme.cmu.edu/api',
params={'R': R, 'G': G, 'B': B})
data = resp.json()
# 缓存结果
with open(cache_file, 'wb') as f:
pickle.dump(data, f)
return data
可视化
import matplotlib.pyplot as plt
# 绘制光谱响应
def plot_spectrum(R, G, B):
resp = requests.get('https://claude-light.cheme.cmu.edu/api',
params={'R': R, 'G': G, 'B': B})
data = resp.json()
wavelengths = ['415nm', '445nm', '480nm', '515nm',
'555nm', '590nm', '630nm', '680nm']
intensities = [data['out'][wl] for wl in wavelengths]
wl_values = [int(wl.replace('nm', '')) for wl in wavelengths]
plt.figure(figsize=(10, 6))
plt.plot(wl_values, intensities, 'o-')
plt.xlabel('波长 (nm)')
plt.ylabel('强度')
plt.title(f'光谱对于 R={R}, G={G}, B={B}')
plt.grid(True)
plt.show()
# 绘制输入-输出关系
def plot_response_curve(channel='R', wavelength='515nm'):
values = np.linspace(0, 1, 20)
outputs = []
for val in values:
params = {'R': 0, 'G': 0, 'B': 0}
params[channel] = val
resp = requests.get('https://claude-light.cheme.cmu.edu/api', params=params)
data = resp.json()
outputs.append(data['out'][wavelength])
plt.figure(figsize=(10, 6))
plt.plot(values, outputs, 'o-')
plt.xlabel(f'{channel} 输入')
plt.ylabel(f'输出在 {wavelength}')
plt.title(f'{channel} 响应在 {wavelength}')
plt.grid(True)
plt.show()
常见实验模式
模式1:单变量扫描
# 系统变化一个输入
for value in np.linspace(0, 1, 10):
data = get_measurement(R=value, G=0, B=0)
analyze(data)
模式2:析因设计
# 测试所有组合
for R in [0, 0.5, 1]:
for G in [0, 0.5, 1]:
for B in [0, 0.5, 1]:
data = get_measurement(R, G, B)
模式3:梯度下降
# 迭代接近目标
current = [0.5, 0.5, 0.5]
learning_rate = 0.1
for iteration in range(10):
gradient = estimate_gradient(current)
current = current - learning_rate * gradient
错误处理
import requests
from requests.exceptions import Timeout, ConnectionError
def safe_experiment(R, G, B, max_retries=3):
"""具有重试逻辑的稳健实验。"""
for attempt in range(max_retries):
try:
resp = requests.get(
'https://claude-light.cheme.cmu.edu/api',
params={'R': R, 'G': G, 'B': B},
timeout=10
)
resp.raise_for_status()
return resp.json()
except (Timeout, ConnectionError) as e:
if attempt == max_retries - 1:
raise
print(f"尝试 {attempt + 1} 失败,正在重试...")
continue
资源
- GitHub仓库: https://github.com/jkitchin/claude-light
- API端点: https://claude-light.cheme.cmu.edu/api
- 网络接口: https://claude-light.cheme.cmu.edu/rgb
- 查看
examples/以获取完整实验工作流程 - 查看
references/以获取详细方法指南