从零开始机器学习(机器学习 监督学习之线性回归 损失函数及可视化 梯度下降 线性回归的平方误差损失函数 lab实验)

news2024/11/26 20:26:53

文章目录

  • 机器学习定义
  • 监督学习之线性回归
  • 损失函数及可视化
  • 梯度下降
  • 线性回归的平方误差损失函数
  • lab实验

机器学习定义

机器学习就是机器通过不断训练数据集从逐渐知道正确的结果

机器学习包括监督学习和非监督学习

  • 监督学习:需要输入数据和结果数据来不断训练学习

监督学习包括回归和分类
回归是结果是连续的,不是有限的
分类是结果是离散的,是有限的

非监督学习:只需要输入数据来学习
例如聚类(将某类输入数据分一组,另外一类数据分一组)

监督学习之线性回归

线性回归:就是根据一组输入数据和输出数据的对应关系进而得到当输入数据为其他时依然能得到可靠输出数据的函数关系(函数是直线的)
在这里插入图片描述
如上图通过一些关于面积和价格的数据集得到这两个之间线性关系

损失函数及可视化

损失函数即cost function
这里m是数据集的个数
可以发现通过损失函数的定义发现如果损失函数的值越小那么对应的Model函数与真实数据集的数据对应关系越接近
在这里插入图片描述
可视化即用图的形式表示
当损失函数取不同的参数值,损失函数的值可能不同可能相同
当以参数为平面,损失函数的值为纵轴,便可得到可视化的立体图
对应的平面时可将相同值的损失函数的值的平面点连接起来,这样就形成了等值线

在这里插入图片描述

梯度下降

作用:得到最小损失函数(不仅仅是线性回归)的值的参数取值
原理:每次微微改变参数使得尝试降低损失函数的值,最终使得其得到一个最小值

类似在损失函数可视化图中从某个位置跑到最低处

在这里插入图片描述
损失韩式对某个参数求导就是损失函数对某个参数的偏导数

在这里插入图片描述
学习率:是一个固定的值

学习率如果过大,那么会导致w变化幅度过大,会在局部最小左右跳转,甚至离局部最小越来越远
学习率如果过小,那么会导致w变化幅度过小,要花很多步骤才会到达局部最小

偏导数会自动变化,当越接近局部最小时,对应的偏导数也会越小。此时学习率就算不变,但w的变化也会更小

在这里插入图片描述

线性回归的平方误差损失函数

下图是递归下降的算法具体实现
在这里插入图片描述

如下图如何得到相关偏导数
即
并且平方误差损失函数的可视化图是凹面图,即只有一个局部最小(即全局最小),而其他损失函数的可视化可能是类似丘陵,存在很多局部最小,从不同的参数位置开始递归下降可能得到不同的局部最小

lab实验

  • scatter 函数来绘制散点图。

  • plot 函数来根据点绘制直线

  • legend()#在左上角显示相关图例代表的数据类型


import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import MaxNLocator
from matplotlib.gridspec import GridSpec
from matplotlib.colors import LinearSegmentedColormap
from ipywidgets import interact
import copy
import math

plt.style.use('./deeplearning.mplstyle')
n_bin = 5

dlblue = '#0096ff'; dlorange = '#FF9300'; dldarkred='#C00000'; dlmagenta='#FF40FF'; dlpurple='#7030A0'
dlc = dict(dlblue = '#0096ff', dlorange = '#FF9300', dldarkred='#C00000', dlmagenta='#FF40FF', dlpurple='#7030A0')
dlcolors = [dlblue, dlorange, dldarkred, dlmagenta, dlpurple]
dlcm = LinearSegmentedColormap.from_list('dl_map', dlcolors, N=n_bin)



def compute_cost(X, y, w, b):
    m = X.shape[0]
    cost = 0.0
    for i in range(m):
        f_wb_i = np.dot(X[i],w) + b           #(n,)(n,)=scalar
        cost = cost + (f_wb_i - y[i])**2
    cost = cost/(2*m)
    return cost 


def plt_house_x(X, y,f_wb=None, ax=None):
    ''' plot house with aXis '''
    if not ax:
        fig, ax = plt.subplots(1,1)
    ax.scatter(X, y, marker='x', c='r', label="Actual Value")

    ax.set_title("Housing Prices")
    ax.set_ylabel('Price (in 1000s of dollars)')
    ax.set_xlabel(f'Size (1000 sqft)')
    if f_wb is not None:
        ax.plot(X, f_wb,  c=dlblue, label="Our Prediction")
    ax.legend()


def mk_cost_lines(x,y,w,b, ax):
    ''' makes vertical cost lines'''
    cstr = "cost = (1/m)*("
    ctot = 0
    label = 'cost for point'
    addedbreak = False
    for p in zip(x,y):
        f_wb_p = w*p[0]+b
        c_p = ((f_wb_p - p[1])**2)/2
        c_p_txt = c_p
        ax.vlines(p[0], p[1],f_wb_p, lw=3, color=dlpurple, ls='dotted', label=label)
        label='' #just one
        cxy = [p[0], p[1] + (f_wb_p-p[1])/2]
        ax.annotate(f'{c_p_txt:0.0f}', xy=cxy, xycoords='data',color=dlpurple,
            xytext=(5, 0), textcoords='offset points')
        cstr += f"{c_p_txt:0.0f} +"
        if len(cstr) > 38 and addedbreak is False:
            cstr += "\n"
            addedbreak = True
        ctot += c_p
    ctot = ctot/(len(x))
    cstr = cstr[:-1] + f") = {ctot:0.0f}"
    ax.text(0.15,0.02,cstr, transform=ax.transAxes, color=dlpurple)




def plt_stationary(x_train, y_train):        # 绘制三个图,一个是某对w和b对应模型,一个是损失函数随着w和b变化的等值线图,一个是三维的损失函数随着w和b变化的变化
    # setup figure 
    fig = plt.figure( figsize=(9,8))
    #fig = plt.figure(constrained_layout=True,  figsize=(12,10))
    fig.set_facecolor('#ffffff') #white
    fig.canvas.toolbar_position = 'top'
    #gs = GridSpec(2, 2, figure=fig, wspace = 0.01)
    gs = GridSpec(2, 2, figure=fig)
    ax0 = fig.add_subplot(gs[0, 0])
    ax1 = fig.add_subplot(gs[0, 1])
    ax2 = fig.add_subplot(gs[1, :],  projection='3d')
    ax = np.array([ax0,ax1,ax2])

    #setup useful ranges and common linspaces
    w_range = np.array([200-300.,200+300])
    b_range = np.array([50-300., 50+300])
    b_space  = np.linspace(*b_range, 100)
    w_space  = np.linspace(*w_range, 100)

    # get cost for w,b ranges for contour and 3D
    tmp_b,tmp_w = np.meshgrid(b_space,w_space)
    print(tmp_b)
    print(tmp_w)
    z=np.zeros_like(tmp_b)
    for i in range(tmp_w.shape[0]):
        for j in range(tmp_w.shape[1]):
            
            z[i,j] = compute_cost(x_train, y_train, tmp_w[i][j], tmp_b[i][j] )
            if z[i,j] == 0: z[i,j] = 1e-6

    w0=200;b=-100    #initial point
    ### plot model w cost ###
    f_wb = np.dot(x_train,w0) + b
    mk_cost_lines(x_train,y_train,w0,b,ax[0])
    plt_house_x(x_train, y_train, f_wb=f_wb, ax=ax[0])

    ### plot contour ###
    CS = ax[1].contour(tmp_w, tmp_b, np.log(z),levels=12, linewidths=2, alpha=0.7,colors=dlcolors)
    ax[1].set_title('Cost(w,b)')
    ax[1].set_xlabel('w', fontsize=10)
    ax[1].set_ylabel('b', fontsize=10)
    ax[1].set_xlim(w_range) ; ax[1].set_ylim(b_range)
    cscat  = ax[1].scatter(w0,b, s=100, color=dlblue, zorder= 10, label="cost with \ncurrent w,b")
    chline = ax[1].hlines(b, ax[1].get_xlim()[0],w0, lw=4, color=dlpurple, ls='dotted')
    cvline = ax[1].vlines(w0, ax[1].get_ylim()[0],b, lw=4, color=dlpurple, ls='dotted')
    ax[1].text(0.5,0.95,"Click to choose w,b",  bbox=dict(facecolor='white', ec = 'black'), fontsize = 10,
                transform=ax[1].transAxes, verticalalignment = 'center', horizontalalignment= 'center')

    #Surface plot of the cost function J(w,b)
    ax[2].plot_surface(tmp_w, tmp_b, z,  cmap = dlcm, alpha=0.3, antialiased=True)
    ax[2].plot_wireframe(tmp_w, tmp_b, z, color='k', alpha=0.1)
    plt.xlabel("$w$")
    plt.ylabel("$b$")
    ax[2].zaxis.set_rotate_label(False)
    ax[2].xaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
    ax[2].yaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
    ax[2].zaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
    ax[2].set_zlabel("J(w, b)\n\n", rotation=90)
    plt.title("Cost(w,b) \n [You can rotate this figure]", size=12)
    ax[2].view_init(30, -120)
    return fig,ax, [cscat, chline, cvline]


#https://matplotlib.org/stable/users/event_handling.html
class plt_update_onclick:  # 
    def __init__(self, fig, ax, x_train,y_train, dyn_items):
        self.fig = fig
        self.ax = ax
        self.x_train = x_train
        self.y_train = y_train
        self.dyn_items = dyn_items
        self.cid = fig.canvas.mpl_connect('button_press_event', self) # 鼠标点击时,会调用自己,即call函数

    def __call__(self, event):
        if event.inaxes == self.ax[1]:  # 点击发生的位置从而得到相应的w和b
            ws = event.xdata
            bs = event.ydata
            cst = compute_cost(self.x_train, self.y_train, ws, bs)

            # clear and redraw line plot
            self.ax[0].clear()
            f_wb = np.dot(self.x_train,ws) + bs  
            mk_cost_lines(self.x_train,self.y_train,ws,bs,self.ax[0])  # 距离
            plt_house_x(self.x_train, self.y_train, f_wb=f_wb, ax=self.ax[0]) # 根据新的w和b得到模型函数

            # remove lines and re-add on countour plot and 3d plot
            for artist in self.dyn_items:
                artist.remove()

            a = self.ax[1].scatter(ws,bs, s=100, color=dlblue, zorder= 10, label="cost with \ncurrent w,b")   
            b = self.ax[1].hlines(bs, self.ax[1].get_xlim()[0],ws, lw=4, color=dlpurple, ls='dotted')
            c = self.ax[1].vlines(ws, self.ax[1].get_ylim()[0],bs, lw=4, color=dlpurple, ls='dotted')
            d = self.ax[1].annotate(f"Cost: {cst:.0f}", xy= (ws, bs), xytext = (4,4), textcoords = 'offset points',
                               bbox=dict(facecolor='white'), size = 10)            # 现在的

            #Add point in 3D surface plot
            e = self.ax[2].scatter3D(ws, bs,cst , marker='X', s=100) # 3d图上画点

            self.dyn_items = [a,b,c,d,e]
            self.fig.canvas.draw()



def inbounds(a,b,xlim,ylim): #判断w和b是否出界
    xlow,xhigh = xlim
    ylow,yhigh = ylim
    ax, ay = a
    bx, by = b
    if (ax > xlow and ax < xhigh) and (bx > xlow and bx < xhigh) \
        and (ay > ylow and ay < yhigh) and (by > ylow and by < yhigh):
        return True
    return False

def plt_contour_wgrad(x, y, hist, ax, w_range=[-100, 500, 5], b_range=[-500, 500, 5], # 等值线上迭代的w和b的变化
                contours = [0.1,50,1000,5000,10000,25000,50000],
                      resolution=5, w_final=200, b_final=100,step=10 ):
    b0,w0 = np.meshgrid(np.arange(*b_range),np.arange(*w_range))
    z=np.zeros_like(b0)
    for i in range(w0.shape[0]):
        for j in range(w0.shape[1]):
            z[i][j] = compute_cost(x, y, w0[i][j], b0[i][j] ) 

    CS = ax.contour(w0, b0, z, contours, linewidths=2,
                   colors=[dlblue, dlorange, dldarkred, dlmagenta, dlpurple]) # 绘制等值线图
    ax.clabel(CS, inline=1, fmt='%1.0f', fontsize=10) # 等高线图上添加标签
    ax.set_xlabel("w");  ax.set_ylabel("b")
    ax.set_title('Contour plot of cost J(w,b), vs b,w with path of gradient descent')
    w = w_final; b=b_final
    ax.hlines(b, ax.get_xlim()[0],w, lw=2, color=dlpurple, ls='dotted')
    ax.vlines(w, ax.get_ylim()[0],b, lw=2, color=dlpurple, ls='dotted')

    base = hist[0]
    for point in hist[0::step]:
        edist = np.sqrt((base[0] - point[0])**2 + (base[1] - point[1])**2) # 计算当前点到到下一个w和b对应的坐标
        if(edist > resolution or point!=hist[-1]):  # 当跳转距离较大的时候或者还没到最后一个点的时候继续跳转
            if inbounds(point,base, ax.get_xlim(),ax.get_ylim()):
                plt.annotate('', xy=point, xytext=base,xycoords='data',
                         arrowprops={'arrowstyle': '->', 'color': 'r', 'lw': 3},
                         va='center', ha='center') # 在当前点绘制一个箭头
            base=point
    return


def plt_divergence(p_hist, J_hist, x_train,y_train):

    x=np.zeros(len(p_hist))
    y=np.zeros(len(p_hist))
    v=np.zeros(len(p_hist))
    for i in range(len(p_hist)):
        x[i] = p_hist[i][0]
        y[i] = p_hist[i][1]
        v[i] = J_hist[i]   # 对应的w和b和此时的损失函数值

    fig = plt.figure(figsize=(12,5))
    plt.subplots_adjust( wspace=0 )  # 子图间距的函数
    gs = fig.add_gridspec(1, 5)   # 5个空间放置子图,它们都将处于同一行内
    fig.suptitle(f"Cost escalates when learning rate is too large")
    #===============
    #  First subplot
    #===============
    ax = fig.add_subplot(gs[:2], )

    # Print w vs cost to see minimum
    fix_b = 100
    w_array = np.arange(-35000, 35000, 1000)
    cost = np.zeros_like(w_array)

    for i in range(len(w_array)):
        tmp_w = w_array[i]
        cost[i] = compute_cost(x_train, y_train, tmp_w, fix_b)

    ax.plot(w_array,cost)  # 损失函数随w的变化而变化
    ax.plot(x,v, c=dlmagenta) # 迭代过程中损失函数随着w的变化而变化
    ax.set_title("Cost vs w, b set to 100")
    ax.set_ylabel('Cost')
    ax.set_xlabel('w')
    ax.xaxis.set_major_locator(MaxNLocator(2))

    #===============
    # Second Subplot
    #===============

    tmp_b,tmp_w = np.meshgrid(np.arange(-35000, 35000, 5000),np.arange(-15000, 15000, 5000)) 
    z=np.zeros_like(tmp_b) 
    for i in range(tmp_w.shape[0]):
        for j in range(tmp_w.shape[1]):
            z[i][j] = compute_cost(x_train, y_train, tmp_w[i][j], tmp_b[i][j] )

    ax = fig.add_subplot(gs[2:], projection='3d') # 三维的损失函数随w和b的变化而变化
    ax.plot_surface(tmp_w, tmp_b, z,  alpha=0.3, color=dlblue) 
    ax.xaxis.set_major_locator(MaxNLocator(2))
    ax.yaxis.set_major_locator(MaxNLocator(2))

    ax.set_xlabel('w', fontsize=16)
    ax.set_ylabel('b', fontsize=16)
    ax.set_zlabel('\ncost', fontsize=16)
    plt.title('Cost vs (b, w)')
    # Customize the view angle
    ax.view_init(elev=20., azim=-65)
    ax.plot(x, y, v,c=dlmagenta) # 将迭代过程中的损失函数的值以及w和b的值
    return

# draw derivative line
# y = m*(x - x1) + y1
def add_line(dj_dx, x1, y1, d, ax):   # 给损失函数上某个点画切线的
    x = np.linspace(x1-d, x1+d,50)
    y = dj_dx*(x - x1) + y1
    ax.scatter(x1, y1, color=dlblue, s=50) # 画点
    ax.plot(x, y, '--', c=dldarkred,zorder=10, linewidth = 1) # 画切线
    xoff = 30 if x1 == 200 else 10
    ax.annotate(r"$\frac{\partial J}{\partial w}$ =%d" % dj_dx, fontsize=14,  # 点旁边的注释
                xy=(x1, y1), xycoords='data',
            xytext=(xoff, 10), textcoords='offset points',
            arrowprops=dict(arrowstyle="->"),
            horizontalalignment='left', verticalalignment='top')

def plt_gradients(x_train,y_train, f_compute_cost, f_compute_gradient):
    #===============
    #  First subplot
    #===============
    fig,ax = plt.subplots(1,2,figsize=(12,4))

    # Print w vs cost to see minimum
    fix_b = 100
    w_array = np.linspace(-100, 500, 50)
    w_array = np.linspace(0, 400, 50)
    cost = np.zeros_like(w_array)

    for i in range(len(w_array)):
        tmp_w = w_array[i]
        cost[i] = f_compute_cost(x_train, y_train, tmp_w, fix_b)
    ax[0].plot(w_array, cost,linewidth=1,label="cost function value")            # 画出损失函数图
    ax[0].set_title("Cost vs w, with gradient; b set to 100")
    ax[0].set_ylabel('Cost')
    ax[0].set_xlabel('w')

    # plot lines for fixed b=100
    for tmp_w in [100,200,300]:  # 画出损失函数上三个点的斜率
        fix_b = 100
        dj_dw,dj_db = f_compute_gradient(x_train, y_train, tmp_w, fix_b )
        j = f_compute_cost(x_train, y_train, tmp_w, fix_b)
        add_line(dj_dw, tmp_w, j, 30, ax[0])

    #===============
    # Second Subplot
    #===============

    tmp_b,tmp_w = np.meshgrid(np.linspace(-200, 200, 10), np.linspace(-100, 600, 10))
    U = np.zeros_like(tmp_w)
    V = np.zeros_like(tmp_b)
    for i in range(tmp_w.shape[0]):
        for j in range(tmp_w.shape[1]):
            U[i][j], V[i][j] = f_compute_gradient(x_train, y_train, tmp_w[i][j], tmp_b[i][j] ) # 计算一系列损失函数上关于w的斜率
    X = tmp_w
    Y = tmp_b
    n=-2
    color_array = np.sqrt(((V-n)/2)**2 + ((U-n)/2)**2)
    print(V)
    ax[1].set_title('Gradient shown in quiver plot')
    Q = ax[1].quiver(X, Y, U, V, color_array, units='width') # 根据斜率确定箭头的方向
    ax[1].quiverkey(Q, 0.9, 0.9, 2, r'$2 \frac{m}{s}$', labelpos='E',coordinates='figure') # 在右上角增加一个图例
    ax[1].set_xlabel("w"); 
    ax[1].set_ylabel("b")



def compute_gradient(x, y, w, b):   # 计算w和b此时对应的偏导数(梯度)

    # Number of training examples
    m = x.shape[0]    
    dj_dw = 0
    dj_db = 0
    
    for i in range(m):  
        f_wb = w * x[i] + b 
        dj_dw_i = (f_wb - y[i]) * x[i] 
        dj_db_i = f_wb - y[i] 
        dj_db += dj_db_i
        dj_dw += dj_dw_i 
    dj_dw = dj_dw / m 
    dj_db = dj_db / m 
        
    return dj_dw, dj_db


def gradient_descent(x, y, w_in, b_in, alpha, num_iters, cost_function, gradient_function):  # 从起始位置迭代规定次数,最后得到合适的参数

    w = copy.deepcopy(w_in) # avoid modifying global w_in
    # An array to store cost J and w's at each iteration primarily for graphing later
    J_history = []
    p_history = []
    b = b_in
    w = w_in
    
    for i in range(num_iters):
        # Calculate the gradient and update the parameters using gradient_function
        dj_dw, dj_db = gradient_function(x, y, w , b)     

        # Update Parameters using equation (3) above
        b = b - alpha * dj_db                            
        w = w - alpha * dj_dw                            

        # Save cost J at each iteration
        if i<100000:      # prevent resource exhaustion 
            J_history.append( cost_function(x, y, w , b))
            p_history.append([w,b])
        # Print cost every at intervals 10 times or as many iterations if < 10
        if i% math.ceil(num_iters/10) == 0:
            print(f"Iteration {i:4}: Cost {J_history[-1]:0.2e} ",
                  f"dj_dw: {dj_dw: 0.3e}, dj_db: {dj_db: 0.3e}  ",
                  f"w: {w: 0.3e}, b:{b: 0.5e}")
 
    return w, b, J_history, p_history #return w and J,w history for graphing





x_train=np.array([1.0,2.0])
y_train=np.array([300.0,500.0])    # 训练数据初始化
"""
fig, ax, dyn_items = plt_stationary(x_train, y_train)
updater = plt_update_onclick(fig, ax, x_train, y_train, dyn_items)
plt.show()                 # 动态变化w和b对应的模型和其与训练数据的差

plt_gradients(x_train,y_train, compute_cost, compute_gradient)
plt.show()             # 得到损失函数随w的变化而变化的趋势

w_final,b_final,J_hist,p_hist=gradient_descent(x_train,y_train,10,20,0.01,10000,compute_cost,compute_gradient)# 通过梯度下降得到合适的w和b值


fig, (ax1, ax2) = plt.subplots(1, 2, constrained_layout=True, figsize=(12,4)) # 绘制梯度下降过程中损失函数随迭代次数的变化的变化
ax1.plot(J_hist[:100]) # 前100次
ax2.plot(1000 + np.arange(len(J_hist[1000:])), J_hist[1000:]) # 所有的次数
ax1.set_title("Cost vs. iteration(start)");  ax2.set_title("Cost vs. iteration (end)")
ax1.set_ylabel('Cost')            ;  ax2.set_ylabel('Cost') 
ax1.set_xlabel('iteration step')  ;  ax2.set_xlabel('iteration step') 
plt.show()

print(f"1000 sqft house prediction {w_final*1.0 + b_final:0.1f} Thousand dollars")  # 利用得到的模型预测结果
print(f"1200 sqft house prediction {w_final*1.2 + b_final:0.1f} Thousand dollars")
print(f"2000 sqft house prediction {w_final*2.0 + b_final:0.1f} Thousand dollars")


fig, ax = plt.subplots(1,1, figsize=(12, 6))
plt_contour_wgrad(x_train, y_train, p_hist, ax) # 在等值线中绘制梯度下降过程中w和b随迭代次数的变化的变化
plt.show()




w_final, b_final, J_hist, p_hist = gradient_descent(x_train ,y_train, 100, 100, 0.8, 10, compute_cost, compute_gradient)
plt_divergence(p_hist, J_hist,x_train, y_train) # 观察当学习率较大时候在损失函数上w和b的位置的变化
plt.show()

 """

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1557146.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

晚间兼职新选择:6种副业让你收入满意

晚上&#xff0c;是许多人放松身心、享受闲暇时光的时刻&#xff0c;但你知道吗&#xff1f;它也是开启副业之门的黄金时段。接下来&#xff0c;我将为你揭晓6个特别适合晚间操作的副业&#xff0c;期待能助你一臂之力。 1,网络兼职新篇章&#xff1a;在浩瀚的互联网海洋中&am…

2024年北京通信展|北京国际信息通信展览会|北京PT展

2024年北京通信展|北京国际信息通信展览会|北京PT展 2024年中国国际信息通信展览会&#xff08;PTEXPO&#xff09;&#xff0c;是由工业和信息化部主办的ICT行业盛会&#xff0c;自1990年创办以来&#xff0c;已成功举办31届&#xff0c;是反映信息通信行业发展最新成果的重要…

NO13 蓝桥杯单片机之NE555的使用及实践

由于LM555的内容较少&#xff0c;因此就把使用方法和代码实践放在一起了。 1 NE555使用方法 NE555是一个“信号发生电路”&#xff0c;可以理解为一个“方波产生器”&#xff0c;值得注意的是&#xff0c;其是一个硬件电路&#xff0c;一旦确定了功能也就确定了&#xff0c;所…

JDK,JRE,JVM 区别和联系【大白话Java面试题】

JDK&#xff0c;JRE&#xff0c;JVM 区别和联系 大白话回答&#xff1a; JDK是开发环境一般开发人员需要&#xff0c;包含开发环境&#xff08;JDK)和运行环境&#xff08;JRE&#xff09;&#xff0c;JRE是运行环境&#xff0c;普通用户需要。jre文件夹下的bin文件夹就是JVM的…

【unity】认识unity Hub的主要功能

这里我们主要讲解unity Hub中的【项目】和【安装】功能&#xff0c;其他对应的功能栏相信大家根据文字就可以知道相应的作用。 首先是介绍【项目】功能&#xff0c;在这里我们可以创建本地项目和云端项目&#xff0c;作为初学者我们创建本地项目皆可&#xff0c;当然如果你是多…

一则关于Go的高级构建指北

本文将探索Golang高级构建技巧&#xff0c;从而有助于创建更高效的二进制文件。 构建选项 以下是 go build 命令最常用的一些选项&#xff1a; -o: 指定输出文件名。默认输出文件名是主软件包的名称&#xff0c;在 Windows 系统中会自动添加 .exe 后缀。-v: 详细输出。该选项…

【AI系列】Python NLTK 库和停用词处理的应用

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

力扣236---二叉树的最近公共祖先(DFS,Java)

题目描述&#xff1a; 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为&#xff1a;“对于有根树 T 的两个节点 p、q&#xff0c;最近公共祖先表示为一个节点 x&#xff0c;满足 x 是 p、q 的祖先且 x 的深度尽可能大&#xff08;一个…

电脑数据守护者:揭秘自动备份的神奇力量

在数字化时代&#xff0c;数据已经成为我们生活和工作中不可或缺的一部分。然而&#xff0c;电脑故障、人为误操作、恶意软件攻击等风险时刻威胁着数据的安全。因此&#xff0c;自动备份的重要性愈发凸显。它能够在数据发生意外丢失或损坏时&#xff0c;迅速恢复原始数据&#…

java入门学习Day03

本篇文章主要有java中的变量、命名方法、数据类型。 一、java中的变量 数据类型 变量名 数据值&#xff1b;int money 50&#xff1b; public class varibledemo {public static void main(String[] args) {int money 50;//变量的输出System.out.println(money);money 6…

浅谈 kafka

引言 同事在公司内部分享了关于 kafka 技术一些相关的内容&#xff0c;所以有了这篇文章&#xff1b;部分图片选自网络摘抄&#xff1b; 1 Kafka概述 1.1 定义 Kafka传统定义&#xff1a;kafka是一个分布式的基于发布/订阅模式的消息队列。 Kafka最新定义&#xff1a;kafka…

ubuntu 安装 cloudcompare(两种方法)

方法一 &#xff1a;从 snap 安装 &#xff08;推荐&#xff09; 安装简单&#xff0c;基本上功能都有&#xff08;读写保存las&#xff0c;pcd&#xff0c;标注等&#xff09; 安装&#xff1a; sudo apt-get update sudo apt install snap sudo snap install cloudcompare…

【送书福利第六期】:《AI绘画教程:Midjourney使用方法与技巧从入门到精通》

文章目录 一、《AI绘画教程&#xff1a;Midjourney使用方法与技巧从入门到精通》二、内容介绍三、作者介绍&#x1f324;️粉丝福利 一、《AI绘画教程&#xff1a;Midjourney使用方法与技巧从入门到精通》 一本书读懂Midjourney绘画&#xff0c;让创意更简单&#xff0c;让设计…

二十四种设计模式与六大设计原则(一):【策略模式、代理模式、单例模式、多例模式、工厂方法模式、抽象工厂模式】的定义、举例说明、核心思想、适用场景和优缺点

目录 策略模式【Strategy Pattern】 定义 举例说明 核心思想 适用场景 优缺点 代理模式【Proxy Pattern】 定义 举例说明 核心思想 适用场景 优缺点 单例模式【Singleton Pattern】 定义 举例说明 核心思想 适用场景 优缺点 多例模式【Multition Pattern】…

视频素材库哪个软件好?这8个高清无版权的素材网推荐

小伙伴们在制作短视频的时候&#xff0c;是不是为找素材发愁呢&#xff1f;一个高质量的无水印视频对创作者的帮助太大了&#xff0c;而且还需要无版权可商用的&#xff0c;那究竟有没有这样的网站呢&#xff1f;今天我来告诉大家。 1&#xff0c;蛙学府&#xff08;中国&…

电商系列之售后退货

> 插&#xff1a;AI时代&#xff0c;程序员或多或少要了解些人工智能&#xff0c;前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 坚持不懈&#xff0c;越努力越幸运&#xff0c;大家…

InternLM 全链路开源体系

书生 浦语全链路开发体系&#xff1a;从数据到最后的应用&#xff0c;都有相应开源工具&#xff0c;其中模型&#xff0c;和数据集都有很好的开源支持。 一. 书生 万卷 书生万卷开发数据集包括&#xff0c;1.0和CC&#xff0c;拥有较为丰富的高质量的数据集&#xff0c;可用于…

Spring依赖注入思想分析

Spring 依赖注入思想分析 文章目录 Spring 依赖注入思想分析一、前言二、控制反转&#xff08;Inversion of Control&#xff09;1. 代码依赖初始化问题2. 匿名内部类解决方案3. 创建接口实现类方案4. 问题深入5. 定义父类解决问题1方案6. 控制反转解决问题2方案 三、依赖注入&…

Swift:“逻辑运算子“与“比较运算符“

1. 逻辑非 ! 逻辑非运算符 ! 是用于对布尔值取反的。当操作数为 true 时&#xff0c;! 将返回 false&#xff0c;而当操作数为 false 时&#xff0c;! 将返回 true。 let isTrue true let isFalse !isTrue // isFalse 现在是 false 2. 逻辑与 && 逻辑与运算符 &a…

CPU 密集型 和 IO密集型 的区别,如何确定线程池大小?

CPU密集型任务 是指需要大量的CPU资源进行计算的任务 CPU密集型任务通常涉及到复杂的计算&#xff0c;如算法逻辑、数学计算等&#xff0c;其特点是CPU使用率高&#xff0c;多在这种类型的任务中&#xff0c;线程数量一般与CPU的核心数相匹配就足够了。 一个简单的估算方法是…