Open liuyameng128 opened 7 months ago
你好,已收到,谢谢。
plt_overfit.py is shown below: `""" plot_overfit class and assocaited routines that plot an interactive example of overfitting and its solutions """ import math from ipywidgets import Output from matplotlib.gridspec import GridSpec from matplotlib.widgets import Button, CheckButtons from sklearn.linear_model import LogisticRegression, Ridge from lab_utils_common import np, plt, dlc, predict_logistic, plot_data, zscore_normalize_features
def map_one_feature(X1, degree): """ Feature mapping function to polynomial features """ X1 = np.atleast1d(X1) out = [] string = "" k = 0 for i in range(1, degree+1): out.append((X1**i)) string = string + f"w{{{k}}}{munge('x_0',i)} + " k += 1 string = string + ' b' #add b to text equation, not to data return np.stack(out, axis=1), string
def map_feature(X1, X2, degree): """ Feature mapping function to polynomial features """ X1 = np.atleast_1d(X1) X2 = np.atleast_1d(X2)
out = []
string = ""
k = 0
for i in range(1, degree+1):
for j in range(i + 1):
out.append((X1**(i-j) * (X2**j)))
string = string + f"w_{{{k}}}{munge('x_0',i-j)}{munge('x_1',j)} + "
k += 1
#print(string + 'b')
return np.stack(out, axis=1), string + ' b'
def munge(base, exp): if exp == 0: return '' if exp == 1: return base return base + f'^{{{exp}}}'
def plot_decision_boundary(ax, x0r,x1r, predict, w, b, scaler = False, mu=None, sigma=None, degree=None): """ Plots a decision boundary Args: x0r : (array_like Shape (1,1)) range (min, max) of x0 x1r : (array_like Shape (1,1)) range (min, max) of x1 predict : function to predict z values scalar : (boolean) scale data or not """
h = .01 # step size in the mesh
# create a mesh to plot in
xx, yy = np.meshgrid(np.arange(x0r[0], x0r[1], h),
np.arange(x1r[0], x1r[1], h))
# Plot the decision boundary. For that, we will assign a color to each
# point in the mesh [x_min, m_max]x[y_min, y_max].
points = np.c_[xx.ravel(), yy.ravel()]
Xm,_ = map_feature(points[:, 0], points[:, 1],degree)
if scaler:
Xm = (Xm - mu)/sigma
Z = predict(Xm, w, b)
# Put the result into a color plot
Z = Z.reshape(xx.shape)
contour = ax.contour(xx, yy, Z, levels = [0.5], colors='g')
return contour
def plot_decision_boundary_sklearn(x0r, x1r, predict, degree, scaler = False): """ Plots a decision boundary Args: x0r : (array_like Shape (1,1)) range (min, max) of x0 x1r : (array_like Shape (1,1)) range (min, max) of x1 degree: (int) degree of polynomial predict : function to predict z values scaler : not sure """
h = .01 # step size in the mesh
# create a mesh to plot in
xx, yy = np.meshgrid(np.arange(x0r[0], x0r[1], h),
np.arange(x1r[0], x1r[1], h))
# Plot the decision boundary. For that, we will assign a color to each
# point in the mesh [x_min, m_max]x[y_min, y_max].
points = np.c_[xx.ravel(), yy.ravel()]
Xm = map_feature(points[:, 0], points[:, 1],degree)
if scaler:
Xm = scaler.transform(Xm)
Z = predict(Xm)
# Put the result into a color plot
Z = Z.reshape(xx.shape)
plt.contour(xx, yy, Z, colors='g')
#plot_data(X_train,y_train)
output
output = Output() # sends hidden error messages to display when using widgets
class button_manager: ''' Handles some missing features of matplotlib check buttons on init: creates button, links to button_click routine, calls call_on_click with active index and firsttime=True on click: maintains single button on state, calls call_on_click '''
@output.capture() # debug
def __init__(self,fig, dim, labels, init, call_on_click):
'''
dim: (list) [leftbottom_x,bottom_y,width,height]
labels: (list) for example ['1','2','3','4','5','6']
init: (list) for example [True, False, False, False, False, False]
'''
self.fig = fig
self.ax = plt.axes(dim) #lx,by,w,h
self.init_state = init
self.call_on_click = call_on_click
self.button = CheckButtons(self.ax,labels,init)
self.button.on_clicked(self.button_click)
self.status = self.button.get_status()
self.call_on_click(self.status.index(True),firsttime=True)
@output.capture() # debug
def reinit(self):
self.status = self.init_state
self.button.set_active(self.status.index(True)) #turn off old, will trigger update and set to status
@output.capture() # debug
def button_click(self, event):
''' maintains one-on state. If on-button is clicked, will process correctly '''
#new_status = self.button.get_status()
#new = [self.status[i] ^ new_status[i] for i in range(len(self.status))]
#newidx = new.index(True)
self.button.eventson = False
self.button.set_active(self.status.index(True)) #turn off old or reenable if same
self.button.eventson = True
self.status = self.button.get_status()
self.call_on_click(self.status.index(True))
class overfit_example(): """ plot overfit example """
# pylint: disable=too-many-locals
# pylint: disable=missing-function-docstring
# pylint: disable=attribute-defined-outside-init
def __init__(self, regularize=False):
self.regularize=regularize
self.lambda_=0
fig = plt.figure( figsize=(8,6))
fig.canvas.toolbar_visible = False
fig.canvas.header_visible = False
fig.canvas.footer_visible = False
fig.set_facecolor('#ffffff') #white
gs = GridSpec(5, 3, figure=fig)
ax0 = fig.add_subplot(gs[0:3, :])
ax1 = fig.add_subplot(gs[-2, :])
ax2 = fig.add_subplot(gs[-1, :])
ax1.set_axis_off()
ax2.set_axis_off()
self.ax = [ax0,ax1,ax2]
self.fig = fig
self.axfitdata = plt.axes([0.26,0.124,0.12,0.1 ]) #lx,by,w,h
self.bfitdata = Button(self.axfitdata , 'fit data', color=dlc['dlblue'])
self.bfitdata.label.set_fontsize(12)
self.bfitdata.on_clicked(self.fitdata_clicked)
#clear data is a future enhancement
#self.axclrdata = plt.axes([0.26,0.06,0.12,0.05 ]) #lx,by,w,h
#self.bclrdata = Button(self.axclrdata , 'clear data', color='white')
#self.bclrdata.label.set_fontsize(12)
#self.bclrdata.on_clicked(self.clrdata_clicked)
self.cid = fig.canvas.mpl_connect('button_press_event', self.add_data)
self.typebut = button_manager(fig, [0.4, 0.07,0.15,0.15], ["Regression", "Categorical"],
[False,True], self.toggle_type)
self.fig.text(0.1, 0.02+0.21, "Degree", fontsize=12)
self.degrbut = button_manager(fig,[0.1,0.02,0.15,0.2 ], ['1','2','3','4','5','6'],
[True, False, False, False, False, False], self.update_equation)
if self.regularize:
self.fig.text(0.6, 0.02+0.21, r"lambda($\lambda$)", fontsize=12)
self.lambut = button_manager(fig,[0.6,0.02,0.15,0.2 ], ['0.0','0.2','0.4','0.6','0.8','1'],
[True, False, False, False, False, False], self.updt_lambda)
#self.regbut = button_manager(fig, [0.8, 0.08,0.24,0.15], ["Regularize"],
# [False], self.toggle_reg)
#self.logistic_data()
def updt_lambda(self, idx, firsttime=False):
# pylint: disable=unused-argument
self.lambda_ = idx * 0.2
def toggle_type(self, idx, firsttime=False):
self.logistic = idx==1
self.ax[0].clear()
if self.logistic:
self.logistic_data()
else:
self.linear_data()
if not firsttime:
self.degrbut.reinit()
@output.capture() # debug
def logistic_data(self,redraw=False):
if not redraw:
m = 50
n = 2
np.random.seed(2)
X_train = 2*(np.random.rand(m,n)-[0.5,0.5])
y_train = X_train[:,1]+0.5 > X_train[:,0]**2 + 0.5*np.random.rand(m) #quadratic + random
y_train = y_train + 0 #convert from boolean to integer
self.X = X_train
self.y = y_train
self.x_ideal = np.sort(X_train[:,0])
self.y_ideal = self.x_ideal**2
self.ax[0].plot(self.x_ideal, self.y_ideal, "--", color = "orangered", label="ideal", lw=1)
plot_data(self.X, self.y, self.ax[0], s=10, loc='lower right')
self.ax[0].set_title("OverFitting Example: Categorical data set with noise")
self.ax[0].text(0.5,0.93, "Click on plot to add data. Hold [Shift] for blue(y=0) data.",
fontsize=12, ha='center',transform=self.ax[0].transAxes, color=dlc["dlblue"])
self.ax[0].set_xlabel(r"$x_0$")
self.ax[0].set_ylabel(r"$x_1$")
def linear_data(self,redraw=False):
if not redraw:
m = 30
c = 0
x_train = np.arange(0,m,1)
np.random.seed(1)
y_ideal = x_train**2 + c
y_train = y_ideal + 0.7 * y_ideal*(np.random.sample((m,))-0.5)
self.x_ideal = x_train #for redraw when new data included in X
self.X = x_train
self.y = y_train
self.y_ideal = y_ideal
else:
self.ax[0].set_xlim(self.xlim)
self.ax[0].set_ylim(self.ylim)
self.ax[0].scatter(self.X,self.y, label="y")
self.ax[0].plot(self.x_ideal, self.y_ideal, "--", color = "orangered", label="y_ideal", lw=1)
self.ax[0].set_title("OverFitting Example: Regression Data Set (quadratic with noise)",fontsize = 14)
self.ax[0].set_xlabel("x")
self.ax[0].set_ylabel("y")
self.ax0ledgend = self.ax[0].legend(loc='lower right')
self.ax[0].text(0.5,0.93, "Click on plot to add data",
fontsize=12, ha='center',transform=self.ax[0].transAxes, color=dlc["dlblue"])
if not redraw:
self.xlim = self.ax[0].get_xlim()
self.ylim = self.ax[0].get_ylim()
@output.capture() # debug
def add_data(self, event):
if self.logistic:
self.add_data_logistic(event)
else:
self.add_data_linear(event)
@output.capture() # debug
def add_data_logistic(self, event):
if event.inaxes == self.ax[0]:
x0_coord = event.xdata
x1_coord = event.ydata
if event.key is None: #shift not pressed
self.ax[0].scatter(x0_coord, x1_coord, marker='x', s=10, c = 'red', label="y=1")
self.y = np.append(self.y,1)
else:
self.ax[0].scatter(x0_coord, x1_coord, marker='o', s=10, label="y=0", facecolors='none',
edgecolors=dlc['dlblue'],lw=3)
self.y = np.append(self.y,0)
self.X = np.append(self.X,np.array([[x0_coord, x1_coord]]),axis=0)
self.fig.canvas.draw()
def add_data_linear(self, event):
if event.inaxes == self.ax[0]:
x_coord = event.xdata
y_coord = event.ydata
self.ax[0].scatter(x_coord, y_coord, marker='o', s=10, facecolors='none',
edgecolors=dlc['dlblue'],lw=3)
self.y = np.append(self.y,y_coord)
self.X = np.append(self.X,x_coord)
self.fig.canvas.draw()
#@output.capture() # debug
#def clrdata_clicked(self,event):
# if self.logistic == True:
# self.X = np.
# else:
# self.linear_regression()
@output.capture() # debug
def fitdata_clicked(self,event):
if self.logistic:
self.logistic_regression()
else:
self.linear_regression()
def linear_regression(self):
self.ax[0].clear()
self.fig.canvas.draw()
# create and fit the model using our mapped_X feature set.
self.X_mapped, _ = map_one_feature(self.X, self.degree)
self.X_mapped_scaled, self.X_mu, self.X_sigma = zscore_normalize_features(self.X_mapped)
#linear_model = LinearRegression()
#linear_model = Ridge(alpha=self.lambda_, normalize=True, max_iter=10000)
linear_model = Ridge(alpha=self.lambda_, max_iter=10000)
linear_model.fit(self.X_mapped_scaled, self.y )
self.w = linear_model.coef_.reshape(-1,)
self.b = linear_model.intercept_
x = np.linspace(*self.xlim,30) #plot line idependent of data which gets disordered
xm, _ = map_one_feature(x, self.degree)
xms = (xm - self.X_mu)/ self.X_sigma
y_pred = linear_model.predict(xms)
#self.fig.canvas.draw()
self.linear_data(redraw=True)
self.ax0yfit = self.ax[0].plot(x, y_pred, color = "blue", label="y_fit")
self.ax0ledgend = self.ax[0].legend(loc='lower right')
self.fig.canvas.draw()
def logistic_regression(self):
self.ax[0].clear()
self.fig.canvas.draw()
# create and fit the model using our mapped_X feature set.
self.X_mapped, _ = map_feature(self.X[:, 0], self.X[:, 1], self.degree)
self.X_mapped_scaled, self.X_mu, self.X_sigma = zscore_normalize_features(self.X_mapped)
if not self.regularize or self.lambda_ == 0:
lr = LogisticRegression(penalty='none', max_iter=10000)
else:
C = 1/self.lambda_
lr = LogisticRegression(C=C, max_iter=10000)
lr.fit(self.X_mapped_scaled,self.y)
#print(lr.score(self.X_mapped_scaled, self.y))
self.w = lr.coef_.reshape(-1,)
self.b = lr.intercept_
#print(self.w, self.b)
self.logistic_data(redraw=True)
self.contour = plot_decision_boundary(self.ax[0],[-1,1],[-1,1], predict_logistic, self.w, self.b,
scaler=True, mu=self.X_mu, sigma=self.X_sigma, degree=self.degree )
self.fig.canvas.draw()
@output.capture() # debug
def update_equation(self, idx, firsttime=False):
#print(f"Update equation, index = {idx}, firsttime={firsttime}")
self.degree = idx+1
if firsttime:
self.eqtext = []
else:
for artist in self.eqtext:
#print(artist)
artist.remove()
self.eqtext = []
if self.logistic:
_, equation = map_feature(self.X[:, 0], self.X[:, 1], self.degree)
string = 'f_{wb} = sigmoid('
else:
_, equation = map_one_feature(self.X, self.degree)
string = 'f_{wb} = ('
bz = 10
seq = equation.split('+')
blks = math.ceil(len(seq)/bz)
for i in range(blks):
if i == 0:
string = string + '+'.join(seq[bz*i:bz*i+bz])
else:
string = '+'.join(seq[bz*i:bz*i+bz])
string = string + ')' if i == blks-1 else string + '+'
ei = self.ax[1].text(0.01,(0.75-i*0.25), f"${string}$",fontsize=9,
transform = self.ax[1].transAxes, ma='left', va='top' )
self.eqtext.append(ei)
self.fig.canvas.draw()`
@hu-minghao @liuyameng128 According to this post sklearn LogisticRegression without regularization, on sklearn 0.21 and higher versions, the regularization can be disabled by passing the None
value to penalty. Also, if you want to use a penalty pass 'l1'
or 'l2'
. So, please fix the lines 359 and 362 of the logistic_regression
function of plt_overflit.py
with penalty = None
as follows:
def logistic_regression(self):
self.ax[0].clear()
self.fig.canvas.draw()
# create and fit the model using our mapped_X feature set.
self.X_mapped, _ = map_feature(self.X[:, 0], self.X[:, 1], self.degree)
self.X_mapped_scaled, self.X_mu, self.X_sigma = zscore_normalize_features(self.X_mapped)
if not self.regularize or self.lambda_ == 0:
lr = LogisticRegression(penalty = None, max_iter = 10000) #line fixed
else:
C = 1/self.lambda_
lr = LogisticRegression(C = C, max_iter = 10000, penalty = None) #line fixed
lr.fit(self.X_mapped_scaled, self.y)
#print(lr.score(self.X_mapped_scaled, self.y))
self.w = lr.coef_.reshape(-1, )
self.b = lr.intercept_
#print(self.w, self.b)
self.logistic_data(redraw=True)
self.contour = plot_decision_boundary(self.ax[0], [-1, 1], [-1, 1], predict_logistic, self.w, self.b,
scaler = True, mu = self.X_mu, sigma = self.X_sigma, degree = self.degree )
self.fig.canvas.draw()
`%matplotlib widget import matplotlib.pyplot as plt from ipywidgets import Output from plt_overfit import overfit_example, output plt.style.use('./deeplearning.mplstyle')
plt.close("all") display(output) ofit = overfit_example(False)`
error message: `InvalidParameterError Traceback (most recent call last) File D:\Python\Lib\site-packages\ipywidgets\widgets\widget_output.py:103, in Output.capture..capture_decorator..inner(*args, kwargs)
101 self.clear_output(*clear_args, *clear_kwargs)
102 with self:
--> 103 return func(args, kwargs)
File D:\ppt\jupyter数据处理\week3\Optional Labs\plt_overfit.py:323, in overfit_example.fitdata_clicked(self, event) 320 @output.capture() # debug 321 def fitdata_clicked(self,event): 322 if self.logistic: --> 323 self.logistic_regression() 324 else: 325 self.linear_regression()
File D:\ppt\jupyter数据处理\week3\Optional Labs\plt_overfit.py:365, in overfit_example.logisticregression(self) 362 C = 1/self.lambda 363 lr = LogisticRegression(C=C, max_iter=10000) --> 365 lr.fit(self.X_mapped_scaled,self.y) 366 #print(lr.score(self.X_mappedscaled, self.y)) 367 self.w = lr.coef.reshape(-1,)
File D:\Python\Lib\site-packages\sklearn\base.py:1467, in _fit_context..decorator..wrapper(estimator, *args, *kwargs)
1462 partial_fit_and_fitted = (
1463 fit_method.name == "partial_fit" and _is_fitted(estimator)
1464 )
1466 if not global_skip_validation and not partial_fit_and_fitted:
-> 1467 estimator._validate_params()
1469 with config_context(
1470 skip_parameter_validation=(
1471 prefer_skip_nested_validation or global_skip_validation
1472 )
1473 ):
1474 return fit_method(estimator, args, **kwargs)
File D:\Python\Lib\site-packages\sklearn\base.py:666, in BaseEstimator._validate_params(self) 658 def _validate_params(self): 659 """Validate types and values of constructor parameters 660 661 The expected type and values must be defined in the
_parameter_constraints
(...) 664 accepted constraints. 665 """ --> 666 validate_parameter_constraints( 667 self._parameter_constraints, 668 self.get_params(deep=False), 669 caller_name=self.class.name, 670 )File D:\Python\Lib\site-packages\sklearn\utils_param_validation.py:95, in validate_parameter_constraints(parameter_constraints, params, caller_name) 89 else: 90 constraints_str = ( 91 f"{', '.join([str(c) for c in constraints[:-1]])} or" 92 f" {constraints[-1]}" 93 ) ---> 95 raise InvalidParameterError( 96 f"The {param_name!r} parameter of {caller_name} must be" 97 f" {constraints_str}. Got {param_val!r} instead." 98 )
InvalidParameterError: The 'penalty' parameter of LogisticRegression must be a str among {'l1', 'l2', 'elasticnet'} or None. Got 'none' instead.`