当前位置: 首页 > news >正文

【人工智能】利用TensorFlow.js在浏览器中实现一个基本的情感分析系统

使用TensorFlow.js在浏览器中进行情感分析是一个非常实用的应用场景。TensorFlow.js 是一个用于在JavaScript环境中训练和部署机器学习模型的库,使得开发者能够在客户端直接运行复杂的机器学习任务。对于情感分析,我们可以使用预先训练好的模型来识别文本中的积极、消极或中性情感。

下面我会给你一个简化的项目计划,包括原理和方法、技术栈的选择、模型的设计,以及一个简单的示例代码,来演示如何使用TensorFlow.js实现一个基本的情感分析器。

一、项目原理和方法

1.情感分析原理

  • 特征提取:将文本转换成数值特征,常见的方法有词袋模型、TF-IDF 和词嵌入(如Word2Vec、GloVe)。
  • 模型训练:使用监督学习算法,如逻辑回归、支持向量机、递归神经网络 (RNN) 或者长短期记忆网络 (LSTM) 来分类文本情感。
  • 模型部署:将训练好的模型部署到生产环境,在本例中是在浏览器中使用TensorFlow.js。

2.使用的方法

  • 预训练模型:可以使用预训练的模型,例如使用BERT或其他Transformer模型进行情感分类。
  • 自定义模型:也可以从头开始训练一个简单的模型,例如使用LSTM进行文本分类。

二、技术栈

  • 前端:HTML, CSS, JavaScript
  • 后端(可选):Node.js + Express
  • 机器学习库:TensorFlow.js
  • 模型训练:TensorFlow.js 或 TensorFlow (Python) 进行模型训练,然后转换为TensorFlow.js格式

三、架构设计

  • 模型训练:在服务器端或本地训练一个简单的情感分析模型。
  • 模型部署:将模型导出为TensorFlow.js格式,并通过HTTP服务提供给客户端。
  • 前端应用:用户输入文本,前端调用TensorFlow.js API进行预测,并显示结果。

四、示例代码

在这个示例中,我们将使用一个简单的LSTM模型来进行情感分析。首先,我们需要创建一个简单的模型并在服务器端训练它,然后将其转换为TensorFlow.js格式,并部署到一个简单的前端应用中。

4.1 训练模型 (Python)

首先,我们需要在Python环境中训练一个模型。这里我们假设已经有一个预处理过的数据集 sentiment_data.csv,其中包含两列:textlabel(0表示负面,1表示正面)。

import tensorflow as tf
from tensorflow.keras.preprocessing.text import Tokenizer
from tensorflow.keras.preprocessing.sequence import pad_sequences
import pandas as pd# 加载数据
data = pd.read_csv('sentiment_data.csv')
texts = data['text'].values
labels = data['label'].values# 分词器
tokenizer = Tokenizer(num_words=10000, oov_token="<OOV>")
tokenizer.fit_on_texts(texts)
sequences = tokenizer.texts_to_sequences(texts)# 序列填充
padded_sequences = pad_sequences(sequences, padding='post', maxlen=128)# 划分数据集
X_train, X_test, y_train, y_test = train_test_split(padded_sequences, labels, test_size=0.2)# 定义模型
model = tf.keras.Sequential([tf.keras.layers.Embedding(10000, 16, input_length=128),tf.keras.layers.LSTM(64, return_sequences=True),tf.keras.layers.LSTM(32),tf.keras.layers.Dense(1, activation='sigmoid')
])# 编译模型
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])# 训练模型
model.fit(X_train, y_train, epochs=10, validation_data=(X_test, y_test), verbose=2)# 导出模型
model.save('sentiment_model.h5')

4.2 转换模型到TensorFlow.js

使用TensorFlow.js Converter将模型转换为TensorFlow.js格式。

tensorflowjs_converter --input_format keras sentiment_model.h5 models/sentiment_model

4.3 前端应用

创建一个简单的HTML文件,使用TensorFlow.js进行预测。

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Sentiment Analysis with TensorFlow.js</title><script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@3.9.0/dist/tf.min.js"></script><script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/universal-sentence-encoder@4.1.0/dist/index.min.js"></script><style>body { font-family: Arial, sans-serif; }#output { margin-top: 20px; }</style>
</head>
<body><h1>Sentiment Analysis Demo</h1><textarea id="inputText" rows="4" cols="50">Enter text here...</textarea><button onclick="analyzeSentiment()">Analyze Sentiment</button><div id="output"></div><script>// Load the modelconst modelUrl = 'models/sentiment_model/model.json';let model;async function loadModel() {model = await tf.loadLayersModel(modelUrl);}// Analyze the sentiment of the input textasync function analyzeSentiment() {const inputText = document.getElementById('inputText').value;const encodedText = await universalSentenceEncoder.embed(inputText);const prediction = model.predict(encodedText.expandDims());const sentiment = prediction.dataSync()[0];const outputDiv = document.getElementById('output');outputDiv.innerHTML = `Sentiment Score: ${sentiment.toFixed(2)}<br />`;if (sentiment > 0.5) {outputDiv.innerHTML += "The sentiment is positive.";} else {outputDiv.innerHTML += "The sentiment is negative.";}}// Load the model when the page loadswindow.onload = loadModel;</script>
</body>
</html>

4.4 注意事项

  • 在这个示例中,我们使用了Universal Sentence Encoder来将文本编码为向量,这简化了模型的复杂度。但在实际应用中,你可能需要使用相同的分词器和序列填充策略来确保输入的一致性。
  • 如果你的模型使用了不同的预处理步骤,你需要确保前端能够正确地复制这些步骤。
  • 这个示例假设你已经有了一定规模的标注数据集。在实际应用中,你可能需要收集和标记更多的数据。

五、完善项目

上面我们已经完成了情感分析的基本框架,接下来我们可以进一步完善这个项目,使其更加完整和实用。这包括以下几个方面:

  1. 增强前端界面:添加更多的交互元素和样式,提升用户体验。
  2. 优化模型:考虑使用更先进的模型,比如BERT,以及对模型进行微调以提高准确性。
  3. 集成API:为模型提供一个RESTful API接口,方便其他应用程序调用。
  4. 部署到服务器:将前端和后端部署到云服务器上,使其对外界可用。

1. 增强前端界面

让我们先来改进前端界面,增加一些交互元素,比如按钮、进度条和结果展示区等,以提升用户体验。

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Sentiment Analysis with TensorFlow.js</title><script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@3.9.0/dist/tf.min.js"></script><script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/universal-sentence-encoder@4.1.0/dist/index.min.js"></script><style>body { font-family: Arial, sans-serif; }#inputText { width: 100%; height: 150px; }#output { margin-top: 20px; }#progressBar { display: none; width: 100%; height: 20px; background-color: #ddd; }#progressBar .progress-bar { height: 100%; background-color: #4caf50; }</style>
</head>
<body><h1>Sentiment Analysis Demo</h1><textarea id="inputText" placeholder="Enter text here..."></textarea><button onclick="analyzeSentiment()">Analyze Sentiment</button><div id="progressBar"><div class="progress-bar"></div></div><div id="output"></div><script>// Load the modelconst modelUrl = 'models/sentiment_model/model.json';let model;async function loadModel() {model = await tf.loadLayersModel(modelUrl);}// Analyze the sentiment of the input textasync function analyzeSentiment() {const inputText = document.getElementById('inputText').value.trim();if (!inputText) {alert("Please enter some text to analyze.");return;}showProgressBar();const encodedText = await universalSentenceEncoder.embed(inputText);const prediction = model.predict(encodedText.expandDims());const sentiment = prediction.dataSync()[0];hideProgressBar();const outputDiv = document.getElementById('output');outputDiv.innerHTML = `Sentiment Score: ${sentiment.toFixed(2)}<br />`;if (sentiment > 0.5) {outputDiv.innerHTML += "The sentiment is positive.";} else {outputDiv.innerHTML += "The sentiment is negative.";}}function showProgressBar() {const progressBar = document.getElementById('progressBar');const progress = progressBar.querySelector('.progress-bar');progressBar.style.display = 'block';progress.style.width = '0%';const intervalId = setInterval(() => {let width = parseFloat(progress.style.width);if (width >= 100) {clearInterval(intervalId);progress.style.width = '100%';setTimeout(() => {hideProgressBar();}, 500);} else {progress.style.width = `${width + 10}%`;}}, 50);}function hideProgressBar() {const progressBar = document.getElementById('progressBar');progressBar.style.display = 'none';}// Load the model when the page loadswindow.onload = loadModel;</script>
</body>
</html>

2. 优化模型

我们可以考虑使用更先进的模型,比如BERT。BERT是一个基于Transformer的预训练模型,它在多种自然语言处理任务上取得了非常好的效果。这里我们使用TensorFlow.js的@tensorflow-models/bert库来加载一个预训练的BERT模型,并进行微调。

2.1 更新模型训练代码 (Python)

由于BERT模型的训练较为复杂,我们在这里只提供一个概览。你可以在Python环境中训练一个基于BERT的模型,并将其转换为TensorFlow.js格式。

import tensorflow as tf
import tensorflow_hub as hub
import tensorflow_text as text
from official.nlp import optimization  # to create AdamW optimizer
import tensorflow_datasets as tfds
import os# Load BERT model and tokenizer
bert_preprocess_model = hub.KerasLayer("https://tfhub.dev/tensorflow/bert_en_uncased_preprocess/3")
bert_encoder = hub.KerasLayer("https://tfhub.dev/tensorflow/bert_en_uncased_L-12_H-768_A-12/4")# Define model architecture
def create_model():text_input = tf.keras.layers.Input(shape=(), dtype=tf.string, name='text')preprocessing_layer = hub.KerasLayer(bert_preprocess_model, name='preprocessing')encoder_inputs = preprocessing_layer(text_input)encoder = hub.KerasLayer(bert_encoder, trainable=True, name='BERT_encoder')outputs = encoder(encoder_inputs)net = outputs['pooled_output']net = tf.keras.layers.Dropout(0.1)(net)net = tf.keras.layers.Dense(1, activation=None, name='classifier')(net)return tf.keras.Model(text_input, net)# Compile the model
model = create_model()
loss = tf.keras.losses.BinaryCrossentropy(from_logits=True)
metrics = tf.metrics.BinaryAccuracy()epochs = 5
steps_per_epoch = tf.data.experimental.cardinality(list(train_data)).numpy()
num_train_steps = steps_per_epoch * epochs
num_warmup_steps = int(0.1*num_train_steps)optimizer = optimization.create_optimizer(init_lr=3e-5,num_train_steps=num_train_steps,num_warmup_steps=num_warmup_steps,optimizer_type='adamw')model.compile(optimizer=optimizer,loss=loss,metrics=metrics)# Train the model
model.fit(x=train_data,y=train_labels,validation_data=(val_data, val_labels),epochs=epochs)# Save the model
model.save('sentiment_bert_model.h5')
2.2 转换模型到TensorFlow.js

使用TensorFlow.js Converter将模型转换为TensorFlow.js格式。

tensorflowjs_converter --input_format keras sentiment_bert_model.h5 models/sentiment_bert_model
2.3 更新前端应用

更新前端应用以使用BERT模型进行预测。

<!DOCTYPE html>
<html>
<head><meta charset="utf-8"><title>Sentiment Analysis with TensorFlow.js (BERT)</title><script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@3.9.0/dist/tf.min.js"></script><script src="https://cdn.jsdelivr.net/npm/@tensorflow-models/bert@1.0.0/dist/index.min.js"></script><style>/* ... existing styles ... */</style>
</head>
<body><!-- ... existing HTML elements ... --><script>// Load the modelconst modelUrl = 'models/sentiment_bert_model/model.json';let model;async function loadModel() {model = await tf.loadLayersModel(modelUrl);}// Analyze the sentiment of the input textasync function analyzeSentiment() {const inputText = document.getElementById('inputText').value.trim();if (!inputText) {alert("Please enter some text to analyze.");return;}showProgressBar();// Use BERT to encode the input textconst encoder = new BertEncoder('uncased_L-12_H-768_A-12');const encodedText = await encoder.encode(inputText);const prediction = model.predict(encodedText);const sentiment = prediction.dataSync()[0];hideProgressBar();const outputDiv = document.getElementById('output');outputDiv.innerHTML = `Sentiment Score: ${sentiment.toFixed(2)}<br />`;if (sentiment > 0.5) {outputDiv.innerHTML += "The sentiment is positive.";} else {outputDiv.innerHTML += "The sentiment is negative.";}}// ... existing functions ...// Load the model when the page loadswindow.onload = loadModel;</script>
</body>
</html>

3. 集成API

为了让其他应用程序能够调用情感分析模型,我们可以创建一个RESTful API。

3.1 创建API (Node.js + Express)
const express = require('express');
const bodyParser = require('body-parser');
const tf = require('@tensorflow/tfjs-node');
const { BertEncoder } = require('@tensorflow-models/bert');const app = express();
app.use(bodyParser.json());// Load the model
let model;async function loadModel() {model = await tf.loadLayersModel('file://./models/sentiment_bert_model/model.json');
}loadModel().then(() => {console.log('Model loaded successfully.');
});// Analyze sentiment endpoint
app.post('/analyze', async (req, res) => {const { text } = req.body;if (!text) {return res.status(400).send({ error: 'Missing text' });}const encoder = new BertEncoder('uncased_L-12_H-768_A-12');const encodedText = await encoder.encode(text);const prediction = model.predict(encodedText);const sentiment = prediction.dataSync()[0];res.json({ sentimentScore: sentiment, isPositive: sentiment > 0.5 });
});// Start the server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {console.log(`Server is running on port ${PORT}`);
});

4. 部署到服务器

你可以将前端和后端分别部署到云服务器上,例如使用Heroku或AWS。这里就不详细展开部署过程了,但你可以参考各个云服务商的文档来进行部署。

通过这些步骤,你将能够构建一个功能完整的情感分析应用,其中包括了用户友好的前端界面、先进的BERT模型以及一个可被其他应用程序调用的API。希望这个项目对你有所帮助!如果有任何疑问或需要进一步的帮助,请随时告诉我。

相关文章:

【人工智能】利用TensorFlow.js在浏览器中实现一个基本的情感分析系统

使用TensorFlow.js在浏览器中进行情感分析是一个非常实用的应用场景。TensorFlow.js 是一个用于在JavaScript环境中训练和部署机器学习模型的库&#xff0c;使得开发者能够在客户端直接运行复杂的机器学习任务。对于情感分析&#xff0c;我们可以使用预先训练好的模型来识别文本…...

Python——扩展数据类型

Python 的扩展数据类型是对内置数据类型的增强&#xff0c;旨在解决特定需求&#xff0c;提供更高级的功能。我们来看一些常见的扩展数据类型及其原理、用途&#xff0c;并通过示例逐步讲解。 1. collections.namedtuple namedtuple 是增强的元组&#xff0c;允许用名称访问元…...

JavaScript 详解——Vue基础

第一章 JavaScript简介 为什么学习javascript &#xff1f; JavaScript 是全球最流行的编程语言。 JavaScript 是属于 Web 的编程语言。 JavaScript 是 web 开发者必学的三种语言之一&#xff1a; HTML 定义网页的内容 CSS 规定网页的布局 JavaScript 对网页行为进行编程 …...

机械行业数字化生产供应链产品解决方案(十二)

我们为机械行业提供的数字化生产供应链解决方案通过集成物联网、人工智能和大数据技术&#xff0c;打造了一套智能化的生产和供应链管理系统&#xff0c;实现了从设计、生产到物流的全程数字化、智能化。该系统通过实时数据采集与分析&#xff0c;优化生产计划和资源配置&#…...

Git——命令集合

Git命令集合 1. 基本操作 1.1 创建版本库 初始化本地仓库&#xff1a;git init添加文件到仓库&#xff1a;git add | git add file file2… | git add.提交文件到本地仓库&#xff1a;git commit -m “message” 1.2 版本回退 查看状态&#xff1a; git status查看全部修改…...

python 数据可视化折线图练习(下:代码演示)

根据上篇对三国疫情情况数据的罗列&#xff0c;构建折线图完成数据展示。&#xff08;示例如下&#xff09; 接下来是具体代码演示 import json from pyecharts.charts import Line from pyecharts.options import TitleOpts , LegendOpts , ToolboxOpts ,VisualMapOpts , T…...

深入探索 Go 1.18 的 debug/buildinfo:构建信息的获取与应用

标题&#xff1a;深入探索 Go 1.18 的 debug/buildinfo&#xff1a;构建信息的获取与应用 引言 Go 语言自 1.18 版本起&#xff0c;引入了对构建信息的标准化处理&#xff0c;这一特性极大地简化了获取程序构建信息的过程。debug/buildinfo 包提供了访问 Go 二进制文件中嵌入…...

Nios II的BSP Editor

1.菜单打开BSP Editor &#xff08;1&#xff09; &#xff08;2&#xff09; &#xff08;3&#xff09; 项目文件夹 -> software文件夹 -> ... _bsp文件夹 -> settings.bsp文件 2.文件打开BSP Editor 选中项目文件&#xff0c;右键&#xff0c;Nios II -> …...

Android-自适用高度的ViewPager

需求 在项目中&#xff0c;我们常常遇到需要动态调整 ViewPager 的高度&#xff0c;以适应其内容大小的需求。默认情况下&#xff0c;ViewPager 的高度是固定的&#xff0c;无法根据每个页面的内容高度进行调整。这会导致在内容高度不一致时&#xff0c;出现不必要的空白区域或…...

代码随想录day38|| 322零钱兑换 279完全平方数 139单词拆分

322零钱兑换 力扣题目链接 题目描述&#xff1a; 给你一个整数数组 coins &#xff0c;表示不同面额的硬币&#xff1b;以及一个整数 amount &#xff0c;表示总金额。 计算并返回可以凑成总金额所需的 最少的硬币个数 。如果没有任何一种硬币组合能组成总金额&#xff0c…...

Cesium天空盒子(Skybox)制作(js代码)和显示

介绍 在Cesium中&#xff0c;星空背景是通过天空盒子方式&#xff08;6张图片&#xff09;来显示的&#xff0c;原生的图片分辨率太低&#xff0c;本项目用于生成天空盒子的6张图片。最终生成的6个图片大小约为500kb(每个)&#xff0c;格式为jpg&#xff0c;总共的恒星数目约为…...

JAVA中的缓冲流BufferedInputStream

在Java中&#xff0c;BufferedInputStream 是一种用于包装其他输入流&#xff08;如 FileInputStream&#xff09;的过滤流。它通过内部缓冲区机制提高了输入流处理的效率。使用缓冲流可以减少读取数据的次数&#xff0c;因为每次从输入流读取数据时&#xff0c;BufferedInputS…...

WindowContainerTransaction类详解(一)

1、WindowContainerTransaction是什么&#xff1a; windowContainerTransaction类的对象是用来存储对windowContainer的修改的一个集合&#xff0c;windowContainer。因为应用侧是无法直接操作windowContainer的&#xff0c;如果应用侧需要修改windowContainer的话&#xff0c…...

安装NFS扩展

#添加helm源 helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner #创建个namespace(可选,主要是为了查看资源方便) kubectl create ns nfs-sc-default #使用helm安装(10.1.129.86为NFS地址,/home/data/nfs…...

计算机网络——运输层(进程之间的通信、运输层端口,UDP与TCP、TCP详解)

运输层协议概述 进程之间的通信 运输层向它上面的应用层提供通信服务。 当网络边缘部分的两台主机使用网络核心部分的功能进行端到端的通信时&#xff0c;都要使用协议栈中的运输层&#xff1b;而网络核心部分中的路由器在转发分组时只用到下三层的功能。 Q1&#xff1a;我们…...

代码随想录算法训练营第一天 | 二分查找

文章目录 Leetcode704 二分查找二分法的使用前提:区间选择其他注意事项 Leetcode27 移除元素解题思路:优化思路 Leetcode704 二分查找 链接&#xff1a;https://leetcode.cn/problems/binary-search/ 代码随想录: https://programmercarl.com/ 时间复杂度: O(logN) 空间复杂度:…...

python相关知识

1、注释 共有三种&#xff1a;#、 、””” ””” 2、数据类型 整数、浮点、字符串、布尔、列表、元组、集合、字典 num1 666、num2 3.14、t1 True、t2 False、 列表&#xff1a;list [1,2,3,4] 元组&#xff1a;tuple (11,aaa,ddd,3) 字典&#xff1a;dict {li…...

Visual Studio 2022 LNK2001无法解析的外部符号 _wcscat_s 问题记录

ANSI C程序中&#xff0c;用到了wcsrchr、wcsncpy_s、wcscat_s、wcscpy_s等几个字符串函数&#xff0c;但是编译时提示&#xff1a; 错误 LNK2001 无法解析的外部符号 _wcscat_s 查了挺多帖子&#xff0c;没有解决。 https://bbs.csdn.net/topics/250012844 解决VS编译…...

Java高并发处理机制

高并发处理的思路&#xff1a; 扩容&#xff1a;水平扩容、垂直扩容缓存&#xff1a;将基础的数据放入缓存进行处理使用SpringCloud的注册中心&#xff0c;分服务注册到同一个注册中心&#xff0c;服务器检测使用Spring的熔断操作&#xff0c;检测服务器的心跳那个正常随机跳转…...

7 数据存储单位,整型、浮点型、字符型、布尔型数据类型,sizeof 运算符

目录 1 数据类型的分类 2 数据存储单位 2.1 位 2.2 字节 2.3 其余单位 3 整数类型 3.1 基本介绍 3.2 整型的类型 3.2.1 整数类型多样性的原因 3.2.2 整型类型之间的相对大小关系 3.3 整型注意事项 3.4 字面量后缀 3.5 格式占位符 3.6 案例&#xff1a;声明并输出…...

网络编程(Modbus进阶)

思维导图 Modbus RTU&#xff08;先学一点理论&#xff09; 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议&#xff0c;由 Modicon 公司&#xff08;现施耐德电气&#xff09;于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

Vue记事本应用实现教程

文章目录 1. 项目介绍2. 开发环境准备3. 设计应用界面4. 创建Vue实例和数据模型5. 实现记事本功能5.1 添加新记事项5.2 删除记事项5.3 清空所有记事 6. 添加样式7. 功能扩展&#xff1a;显示创建时间8. 功能扩展&#xff1a;记事项搜索9. 完整代码10. Vue知识点解析10.1 数据绑…...

大话软工笔记—需求分析概述

需求分析&#xff0c;就是要对需求调研收集到的资料信息逐个地进行拆分、研究&#xff0c;从大量的不确定“需求”中确定出哪些需求最终要转换为确定的“功能需求”。 需求分析的作用非常重要&#xff0c;后续设计的依据主要来自于需求分析的成果&#xff0c;包括: 项目的目的…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

ardupilot 开发环境eclipse 中import 缺少C++

目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...