大数据 | 实验四:并行化数据挖掘算法设计

news2024/12/24 8:11:36

文章目录

  • 📚实验目的
  • 📚实验平台
  • 📚实验内容
  • 📚实验步骤
    • 🐇KNN介绍
    • 🐇并行化
      • 🥕在本地编写程序和调试
      • 🥕在集群上提交作业并执行
    • 🐇非并行化

📚实验目的

机器学习和数据挖掘算法是大数据分析处理领域的重要内容,随着数据规模的不断扩大,设计面向大数据处理的并行化机器学习和数据挖掘算法越来越有必要。通过对并行化数据挖掘算法的实现,掌握并行化处理问题的分析方法和编程思想方法,能够根据实际情况定制并行化的算法解决问题。

📚实验平台

1)操作系统:Linux;
2)Hadoop 版本:3.2.2;
3)JDK 版本:1.8;
4)Java IDE:Eclipse 3.8;
5 ) Spark 版本:3.2.1。

📚实验内容

  • 准备数据集(戳此下载),设计一种数据挖掘算法(聚类、分类、频繁项集挖掘或其他主题)对数据集进行信息提取,要求分别使用并行化非并行化的方式实现该算法。实验环境可选择 Hadoop 或者 Spark,程序语言可选用 Java、Python、Scala 等。
  • 在伪分布式环境下完成并行化算法的编写和测试,并在服务器集群进行提交运行。在单机环境下完成非并行化算法的编写和测试。
  • 自行对比并行化和非并行化实现方法的数据挖掘结果,两种结果需完全一致。

📚实验步骤

🐇KNN介绍

  • k近邻法(k-nearest neighbor,k-NN)是一种基本的分类和回归方法,是监督学习方法里的一种常用方法。k近邻算法假设给定一个训练数据集,其中的实例类别已定。分类时,对新的实例,根据其k个最近邻的训练实例类别,通过多数表决等方式进行预测。
  • k近邻算法用一句通俗的古语来说就是:“物以类聚,人以群分”。如果要看一个实例的类别,那么可以看它附近是什么类别。
    在这里插入图片描述
  • k近邻法三要素:距离度量、 k值的选择和分类决策规则。常用的距离度量是欧氏距离。 k值小时,k近邻模型更复杂,容易发生过拟合;k值大时,k近邻模型更简单,又容易欠拟合。
    在这里插入图片描述

🐇并行化

🥕在本地编写程序和调试

在这里插入图片描述

  • Mapper:计算测试集中每个点与训练集中所有点的欧式距离,并将距离和对应的类标签输出。
    • 输入<行偏移量,文件内容>,缓存的是test测试集,输入的是train训练集
    • 输出<第i组数据,[每个测试点与该训练点的距离+"@"+类标签列表]>
  • Reducer:将输入数据(一组一组来)按照距离从小到大排序,统计前k个元素的不同类别出现的次数,并输出距离最近的前k个元素的分类结果。
    • 输入<第i组数据,[每个测试点与该训练点的距离+"@"+类标签列表]>
    • 按照距离从小到大排序,统计前k个元素的不同类别出现的次数,找出出现次数最多的类别。
    • 输出<第i组数据,分类>
package KNN;
import java.io.BufferedReader;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URI;
import java.nio.file.FileStore;
import java.nio.file.PathMatcher;
import java.nio.file.WatchService;
import java.nio.file.attribute.UserPrincipalLookupService;
import java.nio.file.spi.FileSystemProvider;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.HashMap;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Iterator;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.filecache.DistributedCache;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.io.WritableComparable;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.util.GenericOptionsParser;

public class KNN 
{
	//Mapper:计算测试集中每个点与训练集中所有点的欧式距离,并将距离和对应的类标签输出。
	public static class TokenizerMapper	extends Mapper < Object, Text, IntWritable, Text > 
	{
		//List<String>类型的test变量,存储测试集
		static List < String > test = new ArrayList < String > (); 
		@Override
		//该函数在Mapper类运行前调用,用于初始化一些参数,读取缓存文件。
		protected void setup(Context context) throws IOException,InterruptedException 
		{ 
			//获取缓存文件的路径数组,这里只有一个缓存文件
			Path[] paths = DistributedCache.getLocalCacheFiles(context.getConfiguration());
			System.out.println(paths);
			//通过BufferedReader类读取缓存文件中的内容
			BufferedReader sb = new BufferedReader(new FileReader(paths[0].toUri().getPath()));
			String temp = null;
			//将每行数据存储到test变量中。
			while ((temp = sb.readLine()) != null) 
			{
				test.add(temp);
			}
			sb.close();
			System.out.println("+++++++" + test);
		}

		//计算两个Double类型数组之间的欧式距离
		private double distance(Double[] a, Double[] b) 
		{
			double sum = 0.0;
			for (int i = 0; i < a.length; i++) 
			{
				//累加(a[i] - b[i])^2
				sum += Math.pow(a[i] - b[i], 2);
			}
			return Math.sqrt(sum);//开根号
		}

		//将距离和对应的类标签输出
		public void map(Object key, Text value, Context context) throws IOException,InterruptedException 
		{
			//输入:<行偏移量,文件内容>,缓存的是test测试集,输入的是train训练集
			//将输入数据按照逗号分割成一个字符串数组train[]
			String train[] = value.toString().split(",");
			//最后一个元素是样本点所属的类别标签。
			String label = train[train.length - 1];
			//将train[]中除了最后一个元素以外的每个元素转换成Double类型,并存储到train_point数组中
			Double[] train_point = new Double[4];
			for (int i = 0; i < train.length - 1; i++) 
			{
				train_point[i] = Double.valueOf(train[i]);
			}
			
			//遍历存储测试集的变量test
			for (int i = 0; i < test.size(); i++) 
			{
				//将每个测试点按照逗号分割成一个字符串数组test_poit1[]
				String test_poit1[] = test.get(i).toString().split(",");
				//将test_poit1[]中的每个元素转换成Double类型,并存储到test_poit数组
				Double[] test_poit = new Double[4];
				for (int j = 0; j < test_poit1.length; j++) 
				{
					test_poit[j] = Double.valueOf(test_poit1[j]);
				}
				//将test_poit和train_point作为参数调用distance()函数计算它们之间的欧式距离
				//输出:<第i组数据,每个测试点与该训练点的距离+"@"+类标签>
				context.write(new IntWritable(i), new Text(String.valueOf(distance(test_poit, train_point)) + "@" + label));
			}

		}
	}

	//Reducer:将输入数据按照距离从小到大排序,统计前k个元素的不同类别出现的次数,并输出距离最近的前k个元素的分类结果。
	public static class IntSumReducer extends Reducer < IntWritable, Text, IntWritable, Text > 
	{
		//定义一个Text类型的变量result,用于存储分类结果。
		private Text result = new Text();
		//定义变量用于设置k的值。
		int k;
		//setup()在Reducer开始处理数据之前初始化。
		protected void setup(Context context) throws IOException,InterruptedException 
		{
			//context是上下文对象,用于传递参数和获取配置信息。
			Configuration conf=context.getConfiguration();
			//获取名为"K"的配置参数的值,并将其转化为int类型的值,如果未找到该配置参数,则默认值为1。
			k=conf.getInt("K", 1);
		}
		
		//将输入数据按照距离从小到大排序,统计前k个元素的不同类别出现的次数,并输出距离最近的前k个元素的分类结果。
		public void reduce(IntWritable key, Iterable < Text > values,Context context) throws IOException,InterruptedException 
		{
			//输入:<第i组数据,[每个测试点与该训练点的距离+"@"+类标签列表]>
			//定义一个TreeMap,用于将输入数据按照距离从小到大排序,其中键为距离,值为该距离所对应的类标签列表。
			TreeMap < Double, String > treemap = new TreeMap < Double, String > ();
			for (Text val: values) 
			{
				//将输入数据按照"@"进行分割,分别存储距离和类标签列表。
				String distance_lable[] = val.toString().split("@");
				for (int i = 0; i < distance_lable.length - 1; i = i + 2) 
				{
					//遍历类标签列表,每次i+2,跳过类标签
					//将输入数据按照距离从小到大排序,将当前距离和对应的类标签列表存储到TreeMap中。
					treemap.put(Double.valueOf(distance_lable[i]), distance_lable[i + 1]);
				}
			}
			
			//获取TreeMap的键集合,并返回一个迭代器,用于遍历TreeMap中所有的键。
			Iterator < Double > it = treemap.keySet().iterator();
			//定义一个HashMap,用于统计前k个元素的不同类别出现的次数。
			Map < String, Integer > map = new HashMap < String, Integer > ();
			int num = 0;
			
			//统计前k个元素的不同类别出现的次数
			while (it.hasNext()) 
			{
				//获取 TreeMap 的下一个键
				Double key1 = it.next();
				//如果 Map 中已经存在当前键所代表的值,则表示该值已经出现过,需要将对应键的值加 1
				if (map.containsKey(treemap.get(key1))) 
				{
					//获取当前键所对应的值在 Map 中对应的计数
					int temp = map.get(treemap.get(key1));
					//将计数加 1,然后更新 Map 对应键所代表的值
					map.put(treemap.get(key1), temp + 1);
				} 
				else //如果 Map 中不存在当前键所代表的值,则表示该值还没有出现过,需要在 Map 中添加一个新的元素
				{
					//将当前键所代表的值加入 Map,并设定计数为 1
					map.put(treemap.get(key1), 1);
				}
				//记录已经处理过的元素个数
				num++;
				if (num > k)
					break;
			}
			
			//找出前k个数据里出现次数最多的类别
			Iterator < String > it1 = map.keySet().iterator();
			String label = it1.next();
			//并将其对应的值存储在`count`变量中
			int count = map.get(label);
			while (it1.hasNext()) 
			{//当还有键未被遍历时,执行循环
				String now = it1.next();
				if (count < map.get(now)) 
				{//更新出现次数最多的类别
					label = now;
					count = map.get(label);
				}
			}
			//循环直到所有键都遍历完毕
			result.set(label);
			//输出:<第i组数据,分类>
			context.write(key, result);
		}
	}

	public static void main(String[] args) throws Exception 
	{
		Configuration conf = new Configuration();
		String[] otherArgs = new String[] 
		{
			"hdfs://localhost:9000/user/hadoop/input/train.csv",
			"hdfs://localhost:9000/user/hadoop/output"
		};
		if (otherArgs.length < 2) 
		{
			System.err.println("Usage: wordcount <in> [<in>...] <out>");
			System.exit(2);
		}
		conf.setInt("K",5);
		Job job1 = Job.getInstance(conf, "KNN");
		job1.setJarByClass(KNN.class);
		//设置分布式缓存文件
		job1.addCacheFile(new URI("hdfs://localhost:9000/user/hadoop/input/test.csv"));
		job1.setMapperClass(TokenizerMapper.class);
		job1.setReducerClass(IntSumReducer.class);
		job1.setMapOutputKeyClass(IntWritable.class);
		job1.setMapOutputValueClass(Text.class);
		job1.setOutputKeyClass(IntWritable.class);
		job1.setOutputValueClass(Text.class);
		for (int i = 0; i < otherArgs.length - 1; i++) 
		{
			FileInputFormat.addInputPath(job1, new Path(otherArgs[i]));
		}
		FileOutputFormat.setOutputPath(job1,new Path(otherArgs[otherArgs.length - 1]));
		System.exit(job1.waitForCompletion(true) ? 0 : 1);
	}
}

🥕在集群上提交作业并执行

  • 修改缓存路径、输入、输出路径(这里的路径其实不固定,以下是个人使用路径,与终端操作对应)

    • 输入:hdfs://10.102.0.198:9000/user/bigdata_学号/input/train.csv
    • 输出:hdfs://10.102.0.198:9000/user/bigdata_学号/output
    • 缓存路径:hdfs://10.102.0.198:9000/user/bigdata_学号/input/test.csv
  • 导出export包(这里的具体操作不清楚的可看实验二)
    在这里插入图片描述

  • 将数据包及导出的jar包上传至集群,终端操作依次如下:

    scp test.csv bigdata_学号@10.102.0.198:/home/bigdata_学号
    scp train.csv bigdata_学号@10.102.0.198:/home/bigdata_学号
    scp KNN.jar bigdata_学号@10.102.0.198:/home/bigdata_学号
    
  • 登录ssh:ssh bigdata_学号@10.102.0.198

  • 建好input文件夹,导入相关文件,并删除原有的output,终端操作依次如下:

    hdfs dfs -mkdir input
    hdfs dfs -put train.csv /user/bigdata_学号/input/
    hdfs dfs -put test.csv /user/bigdata_学号/input/
    hadoop fs -rm -r output
    
  • 运行:hadoop jar KNN.jar

    最后可在集群查看提交情况
    在这里插入图片描述

🐇非并行化

采用python(knn函数自带),并在Anaconda的JupyterLab运行。
在这里插入图片描述

import numpy as np
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier 
import matplotlib as mpl
import matplotlib.pyplot as plt

# header参数指定标题的行,默认为0.如果没有标题,则使用None
data = pd.read_csv('iris_train1.csv',header=0)
data2=pd.read_csv('iris_test1.csv',header=0)
print(data.head())
print(data2.head())
# 将文本数据映射成数值类型
data['Species']=data['Species'].map({"versicolor":0,"setosa":1,"virginica":2})
data2['Species']=data2['Species'].map({"versicolor":0,"setosa":1,"virginica":2})
# print(data.duplicated().any())
data.drop_duplicates(inplace=True)
print(data.shape)
print(data2.shape)

在这里插入图片描述

在这里插入图片描述

# 提取出每个类中鸢尾花数据
t0=data[data['Species']==0]
t1=data[data['Species']==1]
t2=data[data['Species']==2]
# 打乱每个类别的数据
t0=t0.sample(len(t0),random_state=0)
t1=t1.sample(len(t1),random_state=0)
t2=t2.sample(len(t2),random_state=0)
# 分配训练集和测试集
train_X=pd.concat([t0.iloc[:30,:-1],t1.iloc[:30,:-1],t2.iloc[:30,:-1]],axis=0)
train_y=pd.concat([t0.iloc[:30,-1],t1.iloc[:30,-1],t2.iloc[:30,-1]],axis=0)
df=pd.DataFrame(data2)
test_X=df[["Sepal.Length","Sepal.Width","Petal.Length","Petal.Width"]]
test_y=df['Species']
# 训练与测试
knn=KNeighborsClassifier(3)
knn.fit(train_X,train_y)
result=knn.predict(test_X)
print(result)
final = []
for i in result:
    if i == 0:
        final.append("versicolor")
    elif i == 1:
        final.append("setosa")
    else:
        final.append("virginica")
print(final)

在这里插入图片描述

# 可视化
# 设置画布大小
plt.figure(figsize=(20,10))
# 设置字体为黑体,支持中文显示
mpl.rcParams['font.family']='SimHei'
# 设置中文字体,可以正常显示负号
mpl.rcParams['axes.unicode_minus']=False
# 绘制训练集数据
plt.subplot(121)
plt.scatter(x=t0['Sepal.Length'][:40],y=t0['Petal.Length'][:40],color='r',label='versicolor')
plt.scatter(x=t1['Sepal.Length'][:40],y=t1['Petal.Length'][:40],color='g',label='setosa')
plt.scatter(x=t2['Sepal.Length'][:40],y=t2['Petal.Length'][:40],color='b',label='virginica')
plt.xlabel('花萼长度')
plt.ylabel('花瓣长度')
plt.legend(loc='best')

plt.subplot(122)
right = test_X[result == test_y]
wrong = test_X[result != test_y]
plt.scatter(x=right['Sepal.Length'], y=right['Petal.Length'], color='c', label="right", marker="x")
plt.scatter(x=wrong['Sepal.Length'], y=wrong['Petal.Length'], color='m', label="wrong", marker=">")
plt.xlabel('花萼长度')
plt.ylabel('花瓣长度')
plt.legend(loc='best')
plt.show()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OdClEh1H-1685002353688)(KNN.assets/image-20230525082701583.png)]

Anaconda是在之前上数据导论的时候安装的(好像当时还挺难装 ,具体安装教程之后再补吧(当时没记可恶

以下是完整python代码(没装Anaconda问题不大,pycharm或者vs都可以

import numpy as np
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
import matplotlib as mpl
import matplotlib.pyplot as plt

# header参数指定标题的行,默认为0.如果没有标题,则使用None
data = pd.read_csv('iris_train1.csv',header=0)
data2=pd.read_csv('iris_test1.csv',header=0)
print(data.head())
print(data2.head())
# 将文本数据映射成数值类型
data['Species']=data['Species'].map({"versicolor":0,"setosa":1,"virginica":2})
data2['Species']=data2['Species'].map({"versicolor":0,"setosa":1,"virginica":2})
# print(data.duplicated().any())
data.drop_duplicates(inplace=True)
print(data.shape)
print(data2.shape)

# 提取出每个类中鸢尾花数据
t0=data[data['Species']==0]
t1=data[data['Species']==1]
t2=data[data['Species']==2]

# 打乱每个类别的数据
t0=t0.sample(len(t0),random_state=0)
t1=t1.sample(len(t1),random_state=0)
t2=t2.sample(len(t2),random_state=0)

# 分配训练集和测试集
train_X=pd.concat([t0.iloc[:30,:-1],t1.iloc[:30,:-1],t2.iloc[:30,:-1]],axis=0)
train_y=pd.concat([t0.iloc[:30,-1],t1.iloc[:30,-1],t2.iloc[:30,-1]],axis=0)

df=pd.DataFrame(data2)
test_X=df[["Sepal.Length","Sepal.Width","Petal.Length","Petal.Width"]]
test_y=df['Species']

# 训练与测试
knn=KNeighborsClassifier(3)
knn.fit(train_X,train_y)
result=knn.predict(test_X)
print(result)
final = []
for i in result:
    if i == 0:
        final.append("versicolor")
    elif i == 1:
        final.append("setosa")
    else:
        final.append("virginica")
print(final)

# 可视化
# 设置画布大小
plt.figure(figsize=(20,10))
# 设置字体为黑体,支持中文显示
mpl.rcParams['font.family']='SimHei'
# 设置中文字体,可以正常显示负号
mpl.rcParams['axes.unicode_minus']=False
# 绘制训练集数据
plt.subplot(121)
plt.scatter(x=t0['Sepal.Length'][:40],y=t0['Petal.Length'][:40],color='r',label='versicolor')
plt.scatter(x=t1['Sepal.Length'][:40],y=t1['Petal.Length'][:40],color='g',label='setosa')
plt.scatter(x=t2['Sepal.Length'][:40],y=t2['Petal.Length'][:40],color='b',label='virginica')
plt.xlabel('花萼长度')
plt.ylabel('花瓣长度')
plt.legend(loc='best')

plt.subplot(122)
right = test_X[result == test_y]
wrong = test_X[result != test_y]
plt.scatter(x=right['Sepal.Length'], y=right['Petal.Length'], color='c', label="right", marker="x")
plt.scatter(x=wrong['Sepal.Length'], y=wrong['Petal.Length'], color='m', label="wrong", marker=">")
plt.xlabel('花萼长度')
plt.ylabel('花瓣长度')
plt.legend(loc='best')
plt.show()

pycharm运行截图

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

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

相关文章

chatgpt赋能python:Python切换输入法:实现更高效的编程

Python 切换输入法&#xff1a;实现更高效的编程 对于有多国语言需求的程序员来说&#xff0c;切换输入法是日常编程的基本操作之一。Python是一门广泛使用的编程语言&#xff0c;对于那些使用中文输入法的开发者来说&#xff0c;如何高效地切换输入法是一个需要考虑的问题。 …

chatgpt赋能python:Python去噪——提高图像质量的神器

Python去噪——提高图像质量的神器 介绍 随着科技的发展&#xff0c;我们的生活被数字化&#xff0c;许多信息都被存储在数字化设备中。这些设备会允许我们拍摄照片、视频和录音等多媒体文件。然而&#xff0c;在实际应用中&#xff0c;多媒体数据通常存在一些问题&#xff0…

chatgpt赋能python:Python加噪声:让你的数据更真实,更可靠

Python加噪声&#xff1a;让你的数据更真实&#xff0c;更可靠 Python作为一种开源高级编程语言&#xff0c;使得加噪声变得非常简单。加噪声是为了让数据更真实、更可靠&#xff0c;防止数据中的过拟合现象。那么本文将介绍Python添加噪声的基本概念和它的具体实现方法。 什…

chatgpt赋能python:Python中取某一列的方法

Python中取某一列的方法 Python是一种易于学习但功能强大的编程语言。它在数据分析、机器学习和Web开发中广泛应用。在这个代码示例中&#xff0c;我们将介绍如何使用Python从数据集中选择某一列。 获取数据集 为了演示如何从数据集中选择某一列&#xff0c;我们将首先使用p…

Packet Tracer - 配置编号标准 IPv4 ACL

Packet Tracer - 配置编号标准 IPv4 ACL 地址分配表 设备 接口 IP 地址 子网掩码 默认网关 R1 G0/0 192.168.10.1 255.255.255.0 不适用 G0/1 192.168.11.1 255.255.255.0 不适用 S0/0/0 10.1.1.1 255.255.255.252 不适用 S0/0/1 10.3.3.1 255.255.255.25…

chatgpt赋能python:Python分配内存的机制

Python 分配内存的机制 Python 是一种高级编程语言&#xff0c;它支持多种数据类型和模块化编程&#xff0c;这使得它成为了快速开发的首选语言。由于 Python 是一种解释型语言&#xff0c;它会动态地分配内存以支持程序执行。在本文中&#xff0c;我们将探讨 Python 分配内存…

C++数据结构:线性顺序表(链表)

文章目录 前言一、链表简介二、单链表实现二、代码解读三、链表的优缺点总结 前言 前一篇文章介绍用数组实现的顺序表时已经提到链表这种结构&#xff0c;在STL中的 list 就是以链表实现的顺序表。这种结构与数组相比最大好处就是可以很方便的在头部和中部插入数据&#xff0c…

chatgpt赋能python:Python动态Import:简介和用法

Python 动态 Import&#xff1a;简介和用法 什么是动态 Import&#xff1f; Python 中的动态 Import 是指在代码运行时通过字符串名称导入模块。这样可以使程序在运行时根据参数来加载不同的模块&#xff0c;达到动态控制程序行为的目的。Python 动态 Import 可以极大地提高编…

013、full-page-writes(全页写)

全页写 Full-Page Writes(全页写)Full-Page Writes(全页写)特点全页写模式全页写是否需要关闭块不一致造成原因:Full-Page Writes(全页写) 假设存储区中表A的页数据已损坏,因为后台写器进程正在写入脏页时操作系统已失败。由于XLOG记录无法在损坏的页面上重播,我们需要…

chatgpt赋能python:Python取负数

Python取负数 Python是一种支持数值和算术运算符的高级编程语言。在Python中&#xff0c;有时需要对数值取负数&#xff0c;本文将介绍如何使用Python来取负数。 什么是负数&#xff1f; 在数学中&#xff0c;负数是小于零的数字。例如&#xff0c;-5是一个负数&#xff0c;…

AF555 NHS ester,Alexa Fluor555 SE,AF 555 琥珀酰亚胺酯,水溶性鲜红色荧光染料

试剂基团反应特点&#xff08;Reagent group reaction characteristics&#xff09;&#xff1a; AF555 NHS酯&#xff08;琥珀酰亚胺酯&#xff09;是一种鲜红色的荧光染料。AF555染料是水溶性的并且pH从pH4到pH10不敏感。AF555的NHS酯&#xff08;或琥珀酰亚胺酯&#xff09…

【PCB专题】Allegro实时DFA(detrend fluctate analysis)约束规则设计

目录 DFA分析的重要性 采用建议 DFA_Update&#xff08;自动更新封装&#xff09;步骤 Side/End定义 约束表格&#xff08;DFA_Spreadsheet Editor&#xff09; 约束表单元格语法 PCB中使用DFA设计 DFA使用注意事项 参考文献 2018.06.21 李光熠 DFA分析的重要性 All…

opensuse15.4安装amd显卡hd6570驱动程序失败的原因分析

opensuse15.4安装amd显卡hd6570驱动程序失败的原因分析 台式机电脑系统是openSUSE-Leap-15.4-DVD-x86_64 独立显卡是AMD Radeon HD 6570 到官网https://www.amd.com/zh-cn.html——下载与支持——Radeon显卡与AMD芯片组——驱动程序——从下方列表中选中你的产品——AMD Radeon…

【项目实践】猫十二分类

【数据科学项目实践】基于ResNet和Inception v3的猫十二分类迁移学习 一、项目背景 本项目来源于飞浆平台的图像分类学习赛。指路链接 代码和结果来源于我的小组同学&#xff0c;没有做任何的改动&#xff0c;我这边仅做一个总结归纳&#xff0c;以便学习和复盘 简单把赛题…

chatgpt赋能python:Python句柄操作

Python 句柄操作 Python作为一门强大又易于使用的编程语言&#xff0c;其在内存管理和资源分配方面广受欢迎。其中Python句柄操作是其独特之处之一。在本文中&#xff0c;我们将介绍Python句柄操作的概念&#xff0c;方法&#xff0c;以及模块&#xff0c;并讨论Python中句柄操…

统计学中的t检验 、f检验、卡方检验

1.1数据的种类 我们都知道&#xff0c;一般数据可以分为两类&#xff0c;即定量数据&#xff08;数值型数据&#xff09;和定性数据&#xff08;非数值型数据&#xff09;&#xff0c;定性数据很好理解&#xff0c;例如人的性别&#xff0c;姓名这些都是定性数据。 定量数据可…

CSS3煎制荷包蛋动画特效,优质男士表白必备

你有多久没吃过早餐了&#xff1f;你是否每天忙碌到很晚&#xff0c;结果导致早上起来也很晚&#xff0c;匆匆忙忙来不及吃早餐&#xff0c;更别说自己做了。一直到现在&#xff0c;你有多久没有吃到过母亲做的早饭了&#xff1f;我们在外奔波&#xff0c;希望家人安康&#xf…

【C语言】几种方法解决问题:C6031返回值被忽略:“scanf” (保姆级图文)

目录 错因分析1. 使用_s结尾的安全函数版本&#xff08;推荐&#xff09;2. 在本项目中关闭警告&#xff08;作用一个项目&#xff09;3. 在本文件中关闭警告&#xff08;作用一个文件&#xff09;总结 欢迎关注 『C语言』 系列&#xff0c;持续更新中 欢迎关注 『C语言』 系列…

分布式协调服务--zookeeper

目录 一、概述 1、zookeeper有两种运行状态 zookeeper架构的角色&#xff1a; 2、Paxos算法&#xff1a;消息传递的一致性算法 3、ZAB协议 Zab 协议实现的作用 Zab协议核心 Zab协议内容 消息广播 崩溃恢复 实现原理 协议实现 一、概述 zookeeper官网 zookeeper官…

Trace32使用Data.Test和Data.TestList命令测试内存类型以及完整性

我们在debug的时候&#xff0c;可以使用Trace32自带的一些命令快速地检测目标系统的内存的类型和完整性&#xff08;是否可读或可写&#xff09;&#xff0c;以便快速排除内存缺陷带来的干扰。 目录 Data.Test&#xff1a; 内存完整性测试 Memory integrity test Data.TestL…