梯度下降算法推导与实现
importmatplotlib.pyplotaspltimportnumpyasnpimportpandasaspddefplot_points(X, y): admitted=X[np.argwhere(y==1)] rejected=X[np.argwhere(y==0)] plt.scatter([s[0][0] forsinrejected], [s[0][1] forsinrejected], s=25, color='blue', edgecolor='k') plt.scatter([s[0][0] forsinadmitted], [s[0][1] forsinadmitted], s=25, color='red', edgecolor='k') defdisplay(m, b, color='g--'): plt.xlim(-0.05,1.05) plt.ylim(-0.05,1.05) x=np.arange(-10, 10, 0.1) plt.plot(x, m*x+b, color) data=pd.read_csv('data.csv', header=None) X=np.array(data[[0,1]]) y=np.array(data[2]) plot_points(X,y) plt.show() defsigmoid(x): return1/(1+np.exp(-x)) defoutput_formula(features, weights, bias): sigmoid(np.dot(features, weights) +bias) deferror_formula(y, output): return-y*np.log(output) - (1-y) *np.log(1-output) defupdate_weights(x, y, weights, bias, learnrate): output=output_formula(x, weights, bias) d_error=-(y-output) weights-=learnrate*d_error*xbias-=learnrate*d_errorreturnweights, biasnp.random.seed(44) epochs=100learnrate=0.01deftrain(features, targets, epochs, learnrate, graph_lines=False): errors= [] n_records, n_features=features.shapelast_loss=Noneweights=np.random.normal(scale=1/n_features**.5, size=n_features) bias=0foreinrange(epochs): del_w=np.zeros(weights.shape) forx, yinzip(features, targets): output=output_formula(x, weights, bias) error=error_formula(y, output) weights, bias=update_weights(x, y, weights, bias, learnrate) out=output_formula(features, weights, bias) loss=np.mean(error_formula(targets, out)) errors.append(loss) ife% (epochs/10) ==0: print("\n========== Epoch", e,"==========") iflast_lossandlast_loss<loss: print("Train loss: ", loss, " WARNING - Loss Increasing") else: print("Train loss: ", loss) last_loss=losspredictions=out>0.5accuracy=np.mean(predictions==targets) print("Accuracy: ", accuracy) ifgraph_linesande% (epochs/100) ==0: display(-weights[0]/weights[1], -bias/weights[1]) plt.title("Solution boundary") display(-weights[0]/weights[1], -bias/weights[1], 'black') plot_points(features, targets) plt.show() plt.title("Error Plot") plt.xlabel('Number of epochs') plt.ylabel('Error') plt.plot(errors) plt.show() train(X, y, epochs, learnrate, True)
反向传播
反向传播流程如下:
- 进行前向反馈运算。
- 将模型的输出与期望的输出进行比较。
- 计算误差。
- 向后运行前向反馈运算(反向传播),将误差分散到每个权重上。
- 更新权重,并获得更好的模型。
- 继续此流程,直到获得很好的模型。
实战演练:利用神经网络来预测学生录取情况
数据集来源: http://www.ats.ucla.edu/
importpandasaspdimportnumpyasnpdata=pd.read_csv('student_data.csv') data[:10] importmatplotlib.pyplotasplt%matplotlibinlinedefplot_points(data): X=np.array(data[["gre","gpa"]]) y=np.array(data["admit"]) admitted=X[np.argwhere(y==1)] rejected=X[np.argwhere(y==0)] plt.scatter([s[0][0] forsinrejected], [s[0][1] forsinrejected], s=25, color='red', edgecolor='k') plt.scatter([s[0][0] forsinadmitted], [s[0][1] forsinadmitted], s=25, color='cyan', edgecolor='k') plt.xlabel('Test (GRE)') plt.ylabel('Grades (GPA)') plot_points(data) plt.show() data_rank1=data[data["rank"]==1] data_rank2=data[data["rank"]==2] data_rank3=data[data["rank"]==3] data_rank4=data[data["rank"]==4] plot_points(data_rank1) plt.title("Rank 1") plt.show() plot_points(data_rank2) plt.title("Rank 2") plt.show() plot_points(data_rank3) plt.title("Rank 3") plt.show() plot_points(data_rank4) plt.title("Rank 4") plt.show() one_hot_data=pd.concat([data, pd.get_dummies(data['rank'], prefix='rank')], axis=1) one_hot_data=one_hot_data.drop('rank', axis=1) one_hot_data[:10] processed_data=one_hot_data[:] processed_data['gre']=processed_data['gre']/800processed_data['gpa']=processed_data['gpa']/4.0processed_data[:10] sample=np.random.choice(processed_data.index, size=int(len(processed_data)*0.9), replace=False) train_data, test_data=processed_data.iloc[sample], processed_data.drop(sample) print("Number of training samples is", len(train_data)) print("Number of testing samples is", len(test_data)) print(train_data[:10]) print(test_data[:10]) features=train_data.drop('admit', axis=1) targets=train_data['admit'] features_test=test_data.drop('admit', axis=1) targets_test=test_data['admit'] print(features[:10]) print(targets[:10]) Activation (sigmoid) functiondefsigmoid(x): return1/ (1+np.exp(-x)) defsigmoid_prime(x): returnsigmoid(x) * (1-sigmoid(x)) deferror_formula(y, output): return-y*np.log(output) - (1-y) *np.log(1-output) deferror_term_formula(y, output): return (y-output)*sigmoid_prime(x) deferror_term_formula(x, y, output): return (y-output) *output* (1-output) epochs=1000learnrate=0.5deftrain_nn(features, targets, epochs, learnrate): np.random.seed(42) n_records, n_features=features.shapelast_loss=Noneweights=np.random.normal(scale=1/n_features**.5, size=n_features) foreinrange(epochs): del_w=np.zeros(weights.shape) forx, yinzip(features.values, targets): output=sigmoid(np.dot(x, weights)) error=error_formula(y, output) error_term=error_term_formula(x,y, output) del_w+=error_term*xweights+=learnrate*del_w/n_recordsife% (epochs/10) ==0: out=sigmoid(np.dot(features, weights)) loss=np.mean((out-targets) **2) print("Epoch:", e) iflast_lossandlast_loss<loss: print("Train loss: ", loss, " WARNING - Loss Increasing") else: print("Train loss: ", loss) last_loss=lossprint("=========") print("Finished training!") returnweightsweights=train_nn(features, targets, epochs, learnrate) tes_out=sigmoid(np.dot(features_test, weights)) predictions=tes_out>0.5accuracy=np.mean(predictions==targets_test) print("Prediction accuracy: {:.3f}".format(accuracy))